1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides a class for OpenMP runtime code generation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGOpenMPRuntime.h" 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/AST/APValue.h" 19 #include "clang/AST/Attr.h" 20 #include "clang/AST/Decl.h" 21 #include "clang/AST/OpenMPClause.h" 22 #include "clang/AST/StmtOpenMP.h" 23 #include "clang/AST/StmtVisitor.h" 24 #include "clang/Basic/BitmaskEnum.h" 25 #include "clang/Basic/FileManager.h" 26 #include "clang/Basic/OpenMPKinds.h" 27 #include "clang/Basic/SourceManager.h" 28 #include "clang/CodeGen/ConstantInitBuilder.h" 29 #include "llvm/ADT/ArrayRef.h" 30 #include "llvm/ADT/SetOperations.h" 31 #include "llvm/ADT/StringExtras.h" 32 #include "llvm/Bitcode/BitcodeReader.h" 33 #include "llvm/IR/Constants.h" 34 #include "llvm/IR/DerivedTypes.h" 35 #include "llvm/IR/GlobalValue.h" 36 #include "llvm/IR/Value.h" 37 #include "llvm/Support/AtomicOrdering.h" 38 #include "llvm/Support/Format.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include <cassert> 41 #include <numeric> 42 43 using namespace clang; 44 using namespace CodeGen; 45 using namespace llvm::omp; 46 47 namespace { 48 /// Base class for handling code generation inside OpenMP regions. 49 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 50 public: 51 /// Kinds of OpenMP regions used in codegen. 52 enum CGOpenMPRegionKind { 53 /// Region with outlined function for standalone 'parallel' 54 /// directive. 55 ParallelOutlinedRegion, 56 /// Region with outlined function for standalone 'task' directive. 57 TaskOutlinedRegion, 58 /// Region for constructs that do not require function outlining, 59 /// like 'for', 'sections', 'atomic' etc. directives. 60 InlinedRegion, 61 /// Region with outlined function for standalone 'target' directive. 62 TargetRegion, 63 }; 64 65 CGOpenMPRegionInfo(const CapturedStmt &CS, 66 const CGOpenMPRegionKind RegionKind, 67 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 68 bool HasCancel) 69 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 70 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 71 72 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 73 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 74 bool HasCancel) 75 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 76 Kind(Kind), HasCancel(HasCancel) {} 77 78 /// Get a variable or parameter for storing global thread id 79 /// inside OpenMP construct. 80 virtual const VarDecl *getThreadIDVariable() const = 0; 81 82 /// Emit the captured statement body. 83 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 84 85 /// Get an LValue for the current ThreadID variable. 86 /// \return LValue for thread id variable. This LValue always has type int32*. 87 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 88 89 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 90 91 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 92 93 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 94 95 bool hasCancel() const { return HasCancel; } 96 97 static bool classof(const CGCapturedStmtInfo *Info) { 98 return Info->getKind() == CR_OpenMP; 99 } 100 101 ~CGOpenMPRegionInfo() override = default; 102 103 protected: 104 CGOpenMPRegionKind RegionKind; 105 RegionCodeGenTy CodeGen; 106 OpenMPDirectiveKind Kind; 107 bool HasCancel; 108 }; 109 110 /// API for captured statement code generation in OpenMP constructs. 111 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 112 public: 113 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 114 const RegionCodeGenTy &CodeGen, 115 OpenMPDirectiveKind Kind, bool HasCancel, 116 StringRef HelperName) 117 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 118 HasCancel), 119 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 120 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 121 } 122 123 /// Get a variable or parameter for storing global thread id 124 /// inside OpenMP construct. 125 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 126 127 /// Get the name of the capture helper. 128 StringRef getHelperName() const override { return HelperName; } 129 130 static bool classof(const CGCapturedStmtInfo *Info) { 131 return CGOpenMPRegionInfo::classof(Info) && 132 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 133 ParallelOutlinedRegion; 134 } 135 136 private: 137 /// A variable or parameter storing global thread id for OpenMP 138 /// constructs. 139 const VarDecl *ThreadIDVar; 140 StringRef HelperName; 141 }; 142 143 /// API for captured statement code generation in OpenMP constructs. 144 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 145 public: 146 class UntiedTaskActionTy final : public PrePostActionTy { 147 bool Untied; 148 const VarDecl *PartIDVar; 149 const RegionCodeGenTy UntiedCodeGen; 150 llvm::SwitchInst *UntiedSwitch = nullptr; 151 152 public: 153 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 154 const RegionCodeGenTy &UntiedCodeGen) 155 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 156 void Enter(CodeGenFunction &CGF) override { 157 if (Untied) { 158 // Emit task switching point. 159 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 160 CGF.GetAddrOfLocalVar(PartIDVar), 161 PartIDVar->getType()->castAs<PointerType>()); 162 llvm::Value *Res = 163 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 164 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 165 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 166 CGF.EmitBlock(DoneBB); 167 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 168 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 169 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 170 CGF.Builder.GetInsertBlock()); 171 emitUntiedSwitch(CGF); 172 } 173 } 174 void emitUntiedSwitch(CodeGenFunction &CGF) const { 175 if (Untied) { 176 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 177 CGF.GetAddrOfLocalVar(PartIDVar), 178 PartIDVar->getType()->castAs<PointerType>()); 179 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 180 PartIdLVal); 181 UntiedCodeGen(CGF); 182 CodeGenFunction::JumpDest CurPoint = 183 CGF.getJumpDestInCurrentScope(".untied.next."); 184 CGF.EmitBranch(CGF.ReturnBlock.getBlock()); 185 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 186 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 187 CGF.Builder.GetInsertBlock()); 188 CGF.EmitBranchThroughCleanup(CurPoint); 189 CGF.EmitBlock(CurPoint.getBlock()); 190 } 191 } 192 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 193 }; 194 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 195 const VarDecl *ThreadIDVar, 196 const RegionCodeGenTy &CodeGen, 197 OpenMPDirectiveKind Kind, bool HasCancel, 198 const UntiedTaskActionTy &Action) 199 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 200 ThreadIDVar(ThreadIDVar), Action(Action) { 201 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 202 } 203 204 /// Get a variable or parameter for storing global thread id 205 /// inside OpenMP construct. 206 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 207 208 /// Get an LValue for the current ThreadID variable. 209 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 210 211 /// Get the name of the capture helper. 212 StringRef getHelperName() const override { return ".omp_outlined."; } 213 214 void emitUntiedSwitch(CodeGenFunction &CGF) override { 215 Action.emitUntiedSwitch(CGF); 216 } 217 218 static bool classof(const CGCapturedStmtInfo *Info) { 219 return CGOpenMPRegionInfo::classof(Info) && 220 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 221 TaskOutlinedRegion; 222 } 223 224 private: 225 /// A variable or parameter storing global thread id for OpenMP 226 /// constructs. 227 const VarDecl *ThreadIDVar; 228 /// Action for emitting code for untied tasks. 229 const UntiedTaskActionTy &Action; 230 }; 231 232 /// API for inlined captured statement code generation in OpenMP 233 /// constructs. 234 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 235 public: 236 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 237 const RegionCodeGenTy &CodeGen, 238 OpenMPDirectiveKind Kind, bool HasCancel) 239 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 240 OldCSI(OldCSI), 241 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 242 243 // Retrieve the value of the context parameter. 244 llvm::Value *getContextValue() const override { 245 if (OuterRegionInfo) 246 return OuterRegionInfo->getContextValue(); 247 llvm_unreachable("No context value for inlined OpenMP region"); 248 } 249 250 void setContextValue(llvm::Value *V) override { 251 if (OuterRegionInfo) { 252 OuterRegionInfo->setContextValue(V); 253 return; 254 } 255 llvm_unreachable("No context value for inlined OpenMP region"); 256 } 257 258 /// Lookup the captured field decl for a variable. 259 const FieldDecl *lookup(const VarDecl *VD) const override { 260 if (OuterRegionInfo) 261 return OuterRegionInfo->lookup(VD); 262 // If there is no outer outlined region,no need to lookup in a list of 263 // captured variables, we can use the original one. 264 return nullptr; 265 } 266 267 FieldDecl *getThisFieldDecl() const override { 268 if (OuterRegionInfo) 269 return OuterRegionInfo->getThisFieldDecl(); 270 return nullptr; 271 } 272 273 /// Get a variable or parameter for storing global thread id 274 /// inside OpenMP construct. 275 const VarDecl *getThreadIDVariable() const override { 276 if (OuterRegionInfo) 277 return OuterRegionInfo->getThreadIDVariable(); 278 return nullptr; 279 } 280 281 /// Get an LValue for the current ThreadID variable. 282 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 283 if (OuterRegionInfo) 284 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 285 llvm_unreachable("No LValue for inlined OpenMP construct"); 286 } 287 288 /// Get the name of the capture helper. 289 StringRef getHelperName() const override { 290 if (auto *OuterRegionInfo = getOldCSI()) 291 return OuterRegionInfo->getHelperName(); 292 llvm_unreachable("No helper name for inlined OpenMP construct"); 293 } 294 295 void emitUntiedSwitch(CodeGenFunction &CGF) override { 296 if (OuterRegionInfo) 297 OuterRegionInfo->emitUntiedSwitch(CGF); 298 } 299 300 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 301 302 static bool classof(const CGCapturedStmtInfo *Info) { 303 return CGOpenMPRegionInfo::classof(Info) && 304 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 305 } 306 307 ~CGOpenMPInlinedRegionInfo() override = default; 308 309 private: 310 /// CodeGen info about outer OpenMP region. 311 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 312 CGOpenMPRegionInfo *OuterRegionInfo; 313 }; 314 315 /// API for captured statement code generation in OpenMP target 316 /// constructs. For this captures, implicit parameters are used instead of the 317 /// captured fields. The name of the target region has to be unique in a given 318 /// application so it is provided by the client, because only the client has 319 /// the information to generate that. 320 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 321 public: 322 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 323 const RegionCodeGenTy &CodeGen, StringRef HelperName) 324 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 325 /*HasCancel=*/false), 326 HelperName(HelperName) {} 327 328 /// This is unused for target regions because each starts executing 329 /// with a single thread. 330 const VarDecl *getThreadIDVariable() const override { return nullptr; } 331 332 /// Get the name of the capture helper. 333 StringRef getHelperName() const override { return HelperName; } 334 335 static bool classof(const CGCapturedStmtInfo *Info) { 336 return CGOpenMPRegionInfo::classof(Info) && 337 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 338 } 339 340 private: 341 StringRef HelperName; 342 }; 343 344 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 345 llvm_unreachable("No codegen for expressions"); 346 } 347 /// API for generation of expressions captured in a innermost OpenMP 348 /// region. 349 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 350 public: 351 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 352 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 353 OMPD_unknown, 354 /*HasCancel=*/false), 355 PrivScope(CGF) { 356 // Make sure the globals captured in the provided statement are local by 357 // using the privatization logic. We assume the same variable is not 358 // captured more than once. 359 for (const auto &C : CS.captures()) { 360 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 361 continue; 362 363 const VarDecl *VD = C.getCapturedVar(); 364 if (VD->isLocalVarDeclOrParm()) 365 continue; 366 367 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 368 /*RefersToEnclosingVariableOrCapture=*/false, 369 VD->getType().getNonReferenceType(), VK_LValue, 370 C.getLocation()); 371 PrivScope.addPrivate( 372 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 373 } 374 (void)PrivScope.Privatize(); 375 } 376 377 /// Lookup the captured field decl for a variable. 378 const FieldDecl *lookup(const VarDecl *VD) const override { 379 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 380 return FD; 381 return nullptr; 382 } 383 384 /// Emit the captured statement body. 385 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 386 llvm_unreachable("No body for expressions"); 387 } 388 389 /// Get a variable or parameter for storing global thread id 390 /// inside OpenMP construct. 391 const VarDecl *getThreadIDVariable() const override { 392 llvm_unreachable("No thread id for expressions"); 393 } 394 395 /// Get the name of the capture helper. 396 StringRef getHelperName() const override { 397 llvm_unreachable("No helper name for expressions"); 398 } 399 400 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 401 402 private: 403 /// Private scope to capture global variables. 404 CodeGenFunction::OMPPrivateScope PrivScope; 405 }; 406 407 /// RAII for emitting code of OpenMP constructs. 408 class InlinedOpenMPRegionRAII { 409 CodeGenFunction &CGF; 410 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 411 FieldDecl *LambdaThisCaptureField = nullptr; 412 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 413 bool NoInheritance = false; 414 415 public: 416 /// Constructs region for combined constructs. 417 /// \param CodeGen Code generation sequence for combined directives. Includes 418 /// a list of functions used for code generation of implicitly inlined 419 /// regions. 420 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 421 OpenMPDirectiveKind Kind, bool HasCancel, 422 bool NoInheritance = true) 423 : CGF(CGF), NoInheritance(NoInheritance) { 424 // Start emission for the construct. 425 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 426 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 427 if (NoInheritance) { 428 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 429 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 430 CGF.LambdaThisCaptureField = nullptr; 431 BlockInfo = CGF.BlockInfo; 432 CGF.BlockInfo = nullptr; 433 } 434 } 435 436 ~InlinedOpenMPRegionRAII() { 437 // Restore original CapturedStmtInfo only if we're done with code emission. 438 auto *OldCSI = 439 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 440 delete CGF.CapturedStmtInfo; 441 CGF.CapturedStmtInfo = OldCSI; 442 if (NoInheritance) { 443 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 444 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 445 CGF.BlockInfo = BlockInfo; 446 } 447 } 448 }; 449 450 /// Values for bit flags used in the ident_t to describe the fields. 451 /// All enumeric elements are named and described in accordance with the code 452 /// from https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h 453 enum OpenMPLocationFlags : unsigned { 454 /// Use trampoline for internal microtask. 455 OMP_IDENT_IMD = 0x01, 456 /// Use c-style ident structure. 457 OMP_IDENT_KMPC = 0x02, 458 /// Atomic reduction option for kmpc_reduce. 459 OMP_ATOMIC_REDUCE = 0x10, 460 /// Explicit 'barrier' directive. 461 OMP_IDENT_BARRIER_EXPL = 0x20, 462 /// Implicit barrier in code. 463 OMP_IDENT_BARRIER_IMPL = 0x40, 464 /// Implicit barrier in 'for' directive. 465 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 466 /// Implicit barrier in 'sections' directive. 467 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 468 /// Implicit barrier in 'single' directive. 469 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 470 /// Call of __kmp_for_static_init for static loop. 471 OMP_IDENT_WORK_LOOP = 0x200, 472 /// Call of __kmp_for_static_init for sections. 473 OMP_IDENT_WORK_SECTIONS = 0x400, 474 /// Call of __kmp_for_static_init for distribute. 475 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 476 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 477 }; 478 479 namespace { 480 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 481 /// Values for bit flags for marking which requires clauses have been used. 482 enum OpenMPOffloadingRequiresDirFlags : int64_t { 483 /// flag undefined. 484 OMP_REQ_UNDEFINED = 0x000, 485 /// no requires clause present. 486 OMP_REQ_NONE = 0x001, 487 /// reverse_offload clause. 488 OMP_REQ_REVERSE_OFFLOAD = 0x002, 489 /// unified_address clause. 490 OMP_REQ_UNIFIED_ADDRESS = 0x004, 491 /// unified_shared_memory clause. 492 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 493 /// dynamic_allocators clause. 494 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 495 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 496 }; 497 498 enum OpenMPOffloadingReservedDeviceIDs { 499 /// Device ID if the device was not defined, runtime should get it 500 /// from environment variables in the spec. 501 OMP_DEVICEID_UNDEF = -1, 502 }; 503 } // anonymous namespace 504 505 /// Describes ident structure that describes a source location. 506 /// All descriptions are taken from 507 /// https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h 508 /// Original structure: 509 /// typedef struct ident { 510 /// kmp_int32 reserved_1; /**< might be used in Fortran; 511 /// see above */ 512 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 513 /// KMP_IDENT_KMPC identifies this union 514 /// member */ 515 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 516 /// see above */ 517 ///#if USE_ITT_BUILD 518 /// /* but currently used for storing 519 /// region-specific ITT */ 520 /// /* contextual information. */ 521 ///#endif /* USE_ITT_BUILD */ 522 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 523 /// C++ */ 524 /// char const *psource; /**< String describing the source location. 525 /// The string is composed of semi-colon separated 526 // fields which describe the source file, 527 /// the function and a pair of line numbers that 528 /// delimit the construct. 529 /// */ 530 /// } ident_t; 531 enum IdentFieldIndex { 532 /// might be used in Fortran 533 IdentField_Reserved_1, 534 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 535 IdentField_Flags, 536 /// Not really used in Fortran any more 537 IdentField_Reserved_2, 538 /// Source[4] in Fortran, do not use for C++ 539 IdentField_Reserved_3, 540 /// String describing the source location. The string is composed of 541 /// semi-colon separated fields which describe the source file, the function 542 /// and a pair of line numbers that delimit the construct. 543 IdentField_PSource 544 }; 545 546 /// Schedule types for 'omp for' loops (these enumerators are taken from 547 /// the enum sched_type in kmp.h). 548 enum OpenMPSchedType { 549 /// Lower bound for default (unordered) versions. 550 OMP_sch_lower = 32, 551 OMP_sch_static_chunked = 33, 552 OMP_sch_static = 34, 553 OMP_sch_dynamic_chunked = 35, 554 OMP_sch_guided_chunked = 36, 555 OMP_sch_runtime = 37, 556 OMP_sch_auto = 38, 557 /// static with chunk adjustment (e.g., simd) 558 OMP_sch_static_balanced_chunked = 45, 559 /// Lower bound for 'ordered' versions. 560 OMP_ord_lower = 64, 561 OMP_ord_static_chunked = 65, 562 OMP_ord_static = 66, 563 OMP_ord_dynamic_chunked = 67, 564 OMP_ord_guided_chunked = 68, 565 OMP_ord_runtime = 69, 566 OMP_ord_auto = 70, 567 OMP_sch_default = OMP_sch_static, 568 /// dist_schedule types 569 OMP_dist_sch_static_chunked = 91, 570 OMP_dist_sch_static = 92, 571 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 572 /// Set if the monotonic schedule modifier was present. 573 OMP_sch_modifier_monotonic = (1 << 29), 574 /// Set if the nonmonotonic schedule modifier was present. 575 OMP_sch_modifier_nonmonotonic = (1 << 30), 576 }; 577 578 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 579 /// region. 580 class CleanupTy final : public EHScopeStack::Cleanup { 581 PrePostActionTy *Action; 582 583 public: 584 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 585 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 586 if (!CGF.HaveInsertPoint()) 587 return; 588 Action->Exit(CGF); 589 } 590 }; 591 592 } // anonymous namespace 593 594 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 595 CodeGenFunction::RunCleanupsScope Scope(CGF); 596 if (PrePostAction) { 597 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 598 Callback(CodeGen, CGF, *PrePostAction); 599 } else { 600 PrePostActionTy Action; 601 Callback(CodeGen, CGF, Action); 602 } 603 } 604 605 /// Check if the combiner is a call to UDR combiner and if it is so return the 606 /// UDR decl used for reduction. 607 static const OMPDeclareReductionDecl * 608 getReductionInit(const Expr *ReductionOp) { 609 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 610 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 611 if (const auto *DRE = 612 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 613 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 614 return DRD; 615 return nullptr; 616 } 617 618 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 619 const OMPDeclareReductionDecl *DRD, 620 const Expr *InitOp, 621 Address Private, Address Original, 622 QualType Ty) { 623 if (DRD->getInitializer()) { 624 std::pair<llvm::Function *, llvm::Function *> Reduction = 625 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 626 const auto *CE = cast<CallExpr>(InitOp); 627 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 628 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 629 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 630 const auto *LHSDRE = 631 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 632 const auto *RHSDRE = 633 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 634 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 635 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 636 [=]() { return Private; }); 637 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 638 [=]() { return 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 DestAddr = 691 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 692 if (DRD) 693 SrcAddr = 694 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 695 696 llvm::Value *SrcBegin = nullptr; 697 if (DRD) 698 SrcBegin = SrcAddr.getPointer(); 699 llvm::Value *DestBegin = DestAddr.getPointer(); 700 // Cast from pointer to array type to pointer to single element. 701 llvm::Value *DestEnd = 702 CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements); 703 // The basic structure here is a while-do loop. 704 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 705 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 706 llvm::Value *IsEmpty = 707 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 708 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 709 710 // Enter the loop body, making that address the current address. 711 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 712 CGF.EmitBlock(BodyBB); 713 714 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 715 716 llvm::PHINode *SrcElementPHI = nullptr; 717 Address SrcElementCurrent = Address::invalid(); 718 if (DRD) { 719 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 720 "omp.arraycpy.srcElementPast"); 721 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 722 SrcElementCurrent = 723 Address(SrcElementPHI, 724 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 725 } 726 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 727 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 728 DestElementPHI->addIncoming(DestBegin, EntryBB); 729 Address DestElementCurrent = 730 Address(DestElementPHI, 731 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 732 733 // Emit copy. 734 { 735 CodeGenFunction::RunCleanupsScope InitScope(CGF); 736 if (EmitDeclareReductionInit) { 737 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 738 SrcElementCurrent, ElementTy); 739 } else 740 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 741 /*IsInitializer=*/false); 742 } 743 744 if (DRD) { 745 // Shift the address forward by one element. 746 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 747 SrcAddr.getElementType(), SrcElementPHI, /*Idx0=*/1, 748 "omp.arraycpy.dest.element"); 749 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 750 } 751 752 // Shift the address forward by one element. 753 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 754 DestAddr.getElementType(), DestElementPHI, /*Idx0=*/1, 755 "omp.arraycpy.dest.element"); 756 // Check whether we've reached the end. 757 llvm::Value *Done = 758 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 759 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 760 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 761 762 // Done. 763 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 764 } 765 766 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 767 return CGF.EmitOMPSharedLValue(E); 768 } 769 770 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 771 const Expr *E) { 772 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 773 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 774 return LValue(); 775 } 776 777 void ReductionCodeGen::emitAggregateInitialization( 778 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 779 const OMPDeclareReductionDecl *DRD) { 780 // Emit VarDecl with copy init for arrays. 781 // Get the address of the original variable captured in current 782 // captured region. 783 const auto *PrivateVD = 784 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 785 bool EmitDeclareReductionInit = 786 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 787 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 788 EmitDeclareReductionInit, 789 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 790 : PrivateVD->getInit(), 791 DRD, SharedLVal.getAddress(CGF)); 792 } 793 794 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 795 ArrayRef<const Expr *> Origs, 796 ArrayRef<const Expr *> Privates, 797 ArrayRef<const Expr *> ReductionOps) { 798 ClausesData.reserve(Shareds.size()); 799 SharedAddresses.reserve(Shareds.size()); 800 Sizes.reserve(Shareds.size()); 801 BaseDecls.reserve(Shareds.size()); 802 const auto *IOrig = Origs.begin(); 803 const auto *IPriv = Privates.begin(); 804 const auto *IRed = ReductionOps.begin(); 805 for (const Expr *Ref : Shareds) { 806 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed); 807 std::advance(IOrig, 1); 808 std::advance(IPriv, 1); 809 std::advance(IRed, 1); 810 } 811 } 812 813 void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) { 814 assert(SharedAddresses.size() == N && OrigAddresses.size() == N && 815 "Number of generated lvalues must be exactly N."); 816 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared); 817 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared); 818 SharedAddresses.emplace_back(First, Second); 819 if (ClausesData[N].Shared == ClausesData[N].Ref) { 820 OrigAddresses.emplace_back(First, Second); 821 } else { 822 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 823 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 824 OrigAddresses.emplace_back(First, Second); 825 } 826 } 827 828 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 829 const auto *PrivateVD = 830 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 831 QualType PrivateType = PrivateVD->getType(); 832 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 833 if (!PrivateType->isVariablyModifiedType()) { 834 Sizes.emplace_back( 835 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()), 836 nullptr); 837 return; 838 } 839 llvm::Value *Size; 840 llvm::Value *SizeInChars; 841 auto *ElemType = 842 cast<llvm::PointerType>(OrigAddresses[N].first.getPointer(CGF)->getType()) 843 ->getElementType(); 844 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 845 if (AsArraySection) { 846 Size = CGF.Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF), 847 OrigAddresses[N].first.getPointer(CGF)); 848 Size = CGF.Builder.CreateNUWAdd( 849 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 850 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 851 } else { 852 SizeInChars = 853 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()); 854 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 855 } 856 Sizes.emplace_back(SizeInChars, Size); 857 CodeGenFunction::OpaqueValueMapping OpaqueMap( 858 CGF, 859 cast<OpaqueValueExpr>( 860 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 861 RValue::get(Size)); 862 CGF.EmitVariablyModifiedType(PrivateType); 863 } 864 865 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 866 llvm::Value *Size) { 867 const auto *PrivateVD = 868 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 869 QualType PrivateType = PrivateVD->getType(); 870 if (!PrivateType->isVariablyModifiedType()) { 871 assert(!Size && !Sizes[N].second && 872 "Size should be nullptr for non-variably modified reduction " 873 "items."); 874 return; 875 } 876 CodeGenFunction::OpaqueValueMapping OpaqueMap( 877 CGF, 878 cast<OpaqueValueExpr>( 879 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 880 RValue::get(Size)); 881 CGF.EmitVariablyModifiedType(PrivateType); 882 } 883 884 void ReductionCodeGen::emitInitialization( 885 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 886 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 887 assert(SharedAddresses.size() > N && "No variable was generated"); 888 const auto *PrivateVD = 889 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 890 const OMPDeclareReductionDecl *DRD = 891 getReductionInit(ClausesData[N].ReductionOp); 892 QualType PrivateType = PrivateVD->getType(); 893 PrivateAddr = CGF.Builder.CreateElementBitCast( 894 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 895 QualType SharedType = SharedAddresses[N].first.getType(); 896 SharedLVal = CGF.MakeAddrLValue( 897 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 898 CGF.ConvertTypeForMem(SharedType)), 899 SharedType, SharedAddresses[N].first.getBaseInfo(), 900 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 901 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 902 if (DRD && DRD->getInitializer()) 903 (void)DefaultInit(CGF); 904 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 905 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 906 (void)DefaultInit(CGF); 907 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 908 PrivateAddr, SharedLVal.getAddress(CGF), 909 SharedLVal.getType()); 910 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 911 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 912 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 913 PrivateVD->getType().getQualifiers(), 914 /*IsInitializer=*/false); 915 } 916 } 917 918 bool ReductionCodeGen::needCleanups(unsigned N) { 919 const auto *PrivateVD = 920 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 921 QualType PrivateType = PrivateVD->getType(); 922 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 923 return DTorKind != QualType::DK_none; 924 } 925 926 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 927 Address PrivateAddr) { 928 const auto *PrivateVD = 929 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 930 QualType PrivateType = PrivateVD->getType(); 931 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 932 if (needCleanups(N)) { 933 PrivateAddr = CGF.Builder.CreateElementBitCast( 934 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 935 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 936 } 937 } 938 939 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 940 LValue BaseLV) { 941 BaseTy = BaseTy.getNonReferenceType(); 942 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 943 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 944 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 945 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 946 } else { 947 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 948 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 949 } 950 BaseTy = BaseTy->getPointeeType(); 951 } 952 return CGF.MakeAddrLValue( 953 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 954 CGF.ConvertTypeForMem(ElTy)), 955 BaseLV.getType(), BaseLV.getBaseInfo(), 956 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 957 } 958 959 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 960 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 961 llvm::Value *Addr) { 962 Address Tmp = Address::invalid(); 963 Address TopTmp = Address::invalid(); 964 Address MostTopTmp = Address::invalid(); 965 BaseTy = BaseTy.getNonReferenceType(); 966 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 967 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 968 Tmp = CGF.CreateMemTemp(BaseTy); 969 if (TopTmp.isValid()) 970 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 971 else 972 MostTopTmp = Tmp; 973 TopTmp = Tmp; 974 BaseTy = BaseTy->getPointeeType(); 975 } 976 llvm::Type *Ty = BaseLVType; 977 if (Tmp.isValid()) 978 Ty = Tmp.getElementType(); 979 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 980 if (Tmp.isValid()) { 981 CGF.Builder.CreateStore(Addr, Tmp); 982 return MostTopTmp; 983 } 984 return Address(Addr, BaseLVAlignment); 985 } 986 987 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 988 const VarDecl *OrigVD = nullptr; 989 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 990 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 991 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 992 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 993 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 994 Base = TempASE->getBase()->IgnoreParenImpCasts(); 995 DE = cast<DeclRefExpr>(Base); 996 OrigVD = cast<VarDecl>(DE->getDecl()); 997 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 998 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 999 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1000 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1001 DE = cast<DeclRefExpr>(Base); 1002 OrigVD = cast<VarDecl>(DE->getDecl()); 1003 } 1004 return OrigVD; 1005 } 1006 1007 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1008 Address PrivateAddr) { 1009 const DeclRefExpr *DE; 1010 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1011 BaseDecls.emplace_back(OrigVD); 1012 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1013 LValue BaseLValue = 1014 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1015 OriginalBaseLValue); 1016 Address SharedAddr = SharedAddresses[N].first.getAddress(CGF); 1017 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1018 BaseLValue.getPointer(CGF), SharedAddr.getPointer()); 1019 llvm::Value *PrivatePointer = 1020 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1021 PrivateAddr.getPointer(), SharedAddr.getType()); 1022 llvm::Value *Ptr = CGF.Builder.CreateGEP( 1023 SharedAddr.getElementType(), PrivatePointer, Adjustment); 1024 return castToBase(CGF, OrigVD->getType(), 1025 SharedAddresses[N].first.getType(), 1026 OriginalBaseLValue.getAddress(CGF).getType(), 1027 OriginalBaseLValue.getAlignment(), Ptr); 1028 } 1029 BaseDecls.emplace_back( 1030 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1031 return PrivateAddr; 1032 } 1033 1034 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1035 const OMPDeclareReductionDecl *DRD = 1036 getReductionInit(ClausesData[N].ReductionOp); 1037 return DRD && DRD->getInitializer(); 1038 } 1039 1040 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1041 return CGF.EmitLoadOfPointerLValue( 1042 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1043 getThreadIDVariable()->getType()->castAs<PointerType>()); 1044 } 1045 1046 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt *S) { 1047 if (!CGF.HaveInsertPoint()) 1048 return; 1049 // 1.2.2 OpenMP Language Terminology 1050 // Structured block - An executable statement with a single entry at the 1051 // top and a single exit at the bottom. 1052 // The point of exit cannot be a branch out of the structured block. 1053 // longjmp() and throw() must not violate the entry/exit criteria. 1054 CGF.EHStack.pushTerminate(); 1055 if (S) 1056 CGF.incrementProfileCounter(S); 1057 CodeGen(CGF); 1058 CGF.EHStack.popTerminate(); 1059 } 1060 1061 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1062 CodeGenFunction &CGF) { 1063 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1064 getThreadIDVariable()->getType(), 1065 AlignmentSource::Decl); 1066 } 1067 1068 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1069 QualType FieldTy) { 1070 auto *Field = FieldDecl::Create( 1071 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1072 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1073 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1074 Field->setAccess(AS_public); 1075 DC->addDecl(Field); 1076 return Field; 1077 } 1078 1079 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1080 StringRef Separator) 1081 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1082 OMPBuilder(CGM.getModule()), OffloadEntriesInfoManager(CGM) { 1083 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1084 1085 // Initialize Types used in OpenMPIRBuilder from OMPKinds.def 1086 OMPBuilder.initialize(); 1087 loadOffloadInfoMetadata(); 1088 } 1089 1090 void CGOpenMPRuntime::clear() { 1091 InternalVars.clear(); 1092 // Clean non-target variable declarations possibly used only in debug info. 1093 for (const auto &Data : EmittedNonTargetVariables) { 1094 if (!Data.getValue().pointsToAliveValue()) 1095 continue; 1096 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1097 if (!GV) 1098 continue; 1099 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1100 continue; 1101 GV->eraseFromParent(); 1102 } 1103 } 1104 1105 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1106 SmallString<128> Buffer; 1107 llvm::raw_svector_ostream OS(Buffer); 1108 StringRef Sep = FirstSeparator; 1109 for (StringRef Part : Parts) { 1110 OS << Sep << Part; 1111 Sep = Separator; 1112 } 1113 return std::string(OS.str()); 1114 } 1115 1116 static llvm::Function * 1117 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1118 const Expr *CombinerInitializer, const VarDecl *In, 1119 const VarDecl *Out, bool IsCombiner) { 1120 // void .omp_combiner.(Ty *in, Ty *out); 1121 ASTContext &C = CGM.getContext(); 1122 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1123 FunctionArgList Args; 1124 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1125 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1126 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1127 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1128 Args.push_back(&OmpOutParm); 1129 Args.push_back(&OmpInParm); 1130 const CGFunctionInfo &FnInfo = 1131 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1132 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1133 std::string Name = CGM.getOpenMPRuntime().getName( 1134 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1135 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1136 Name, &CGM.getModule()); 1137 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1138 if (CGM.getLangOpts().Optimize) { 1139 Fn->removeFnAttr(llvm::Attribute::NoInline); 1140 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1141 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1142 } 1143 CodeGenFunction CGF(CGM); 1144 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1145 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1146 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1147 Out->getLocation()); 1148 CodeGenFunction::OMPPrivateScope Scope(CGF); 1149 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1150 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1151 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1152 .getAddress(CGF); 1153 }); 1154 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1155 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1156 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1157 .getAddress(CGF); 1158 }); 1159 (void)Scope.Privatize(); 1160 if (!IsCombiner && Out->hasInit() && 1161 !CGF.isTrivialInitializer(Out->getInit())) { 1162 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1163 Out->getType().getQualifiers(), 1164 /*IsInitializer=*/true); 1165 } 1166 if (CombinerInitializer) 1167 CGF.EmitIgnoredExpr(CombinerInitializer); 1168 Scope.ForceCleanup(); 1169 CGF.FinishFunction(); 1170 return Fn; 1171 } 1172 1173 void CGOpenMPRuntime::emitUserDefinedReduction( 1174 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1175 if (UDRMap.count(D) > 0) 1176 return; 1177 llvm::Function *Combiner = emitCombinerOrInitializer( 1178 CGM, D->getType(), D->getCombiner(), 1179 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1180 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1181 /*IsCombiner=*/true); 1182 llvm::Function *Initializer = nullptr; 1183 if (const Expr *Init = D->getInitializer()) { 1184 Initializer = emitCombinerOrInitializer( 1185 CGM, D->getType(), 1186 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1187 : nullptr, 1188 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1189 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1190 /*IsCombiner=*/false); 1191 } 1192 UDRMap.try_emplace(D, Combiner, Initializer); 1193 if (CGF) { 1194 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1195 Decls.second.push_back(D); 1196 } 1197 } 1198 1199 std::pair<llvm::Function *, llvm::Function *> 1200 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1201 auto I = UDRMap.find(D); 1202 if (I != UDRMap.end()) 1203 return I->second; 1204 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1205 return UDRMap.lookup(D); 1206 } 1207 1208 namespace { 1209 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1210 // Builder if one is present. 1211 struct PushAndPopStackRAII { 1212 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1213 bool HasCancel, llvm::omp::Directive Kind) 1214 : OMPBuilder(OMPBuilder) { 1215 if (!OMPBuilder) 1216 return; 1217 1218 // The following callback is the crucial part of clangs cleanup process. 1219 // 1220 // NOTE: 1221 // Once the OpenMPIRBuilder is used to create parallel regions (and 1222 // similar), the cancellation destination (Dest below) is determined via 1223 // IP. That means if we have variables to finalize we split the block at IP, 1224 // use the new block (=BB) as destination to build a JumpDest (via 1225 // getJumpDestInCurrentScope(BB)) which then is fed to 1226 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1227 // to push & pop an FinalizationInfo object. 1228 // The FiniCB will still be needed but at the point where the 1229 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1230 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1231 assert(IP.getBlock()->end() == IP.getPoint() && 1232 "Clang CG should cause non-terminated block!"); 1233 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1234 CGF.Builder.restoreIP(IP); 1235 CodeGenFunction::JumpDest Dest = 1236 CGF.getOMPCancelDestination(OMPD_parallel); 1237 CGF.EmitBranchThroughCleanup(Dest); 1238 }; 1239 1240 // TODO: Remove this once we emit parallel regions through the 1241 // OpenMPIRBuilder as it can do this setup internally. 1242 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel}); 1243 OMPBuilder->pushFinalizationCB(std::move(FI)); 1244 } 1245 ~PushAndPopStackRAII() { 1246 if (OMPBuilder) 1247 OMPBuilder->popFinalizationCB(); 1248 } 1249 llvm::OpenMPIRBuilder *OMPBuilder; 1250 }; 1251 } // namespace 1252 1253 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1254 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1255 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1256 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1257 assert(ThreadIDVar->getType()->isPointerType() && 1258 "thread id variable must be of type kmp_int32 *"); 1259 CodeGenFunction CGF(CGM, true); 1260 bool HasCancel = false; 1261 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1262 HasCancel = OPD->hasCancel(); 1263 else if (const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D)) 1264 HasCancel = OPD->hasCancel(); 1265 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1266 HasCancel = OPSD->hasCancel(); 1267 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1268 HasCancel = OPFD->hasCancel(); 1269 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1270 HasCancel = OPFD->hasCancel(); 1271 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1272 HasCancel = OPFD->hasCancel(); 1273 else if (const auto *OPFD = 1274 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1275 HasCancel = OPFD->hasCancel(); 1276 else if (const auto *OPFD = 1277 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1278 HasCancel = OPFD->hasCancel(); 1279 1280 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1281 // parallel region to make cancellation barriers work properly. 1282 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); 1283 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind); 1284 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1285 HasCancel, OutlinedHelperName); 1286 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1287 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1288 } 1289 1290 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1291 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1292 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1293 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1294 return emitParallelOrTeamsOutlinedFunction( 1295 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1296 } 1297 1298 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1299 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1300 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1301 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1302 return emitParallelOrTeamsOutlinedFunction( 1303 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1304 } 1305 1306 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1307 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1308 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1309 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1310 bool Tied, unsigned &NumberOfParts) { 1311 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1312 PrePostActionTy &) { 1313 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1314 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1315 llvm::Value *TaskArgs[] = { 1316 UpLoc, ThreadID, 1317 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1318 TaskTVar->getType()->castAs<PointerType>()) 1319 .getPointer(CGF)}; 1320 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1321 CGM.getModule(), OMPRTL___kmpc_omp_task), 1322 TaskArgs); 1323 }; 1324 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1325 UntiedCodeGen); 1326 CodeGen.setAction(Action); 1327 assert(!ThreadIDVar->getType()->isPointerType() && 1328 "thread id variable must be of type kmp_int32 for tasks"); 1329 const OpenMPDirectiveKind Region = 1330 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1331 : OMPD_task; 1332 const CapturedStmt *CS = D.getCapturedStmt(Region); 1333 bool HasCancel = false; 1334 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1335 HasCancel = TD->hasCancel(); 1336 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1337 HasCancel = TD->hasCancel(); 1338 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1339 HasCancel = TD->hasCancel(); 1340 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1341 HasCancel = TD->hasCancel(); 1342 1343 CodeGenFunction CGF(CGM, true); 1344 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1345 InnermostKind, HasCancel, Action); 1346 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1347 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1348 if (!Tied) 1349 NumberOfParts = Action.getNumberOfParts(); 1350 return Res; 1351 } 1352 1353 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1354 const RecordDecl *RD, const CGRecordLayout &RL, 1355 ArrayRef<llvm::Constant *> Data) { 1356 llvm::StructType *StructTy = RL.getLLVMType(); 1357 unsigned PrevIdx = 0; 1358 ConstantInitBuilder CIBuilder(CGM); 1359 auto DI = Data.begin(); 1360 for (const FieldDecl *FD : RD->fields()) { 1361 unsigned Idx = RL.getLLVMFieldNo(FD); 1362 // Fill the alignment. 1363 for (unsigned I = PrevIdx; I < Idx; ++I) 1364 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1365 PrevIdx = Idx + 1; 1366 Fields.add(*DI); 1367 ++DI; 1368 } 1369 } 1370 1371 template <class... As> 1372 static llvm::GlobalVariable * 1373 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1374 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1375 As &&... Args) { 1376 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1377 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1378 ConstantInitBuilder CIBuilder(CGM); 1379 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1380 buildStructValue(Fields, CGM, RD, RL, Data); 1381 return Fields.finishAndCreateGlobal( 1382 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1383 std::forward<As>(Args)...); 1384 } 1385 1386 template <typename T> 1387 static void 1388 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1389 ArrayRef<llvm::Constant *> Data, 1390 T &Parent) { 1391 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1392 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1393 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1394 buildStructValue(Fields, CGM, RD, RL, Data); 1395 Fields.finishAndAddTo(Parent); 1396 } 1397 1398 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1399 bool AtCurrentPoint) { 1400 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1401 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1402 1403 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1404 if (AtCurrentPoint) { 1405 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1406 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1407 } else { 1408 Elem.second.ServiceInsertPt = 1409 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1410 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1411 } 1412 } 1413 1414 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1415 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1416 if (Elem.second.ServiceInsertPt) { 1417 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1418 Elem.second.ServiceInsertPt = nullptr; 1419 Ptr->eraseFromParent(); 1420 } 1421 } 1422 1423 static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, 1424 SourceLocation Loc, 1425 SmallString<128> &Buffer) { 1426 llvm::raw_svector_ostream OS(Buffer); 1427 // Build debug location 1428 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1429 OS << ";" << PLoc.getFilename() << ";"; 1430 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1431 OS << FD->getQualifiedNameAsString(); 1432 OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1433 return OS.str(); 1434 } 1435 1436 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1437 SourceLocation Loc, 1438 unsigned Flags) { 1439 llvm::Constant *SrcLocStr; 1440 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1441 Loc.isInvalid()) { 1442 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(); 1443 } else { 1444 std::string FunctionName = ""; 1445 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1446 FunctionName = FD->getQualifiedNameAsString(); 1447 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1448 const char *FileName = PLoc.getFilename(); 1449 unsigned Line = PLoc.getLine(); 1450 unsigned Column = PLoc.getColumn(); 1451 SrcLocStr = 1452 OMPBuilder.getOrCreateSrcLocStr(FunctionName, FileName, Line, Column); 1453 } 1454 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1455 return OMPBuilder.getOrCreateIdent(SrcLocStr, llvm::omp::IdentFlag(Flags), 1456 Reserved2Flags); 1457 } 1458 1459 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1460 SourceLocation Loc) { 1461 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1462 // If the OpenMPIRBuilder is used we need to use it for all thread id calls as 1463 // the clang invariants used below might be broken. 1464 if (CGM.getLangOpts().OpenMPIRBuilder) { 1465 SmallString<128> Buffer; 1466 OMPBuilder.updateToLocation(CGF.Builder.saveIP()); 1467 auto *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr( 1468 getIdentStringFromSourceLocation(CGF, Loc, Buffer)); 1469 return OMPBuilder.getOrCreateThreadID( 1470 OMPBuilder.getOrCreateIdent(SrcLocStr)); 1471 } 1472 1473 llvm::Value *ThreadID = nullptr; 1474 // Check whether we've already cached a load of the thread id in this 1475 // function. 1476 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1477 if (I != OpenMPLocThreadIDMap.end()) { 1478 ThreadID = I->second.ThreadID; 1479 if (ThreadID != nullptr) 1480 return ThreadID; 1481 } 1482 // If exceptions are enabled, do not use parameter to avoid possible crash. 1483 if (auto *OMPRegionInfo = 1484 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1485 if (OMPRegionInfo->getThreadIDVariable()) { 1486 // Check if this an outlined function with thread id passed as argument. 1487 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1488 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1489 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1490 !CGF.getLangOpts().CXXExceptions || 1491 CGF.Builder.GetInsertBlock() == TopBlock || 1492 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1493 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1494 TopBlock || 1495 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1496 CGF.Builder.GetInsertBlock()) { 1497 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1498 // If value loaded in entry block, cache it and use it everywhere in 1499 // function. 1500 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1501 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1502 Elem.second.ThreadID = ThreadID; 1503 } 1504 return ThreadID; 1505 } 1506 } 1507 } 1508 1509 // This is not an outlined function region - need to call __kmpc_int32 1510 // kmpc_global_thread_num(ident_t *loc). 1511 // Generate thread id value and cache this value for use across the 1512 // function. 1513 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1514 if (!Elem.second.ServiceInsertPt) 1515 setLocThreadIdInsertPt(CGF); 1516 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1517 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1518 llvm::CallInst *Call = CGF.Builder.CreateCall( 1519 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 1520 OMPRTL___kmpc_global_thread_num), 1521 emitUpdateLocation(CGF, Loc)); 1522 Call->setCallingConv(CGF.getRuntimeCC()); 1523 Elem.second.ThreadID = Call; 1524 return Call; 1525 } 1526 1527 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1528 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1529 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1530 clearLocThreadIdInsertPt(CGF); 1531 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1532 } 1533 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1534 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1535 UDRMap.erase(D); 1536 FunctionUDRMap.erase(CGF.CurFn); 1537 } 1538 auto I = FunctionUDMMap.find(CGF.CurFn); 1539 if (I != FunctionUDMMap.end()) { 1540 for(const auto *D : I->second) 1541 UDMMap.erase(D); 1542 FunctionUDMMap.erase(I); 1543 } 1544 LastprivateConditionalToTypes.erase(CGF.CurFn); 1545 FunctionToUntiedTaskStackMap.erase(CGF.CurFn); 1546 } 1547 1548 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1549 return OMPBuilder.IdentPtr; 1550 } 1551 1552 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1553 if (!Kmpc_MicroTy) { 1554 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1555 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1556 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1557 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1558 } 1559 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1560 } 1561 1562 llvm::FunctionCallee 1563 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned, 1564 bool IsGPUDistribute) { 1565 assert((IVSize == 32 || IVSize == 64) && 1566 "IV size is not compatible with the omp runtime"); 1567 StringRef Name; 1568 if (IsGPUDistribute) 1569 Name = IVSize == 32 ? (IVSigned ? "__kmpc_distribute_static_init_4" 1570 : "__kmpc_distribute_static_init_4u") 1571 : (IVSigned ? "__kmpc_distribute_static_init_8" 1572 : "__kmpc_distribute_static_init_8u"); 1573 else 1574 Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 1575 : "__kmpc_for_static_init_4u") 1576 : (IVSigned ? "__kmpc_for_static_init_8" 1577 : "__kmpc_for_static_init_8u"); 1578 1579 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1580 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1581 llvm::Type *TypeParams[] = { 1582 getIdentTyPointerTy(), // loc 1583 CGM.Int32Ty, // tid 1584 CGM.Int32Ty, // schedtype 1585 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1586 PtrTy, // p_lower 1587 PtrTy, // p_upper 1588 PtrTy, // p_stride 1589 ITy, // incr 1590 ITy // chunk 1591 }; 1592 auto *FnTy = 1593 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1594 return CGM.CreateRuntimeFunction(FnTy, Name); 1595 } 1596 1597 llvm::FunctionCallee 1598 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 1599 assert((IVSize == 32 || IVSize == 64) && 1600 "IV size is not compatible with the omp runtime"); 1601 StringRef Name = 1602 IVSize == 32 1603 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 1604 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 1605 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1606 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 1607 CGM.Int32Ty, // tid 1608 CGM.Int32Ty, // schedtype 1609 ITy, // lower 1610 ITy, // upper 1611 ITy, // stride 1612 ITy // chunk 1613 }; 1614 auto *FnTy = 1615 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1616 return CGM.CreateRuntimeFunction(FnTy, Name); 1617 } 1618 1619 llvm::FunctionCallee 1620 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 1621 assert((IVSize == 32 || IVSize == 64) && 1622 "IV size is not compatible with the omp runtime"); 1623 StringRef Name = 1624 IVSize == 32 1625 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 1626 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 1627 llvm::Type *TypeParams[] = { 1628 getIdentTyPointerTy(), // loc 1629 CGM.Int32Ty, // tid 1630 }; 1631 auto *FnTy = 1632 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1633 return CGM.CreateRuntimeFunction(FnTy, Name); 1634 } 1635 1636 llvm::FunctionCallee 1637 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 1638 assert((IVSize == 32 || IVSize == 64) && 1639 "IV size is not compatible with the omp runtime"); 1640 StringRef Name = 1641 IVSize == 32 1642 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 1643 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 1644 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1645 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1646 llvm::Type *TypeParams[] = { 1647 getIdentTyPointerTy(), // loc 1648 CGM.Int32Ty, // tid 1649 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1650 PtrTy, // p_lower 1651 PtrTy, // p_upper 1652 PtrTy // p_stride 1653 }; 1654 auto *FnTy = 1655 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1656 return CGM.CreateRuntimeFunction(FnTy, Name); 1657 } 1658 1659 /// Obtain information that uniquely identifies a target entry. This 1660 /// consists of the file and device IDs as well as line number associated with 1661 /// the relevant entry source location. 1662 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 1663 unsigned &DeviceID, unsigned &FileID, 1664 unsigned &LineNum) { 1665 SourceManager &SM = C.getSourceManager(); 1666 1667 // The loc should be always valid and have a file ID (the user cannot use 1668 // #pragma directives in macros) 1669 1670 assert(Loc.isValid() && "Source location is expected to be always valid."); 1671 1672 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 1673 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1674 1675 llvm::sys::fs::UniqueID ID; 1676 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) { 1677 PLoc = SM.getPresumedLoc(Loc, /*UseLineDirectives=*/false); 1678 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1679 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 1680 SM.getDiagnostics().Report(diag::err_cannot_open_file) 1681 << PLoc.getFilename() << EC.message(); 1682 } 1683 1684 DeviceID = ID.getDevice(); 1685 FileID = ID.getFile(); 1686 LineNum = PLoc.getLine(); 1687 } 1688 1689 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 1690 if (CGM.getLangOpts().OpenMPSimd) 1691 return Address::invalid(); 1692 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1693 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1694 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 1695 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1696 HasRequiresUnifiedSharedMemory))) { 1697 SmallString<64> PtrName; 1698 { 1699 llvm::raw_svector_ostream OS(PtrName); 1700 OS << CGM.getMangledName(GlobalDecl(VD)); 1701 if (!VD->isExternallyVisible()) { 1702 unsigned DeviceID, FileID, Line; 1703 getTargetEntryUniqueInfo(CGM.getContext(), 1704 VD->getCanonicalDecl()->getBeginLoc(), 1705 DeviceID, FileID, Line); 1706 OS << llvm::format("_%x", FileID); 1707 } 1708 OS << "_decl_tgt_ref_ptr"; 1709 } 1710 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 1711 if (!Ptr) { 1712 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 1713 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 1714 PtrName); 1715 1716 auto *GV = cast<llvm::GlobalVariable>(Ptr); 1717 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 1718 1719 if (!CGM.getLangOpts().OpenMPIsDevice) 1720 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 1721 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 1722 } 1723 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 1724 } 1725 return Address::invalid(); 1726 } 1727 1728 llvm::Constant * 1729 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 1730 assert(!CGM.getLangOpts().OpenMPUseTLS || 1731 !CGM.getContext().getTargetInfo().isTLSSupported()); 1732 // Lookup the entry, lazily creating it if necessary. 1733 std::string Suffix = getName({"cache", ""}); 1734 return getOrCreateInternalVariable( 1735 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 1736 } 1737 1738 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 1739 const VarDecl *VD, 1740 Address VDAddr, 1741 SourceLocation Loc) { 1742 if (CGM.getLangOpts().OpenMPUseTLS && 1743 CGM.getContext().getTargetInfo().isTLSSupported()) 1744 return VDAddr; 1745 1746 llvm::Type *VarTy = VDAddr.getElementType(); 1747 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1748 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1749 CGM.Int8PtrTy), 1750 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 1751 getOrCreateThreadPrivateCache(VD)}; 1752 return Address(CGF.EmitRuntimeCall( 1753 OMPBuilder.getOrCreateRuntimeFunction( 1754 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 1755 Args), 1756 VDAddr.getAlignment()); 1757 } 1758 1759 void CGOpenMPRuntime::emitThreadPrivateVarInit( 1760 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 1761 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 1762 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 1763 // library. 1764 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 1765 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1766 CGM.getModule(), OMPRTL___kmpc_global_thread_num), 1767 OMPLoc); 1768 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 1769 // to register constructor/destructor for variable. 1770 llvm::Value *Args[] = { 1771 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 1772 Ctor, CopyCtor, Dtor}; 1773 CGF.EmitRuntimeCall( 1774 OMPBuilder.getOrCreateRuntimeFunction( 1775 CGM.getModule(), OMPRTL___kmpc_threadprivate_register), 1776 Args); 1777 } 1778 1779 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 1780 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 1781 bool PerformInit, CodeGenFunction *CGF) { 1782 if (CGM.getLangOpts().OpenMPUseTLS && 1783 CGM.getContext().getTargetInfo().isTLSSupported()) 1784 return nullptr; 1785 1786 VD = VD->getDefinition(CGM.getContext()); 1787 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 1788 QualType ASTTy = VD->getType(); 1789 1790 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 1791 const Expr *Init = VD->getAnyInitializer(); 1792 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1793 // Generate function that re-emits the declaration's initializer into the 1794 // threadprivate copy of the variable VD 1795 CodeGenFunction CtorCGF(CGM); 1796 FunctionArgList Args; 1797 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1798 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1799 ImplicitParamDecl::Other); 1800 Args.push_back(&Dst); 1801 1802 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1803 CGM.getContext().VoidPtrTy, Args); 1804 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1805 std::string Name = getName({"__kmpc_global_ctor_", ""}); 1806 llvm::Function *Fn = 1807 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1808 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 1809 Args, Loc, Loc); 1810 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 1811 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1812 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1813 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 1814 Arg = CtorCGF.Builder.CreateElementBitCast( 1815 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 1816 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1817 /*IsInitializer=*/true); 1818 ArgVal = CtorCGF.EmitLoadOfScalar( 1819 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1820 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1821 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1822 CtorCGF.FinishFunction(); 1823 Ctor = Fn; 1824 } 1825 if (VD->getType().isDestructedType() != QualType::DK_none) { 1826 // Generate function that emits destructor call for the threadprivate copy 1827 // of the variable VD 1828 CodeGenFunction DtorCGF(CGM); 1829 FunctionArgList Args; 1830 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1831 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1832 ImplicitParamDecl::Other); 1833 Args.push_back(&Dst); 1834 1835 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1836 CGM.getContext().VoidTy, Args); 1837 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1838 std::string Name = getName({"__kmpc_global_dtor_", ""}); 1839 llvm::Function *Fn = 1840 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1841 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1842 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1843 Loc, Loc); 1844 // Create a scope with an artificial location for the body of this function. 1845 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1846 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 1847 DtorCGF.GetAddrOfLocalVar(&Dst), 1848 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 1849 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 1850 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1851 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1852 DtorCGF.FinishFunction(); 1853 Dtor = Fn; 1854 } 1855 // Do not emit init function if it is not required. 1856 if (!Ctor && !Dtor) 1857 return nullptr; 1858 1859 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1860 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1861 /*isVarArg=*/false) 1862 ->getPointerTo(); 1863 // Copying constructor for the threadprivate variable. 1864 // Must be NULL - reserved by runtime, but currently it requires that this 1865 // parameter is always NULL. Otherwise it fires assertion. 1866 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1867 if (Ctor == nullptr) { 1868 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1869 /*isVarArg=*/false) 1870 ->getPointerTo(); 1871 Ctor = llvm::Constant::getNullValue(CtorTy); 1872 } 1873 if (Dtor == nullptr) { 1874 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1875 /*isVarArg=*/false) 1876 ->getPointerTo(); 1877 Dtor = llvm::Constant::getNullValue(DtorTy); 1878 } 1879 if (!CGF) { 1880 auto *InitFunctionTy = 1881 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1882 std::string Name = getName({"__omp_threadprivate_init_", ""}); 1883 llvm::Function *InitFunction = CGM.CreateGlobalInitOrCleanUpFunction( 1884 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 1885 CodeGenFunction InitCGF(CGM); 1886 FunctionArgList ArgList; 1887 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1888 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1889 Loc, Loc); 1890 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1891 InitCGF.FinishFunction(); 1892 return InitFunction; 1893 } 1894 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1895 } 1896 return nullptr; 1897 } 1898 1899 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 1900 llvm::GlobalVariable *Addr, 1901 bool PerformInit) { 1902 if (CGM.getLangOpts().OMPTargetTriples.empty() && 1903 !CGM.getLangOpts().OpenMPIsDevice) 1904 return false; 1905 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1906 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1907 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 1908 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1909 HasRequiresUnifiedSharedMemory)) 1910 return CGM.getLangOpts().OpenMPIsDevice; 1911 VD = VD->getDefinition(CGM.getContext()); 1912 assert(VD && "Unknown VarDecl"); 1913 1914 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 1915 return CGM.getLangOpts().OpenMPIsDevice; 1916 1917 QualType ASTTy = VD->getType(); 1918 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 1919 1920 // Produce the unique prefix to identify the new target regions. We use 1921 // the source location of the variable declaration which we know to not 1922 // conflict with any target region. 1923 unsigned DeviceID; 1924 unsigned FileID; 1925 unsigned Line; 1926 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 1927 SmallString<128> Buffer, Out; 1928 { 1929 llvm::raw_svector_ostream OS(Buffer); 1930 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 1931 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 1932 } 1933 1934 const Expr *Init = VD->getAnyInitializer(); 1935 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1936 llvm::Constant *Ctor; 1937 llvm::Constant *ID; 1938 if (CGM.getLangOpts().OpenMPIsDevice) { 1939 // Generate function that re-emits the declaration's initializer into 1940 // the threadprivate copy of the variable VD 1941 CodeGenFunction CtorCGF(CGM); 1942 1943 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1944 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1945 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1946 FTy, Twine(Buffer, "_ctor"), FI, Loc); 1947 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 1948 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1949 FunctionArgList(), Loc, Loc); 1950 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 1951 CtorCGF.EmitAnyExprToMem(Init, 1952 Address(Addr, CGM.getContext().getDeclAlign(VD)), 1953 Init->getType().getQualifiers(), 1954 /*IsInitializer=*/true); 1955 CtorCGF.FinishFunction(); 1956 Ctor = Fn; 1957 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1958 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 1959 } else { 1960 Ctor = new llvm::GlobalVariable( 1961 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1962 llvm::GlobalValue::PrivateLinkage, 1963 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 1964 ID = Ctor; 1965 } 1966 1967 // Register the information for the entry associated with the constructor. 1968 Out.clear(); 1969 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 1970 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 1971 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 1972 } 1973 if (VD->getType().isDestructedType() != QualType::DK_none) { 1974 llvm::Constant *Dtor; 1975 llvm::Constant *ID; 1976 if (CGM.getLangOpts().OpenMPIsDevice) { 1977 // Generate function that emits destructor call for the threadprivate 1978 // copy of the variable VD 1979 CodeGenFunction DtorCGF(CGM); 1980 1981 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1982 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1983 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1984 FTy, Twine(Buffer, "_dtor"), FI, Loc); 1985 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1986 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1987 FunctionArgList(), Loc, Loc); 1988 // Create a scope with an artificial location for the body of this 1989 // function. 1990 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1991 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 1992 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1993 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1994 DtorCGF.FinishFunction(); 1995 Dtor = Fn; 1996 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1997 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 1998 } else { 1999 Dtor = new llvm::GlobalVariable( 2000 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2001 llvm::GlobalValue::PrivateLinkage, 2002 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 2003 ID = Dtor; 2004 } 2005 // Register the information for the entry associated with the destructor. 2006 Out.clear(); 2007 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2008 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2009 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2010 } 2011 return CGM.getLangOpts().OpenMPIsDevice; 2012 } 2013 2014 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2015 QualType VarType, 2016 StringRef Name) { 2017 std::string Suffix = getName({"artificial", ""}); 2018 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2019 llvm::Value *GAddr = 2020 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2021 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 2022 CGM.getTarget().isTLSSupported()) { 2023 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 2024 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 2025 } 2026 std::string CacheSuffix = getName({"cache", ""}); 2027 llvm::Value *Args[] = { 2028 emitUpdateLocation(CGF, SourceLocation()), 2029 getThreadID(CGF, SourceLocation()), 2030 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2031 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2032 /*isSigned=*/false), 2033 getOrCreateInternalVariable( 2034 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2035 return Address( 2036 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2037 CGF.EmitRuntimeCall( 2038 OMPBuilder.getOrCreateRuntimeFunction( 2039 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 2040 Args), 2041 VarLVType->getPointerTo(/*AddrSpace=*/0)), 2042 CGM.getContext().getTypeAlignInChars(VarType)); 2043 } 2044 2045 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 2046 const RegionCodeGenTy &ThenGen, 2047 const RegionCodeGenTy &ElseGen) { 2048 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 2049 2050 // If the condition constant folds and can be elided, try to avoid emitting 2051 // the condition and the dead arm of the if/else. 2052 bool CondConstant; 2053 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 2054 if (CondConstant) 2055 ThenGen(CGF); 2056 else 2057 ElseGen(CGF); 2058 return; 2059 } 2060 2061 // Otherwise, the condition did not fold, or we couldn't elide it. Just 2062 // emit the conditional branch. 2063 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2064 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 2065 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 2066 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 2067 2068 // Emit the 'then' code. 2069 CGF.EmitBlock(ThenBlock); 2070 ThenGen(CGF); 2071 CGF.EmitBranch(ContBlock); 2072 // Emit the 'else' code if present. 2073 // There is no need to emit line number for unconditional branch. 2074 (void)ApplyDebugLocation::CreateEmpty(CGF); 2075 CGF.EmitBlock(ElseBlock); 2076 ElseGen(CGF); 2077 // There is no need to emit line number for unconditional branch. 2078 (void)ApplyDebugLocation::CreateEmpty(CGF); 2079 CGF.EmitBranch(ContBlock); 2080 // Emit the continuation block for code after the if. 2081 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 2082 } 2083 2084 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 2085 llvm::Function *OutlinedFn, 2086 ArrayRef<llvm::Value *> CapturedVars, 2087 const Expr *IfCond) { 2088 if (!CGF.HaveInsertPoint()) 2089 return; 2090 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 2091 auto &M = CGM.getModule(); 2092 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc, 2093 this](CodeGenFunction &CGF, PrePostActionTy &) { 2094 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 2095 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2096 llvm::Value *Args[] = { 2097 RTLoc, 2098 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 2099 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 2100 llvm::SmallVector<llvm::Value *, 16> RealArgs; 2101 RealArgs.append(std::begin(Args), std::end(Args)); 2102 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 2103 2104 llvm::FunctionCallee RTLFn = 2105 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call); 2106 CGF.EmitRuntimeCall(RTLFn, RealArgs); 2107 }; 2108 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc, 2109 this](CodeGenFunction &CGF, PrePostActionTy &) { 2110 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2111 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 2112 // Build calls: 2113 // __kmpc_serialized_parallel(&Loc, GTid); 2114 llvm::Value *Args[] = {RTLoc, ThreadID}; 2115 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2116 M, OMPRTL___kmpc_serialized_parallel), 2117 Args); 2118 2119 // OutlinedFn(>id, &zero_bound, CapturedStruct); 2120 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 2121 Address ZeroAddrBound = 2122 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 2123 /*Name=*/".bound.zero.addr"); 2124 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 2125 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 2126 // ThreadId for serialized parallels is 0. 2127 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 2128 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 2129 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 2130 2131 // Ensure we do not inline the function. This is trivially true for the ones 2132 // passed to __kmpc_fork_call but the ones called in serialized regions 2133 // could be inlined. This is not a perfect but it is closer to the invariant 2134 // we want, namely, every data environment starts with a new function. 2135 // TODO: We should pass the if condition to the runtime function and do the 2136 // handling there. Much cleaner code. 2137 OutlinedFn->removeFnAttr(llvm::Attribute::AlwaysInline); 2138 OutlinedFn->addFnAttr(llvm::Attribute::NoInline); 2139 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 2140 2141 // __kmpc_end_serialized_parallel(&Loc, GTid); 2142 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 2143 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2144 M, OMPRTL___kmpc_end_serialized_parallel), 2145 EndArgs); 2146 }; 2147 if (IfCond) { 2148 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 2149 } else { 2150 RegionCodeGenTy ThenRCG(ThenGen); 2151 ThenRCG(CGF); 2152 } 2153 } 2154 2155 // If we're inside an (outlined) parallel region, use the region info's 2156 // thread-ID variable (it is passed in a first argument of the outlined function 2157 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 2158 // regular serial code region, get thread ID by calling kmp_int32 2159 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 2160 // return the address of that temp. 2161 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 2162 SourceLocation Loc) { 2163 if (auto *OMPRegionInfo = 2164 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2165 if (OMPRegionInfo->getThreadIDVariable()) 2166 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 2167 2168 llvm::Value *ThreadID = getThreadID(CGF, Loc); 2169 QualType Int32Ty = 2170 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 2171 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 2172 CGF.EmitStoreOfScalar(ThreadID, 2173 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 2174 2175 return ThreadIDTemp; 2176 } 2177 2178 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 2179 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 2180 SmallString<256> Buffer; 2181 llvm::raw_svector_ostream Out(Buffer); 2182 Out << Name; 2183 StringRef RuntimeName = Out.str(); 2184 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 2185 if (Elem.second) { 2186 assert(Elem.second->getType()->getPointerElementType() == Ty && 2187 "OMP internal variable has different type than requested"); 2188 return &*Elem.second; 2189 } 2190 2191 return Elem.second = new llvm::GlobalVariable( 2192 CGM.getModule(), Ty, /*IsConstant*/ false, 2193 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 2194 Elem.first(), /*InsertBefore=*/nullptr, 2195 llvm::GlobalValue::NotThreadLocal, AddressSpace); 2196 } 2197 2198 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 2199 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 2200 std::string Name = getName({Prefix, "var"}); 2201 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 2202 } 2203 2204 namespace { 2205 /// Common pre(post)-action for different OpenMP constructs. 2206 class CommonActionTy final : public PrePostActionTy { 2207 llvm::FunctionCallee EnterCallee; 2208 ArrayRef<llvm::Value *> EnterArgs; 2209 llvm::FunctionCallee ExitCallee; 2210 ArrayRef<llvm::Value *> ExitArgs; 2211 bool Conditional; 2212 llvm::BasicBlock *ContBlock = nullptr; 2213 2214 public: 2215 CommonActionTy(llvm::FunctionCallee EnterCallee, 2216 ArrayRef<llvm::Value *> EnterArgs, 2217 llvm::FunctionCallee ExitCallee, 2218 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 2219 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 2220 ExitArgs(ExitArgs), Conditional(Conditional) {} 2221 void Enter(CodeGenFunction &CGF) override { 2222 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 2223 if (Conditional) { 2224 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 2225 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2226 ContBlock = CGF.createBasicBlock("omp_if.end"); 2227 // Generate the branch (If-stmt) 2228 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 2229 CGF.EmitBlock(ThenBlock); 2230 } 2231 } 2232 void Done(CodeGenFunction &CGF) { 2233 // Emit the rest of blocks/branches 2234 CGF.EmitBranch(ContBlock); 2235 CGF.EmitBlock(ContBlock, true); 2236 } 2237 void Exit(CodeGenFunction &CGF) override { 2238 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 2239 } 2240 }; 2241 } // anonymous namespace 2242 2243 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 2244 StringRef CriticalName, 2245 const RegionCodeGenTy &CriticalOpGen, 2246 SourceLocation Loc, const Expr *Hint) { 2247 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 2248 // CriticalOpGen(); 2249 // __kmpc_end_critical(ident_t *, gtid, Lock); 2250 // Prepare arguments and build a call to __kmpc_critical 2251 if (!CGF.HaveInsertPoint()) 2252 return; 2253 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2254 getCriticalRegionLock(CriticalName)}; 2255 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 2256 std::end(Args)); 2257 if (Hint) { 2258 EnterArgs.push_back(CGF.Builder.CreateIntCast( 2259 CGF.EmitScalarExpr(Hint), CGM.Int32Ty, /*isSigned=*/false)); 2260 } 2261 CommonActionTy Action( 2262 OMPBuilder.getOrCreateRuntimeFunction( 2263 CGM.getModule(), 2264 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical), 2265 EnterArgs, 2266 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2267 OMPRTL___kmpc_end_critical), 2268 Args); 2269 CriticalOpGen.setAction(Action); 2270 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 2271 } 2272 2273 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 2274 const RegionCodeGenTy &MasterOpGen, 2275 SourceLocation Loc) { 2276 if (!CGF.HaveInsertPoint()) 2277 return; 2278 // if(__kmpc_master(ident_t *, gtid)) { 2279 // MasterOpGen(); 2280 // __kmpc_end_master(ident_t *, gtid); 2281 // } 2282 // Prepare arguments and build a call to __kmpc_master 2283 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2284 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2285 CGM.getModule(), OMPRTL___kmpc_master), 2286 Args, 2287 OMPBuilder.getOrCreateRuntimeFunction( 2288 CGM.getModule(), OMPRTL___kmpc_end_master), 2289 Args, 2290 /*Conditional=*/true); 2291 MasterOpGen.setAction(Action); 2292 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 2293 Action.Done(CGF); 2294 } 2295 2296 void CGOpenMPRuntime::emitMaskedRegion(CodeGenFunction &CGF, 2297 const RegionCodeGenTy &MaskedOpGen, 2298 SourceLocation Loc, const Expr *Filter) { 2299 if (!CGF.HaveInsertPoint()) 2300 return; 2301 // if(__kmpc_masked(ident_t *, gtid, filter)) { 2302 // MaskedOpGen(); 2303 // __kmpc_end_masked(iden_t *, gtid); 2304 // } 2305 // Prepare arguments and build a call to __kmpc_masked 2306 llvm::Value *FilterVal = Filter 2307 ? CGF.EmitScalarExpr(Filter, CGF.Int32Ty) 2308 : llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/0); 2309 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2310 FilterVal}; 2311 llvm::Value *ArgsEnd[] = {emitUpdateLocation(CGF, Loc), 2312 getThreadID(CGF, Loc)}; 2313 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2314 CGM.getModule(), OMPRTL___kmpc_masked), 2315 Args, 2316 OMPBuilder.getOrCreateRuntimeFunction( 2317 CGM.getModule(), OMPRTL___kmpc_end_masked), 2318 ArgsEnd, 2319 /*Conditional=*/true); 2320 MaskedOpGen.setAction(Action); 2321 emitInlinedDirective(CGF, OMPD_masked, MaskedOpGen); 2322 Action.Done(CGF); 2323 } 2324 2325 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 2326 SourceLocation Loc) { 2327 if (!CGF.HaveInsertPoint()) 2328 return; 2329 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2330 OMPBuilder.createTaskyield(CGF.Builder); 2331 } else { 2332 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 2333 llvm::Value *Args[] = { 2334 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2335 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 2336 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2337 CGM.getModule(), OMPRTL___kmpc_omp_taskyield), 2338 Args); 2339 } 2340 2341 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2342 Region->emitUntiedSwitch(CGF); 2343 } 2344 2345 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 2346 const RegionCodeGenTy &TaskgroupOpGen, 2347 SourceLocation Loc) { 2348 if (!CGF.HaveInsertPoint()) 2349 return; 2350 // __kmpc_taskgroup(ident_t *, gtid); 2351 // TaskgroupOpGen(); 2352 // __kmpc_end_taskgroup(ident_t *, gtid); 2353 // Prepare arguments and build a call to __kmpc_taskgroup 2354 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2355 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2356 CGM.getModule(), OMPRTL___kmpc_taskgroup), 2357 Args, 2358 OMPBuilder.getOrCreateRuntimeFunction( 2359 CGM.getModule(), OMPRTL___kmpc_end_taskgroup), 2360 Args); 2361 TaskgroupOpGen.setAction(Action); 2362 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 2363 } 2364 2365 /// Given an array of pointers to variables, project the address of a 2366 /// given variable. 2367 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 2368 unsigned Index, const VarDecl *Var) { 2369 // Pull out the pointer to the variable. 2370 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 2371 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 2372 2373 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 2374 Addr = CGF.Builder.CreateElementBitCast( 2375 Addr, CGF.ConvertTypeForMem(Var->getType())); 2376 return Addr; 2377 } 2378 2379 static llvm::Value *emitCopyprivateCopyFunction( 2380 CodeGenModule &CGM, llvm::Type *ArgsType, 2381 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 2382 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 2383 SourceLocation Loc) { 2384 ASTContext &C = CGM.getContext(); 2385 // void copy_func(void *LHSArg, void *RHSArg); 2386 FunctionArgList Args; 2387 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2388 ImplicitParamDecl::Other); 2389 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2390 ImplicitParamDecl::Other); 2391 Args.push_back(&LHSArg); 2392 Args.push_back(&RHSArg); 2393 const auto &CGFI = 2394 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2395 std::string Name = 2396 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 2397 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 2398 llvm::GlobalValue::InternalLinkage, Name, 2399 &CGM.getModule()); 2400 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 2401 Fn->setDoesNotRecurse(); 2402 CodeGenFunction CGF(CGM); 2403 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 2404 // Dest = (void*[n])(LHSArg); 2405 // Src = (void*[n])(RHSArg); 2406 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2407 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 2408 ArgsType), CGF.getPointerAlign()); 2409 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2410 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 2411 ArgsType), CGF.getPointerAlign()); 2412 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 2413 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 2414 // ... 2415 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 2416 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 2417 const auto *DestVar = 2418 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 2419 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 2420 2421 const auto *SrcVar = 2422 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 2423 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 2424 2425 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 2426 QualType Type = VD->getType(); 2427 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 2428 } 2429 CGF.FinishFunction(); 2430 return Fn; 2431 } 2432 2433 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 2434 const RegionCodeGenTy &SingleOpGen, 2435 SourceLocation Loc, 2436 ArrayRef<const Expr *> CopyprivateVars, 2437 ArrayRef<const Expr *> SrcExprs, 2438 ArrayRef<const Expr *> DstExprs, 2439 ArrayRef<const Expr *> AssignmentOps) { 2440 if (!CGF.HaveInsertPoint()) 2441 return; 2442 assert(CopyprivateVars.size() == SrcExprs.size() && 2443 CopyprivateVars.size() == DstExprs.size() && 2444 CopyprivateVars.size() == AssignmentOps.size()); 2445 ASTContext &C = CGM.getContext(); 2446 // int32 did_it = 0; 2447 // if(__kmpc_single(ident_t *, gtid)) { 2448 // SingleOpGen(); 2449 // __kmpc_end_single(ident_t *, gtid); 2450 // did_it = 1; 2451 // } 2452 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2453 // <copy_func>, did_it); 2454 2455 Address DidIt = Address::invalid(); 2456 if (!CopyprivateVars.empty()) { 2457 // int32 did_it = 0; 2458 QualType KmpInt32Ty = 2459 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2460 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 2461 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 2462 } 2463 // Prepare arguments and build a call to __kmpc_single 2464 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2465 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2466 CGM.getModule(), OMPRTL___kmpc_single), 2467 Args, 2468 OMPBuilder.getOrCreateRuntimeFunction( 2469 CGM.getModule(), OMPRTL___kmpc_end_single), 2470 Args, 2471 /*Conditional=*/true); 2472 SingleOpGen.setAction(Action); 2473 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 2474 if (DidIt.isValid()) { 2475 // did_it = 1; 2476 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 2477 } 2478 Action.Done(CGF); 2479 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2480 // <copy_func>, did_it); 2481 if (DidIt.isValid()) { 2482 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 2483 QualType CopyprivateArrayTy = C.getConstantArrayType( 2484 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 2485 /*IndexTypeQuals=*/0); 2486 // Create a list of all private variables for copyprivate. 2487 Address CopyprivateList = 2488 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 2489 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 2490 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 2491 CGF.Builder.CreateStore( 2492 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2493 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 2494 CGF.VoidPtrTy), 2495 Elem); 2496 } 2497 // Build function that copies private values from single region to all other 2498 // threads in the corresponding parallel region. 2499 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 2500 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 2501 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 2502 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 2503 Address CL = 2504 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 2505 CGF.VoidPtrTy); 2506 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 2507 llvm::Value *Args[] = { 2508 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 2509 getThreadID(CGF, Loc), // i32 <gtid> 2510 BufSize, // size_t <buf_size> 2511 CL.getPointer(), // void *<copyprivate list> 2512 CpyFn, // void (*) (void *, void *) <copy_func> 2513 DidItVal // i32 did_it 2514 }; 2515 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2516 CGM.getModule(), OMPRTL___kmpc_copyprivate), 2517 Args); 2518 } 2519 } 2520 2521 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 2522 const RegionCodeGenTy &OrderedOpGen, 2523 SourceLocation Loc, bool IsThreads) { 2524 if (!CGF.HaveInsertPoint()) 2525 return; 2526 // __kmpc_ordered(ident_t *, gtid); 2527 // OrderedOpGen(); 2528 // __kmpc_end_ordered(ident_t *, gtid); 2529 // Prepare arguments and build a call to __kmpc_ordered 2530 if (IsThreads) { 2531 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2532 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2533 CGM.getModule(), OMPRTL___kmpc_ordered), 2534 Args, 2535 OMPBuilder.getOrCreateRuntimeFunction( 2536 CGM.getModule(), OMPRTL___kmpc_end_ordered), 2537 Args); 2538 OrderedOpGen.setAction(Action); 2539 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2540 return; 2541 } 2542 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2543 } 2544 2545 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 2546 unsigned Flags; 2547 if (Kind == OMPD_for) 2548 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 2549 else if (Kind == OMPD_sections) 2550 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 2551 else if (Kind == OMPD_single) 2552 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 2553 else if (Kind == OMPD_barrier) 2554 Flags = OMP_IDENT_BARRIER_EXPL; 2555 else 2556 Flags = OMP_IDENT_BARRIER_IMPL; 2557 return Flags; 2558 } 2559 2560 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 2561 CodeGenFunction &CGF, const OMPLoopDirective &S, 2562 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 2563 // Check if the loop directive is actually a doacross loop directive. In this 2564 // case choose static, 1 schedule. 2565 if (llvm::any_of( 2566 S.getClausesOfKind<OMPOrderedClause>(), 2567 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 2568 ScheduleKind = OMPC_SCHEDULE_static; 2569 // Chunk size is 1 in this case. 2570 llvm::APInt ChunkSize(32, 1); 2571 ChunkExpr = IntegerLiteral::Create( 2572 CGF.getContext(), ChunkSize, 2573 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 2574 SourceLocation()); 2575 } 2576 } 2577 2578 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 2579 OpenMPDirectiveKind Kind, bool EmitChecks, 2580 bool ForceSimpleCall) { 2581 // Check if we should use the OMPBuilder 2582 auto *OMPRegionInfo = 2583 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 2584 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2585 CGF.Builder.restoreIP(OMPBuilder.createBarrier( 2586 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 2587 return; 2588 } 2589 2590 if (!CGF.HaveInsertPoint()) 2591 return; 2592 // Build call __kmpc_cancel_barrier(loc, thread_id); 2593 // Build call __kmpc_barrier(loc, thread_id); 2594 unsigned Flags = getDefaultFlagsForBarriers(Kind); 2595 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 2596 // thread_id); 2597 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 2598 getThreadID(CGF, Loc)}; 2599 if (OMPRegionInfo) { 2600 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 2601 llvm::Value *Result = CGF.EmitRuntimeCall( 2602 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2603 OMPRTL___kmpc_cancel_barrier), 2604 Args); 2605 if (EmitChecks) { 2606 // if (__kmpc_cancel_barrier()) { 2607 // exit from construct; 2608 // } 2609 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2610 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 2611 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 2612 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2613 CGF.EmitBlock(ExitBB); 2614 // exit from construct; 2615 CodeGenFunction::JumpDest CancelDestination = 2616 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2617 CGF.EmitBranchThroughCleanup(CancelDestination); 2618 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2619 } 2620 return; 2621 } 2622 } 2623 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2624 CGM.getModule(), OMPRTL___kmpc_barrier), 2625 Args); 2626 } 2627 2628 /// Map the OpenMP loop schedule to the runtime enumeration. 2629 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 2630 bool Chunked, bool Ordered) { 2631 switch (ScheduleKind) { 2632 case OMPC_SCHEDULE_static: 2633 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 2634 : (Ordered ? OMP_ord_static : OMP_sch_static); 2635 case OMPC_SCHEDULE_dynamic: 2636 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 2637 case OMPC_SCHEDULE_guided: 2638 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 2639 case OMPC_SCHEDULE_runtime: 2640 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 2641 case OMPC_SCHEDULE_auto: 2642 return Ordered ? OMP_ord_auto : OMP_sch_auto; 2643 case OMPC_SCHEDULE_unknown: 2644 assert(!Chunked && "chunk was specified but schedule kind not known"); 2645 return Ordered ? OMP_ord_static : OMP_sch_static; 2646 } 2647 llvm_unreachable("Unexpected runtime schedule"); 2648 } 2649 2650 /// Map the OpenMP distribute schedule to the runtime enumeration. 2651 static OpenMPSchedType 2652 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 2653 // only static is allowed for dist_schedule 2654 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 2655 } 2656 2657 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 2658 bool Chunked) const { 2659 OpenMPSchedType Schedule = 2660 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2661 return Schedule == OMP_sch_static; 2662 } 2663 2664 bool CGOpenMPRuntime::isStaticNonchunked( 2665 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2666 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2667 return Schedule == OMP_dist_sch_static; 2668 } 2669 2670 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 2671 bool Chunked) const { 2672 OpenMPSchedType Schedule = 2673 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2674 return Schedule == OMP_sch_static_chunked; 2675 } 2676 2677 bool CGOpenMPRuntime::isStaticChunked( 2678 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2679 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2680 return Schedule == OMP_dist_sch_static_chunked; 2681 } 2682 2683 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 2684 OpenMPSchedType Schedule = 2685 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 2686 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 2687 return Schedule != OMP_sch_static; 2688 } 2689 2690 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 2691 OpenMPScheduleClauseModifier M1, 2692 OpenMPScheduleClauseModifier M2) { 2693 int Modifier = 0; 2694 switch (M1) { 2695 case OMPC_SCHEDULE_MODIFIER_monotonic: 2696 Modifier = OMP_sch_modifier_monotonic; 2697 break; 2698 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2699 Modifier = OMP_sch_modifier_nonmonotonic; 2700 break; 2701 case OMPC_SCHEDULE_MODIFIER_simd: 2702 if (Schedule == OMP_sch_static_chunked) 2703 Schedule = OMP_sch_static_balanced_chunked; 2704 break; 2705 case OMPC_SCHEDULE_MODIFIER_last: 2706 case OMPC_SCHEDULE_MODIFIER_unknown: 2707 break; 2708 } 2709 switch (M2) { 2710 case OMPC_SCHEDULE_MODIFIER_monotonic: 2711 Modifier = OMP_sch_modifier_monotonic; 2712 break; 2713 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2714 Modifier = OMP_sch_modifier_nonmonotonic; 2715 break; 2716 case OMPC_SCHEDULE_MODIFIER_simd: 2717 if (Schedule == OMP_sch_static_chunked) 2718 Schedule = OMP_sch_static_balanced_chunked; 2719 break; 2720 case OMPC_SCHEDULE_MODIFIER_last: 2721 case OMPC_SCHEDULE_MODIFIER_unknown: 2722 break; 2723 } 2724 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 2725 // If the static schedule kind is specified or if the ordered clause is 2726 // specified, and if the nonmonotonic modifier is not specified, the effect is 2727 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 2728 // modifier is specified, the effect is as if the nonmonotonic modifier is 2729 // specified. 2730 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 2731 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 2732 Schedule == OMP_sch_static_balanced_chunked || 2733 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 2734 Schedule == OMP_dist_sch_static_chunked || 2735 Schedule == OMP_dist_sch_static)) 2736 Modifier = OMP_sch_modifier_nonmonotonic; 2737 } 2738 return Schedule | Modifier; 2739 } 2740 2741 void CGOpenMPRuntime::emitForDispatchInit( 2742 CodeGenFunction &CGF, SourceLocation Loc, 2743 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 2744 bool Ordered, const DispatchRTInput &DispatchValues) { 2745 if (!CGF.HaveInsertPoint()) 2746 return; 2747 OpenMPSchedType Schedule = getRuntimeSchedule( 2748 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 2749 assert(Ordered || 2750 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 2751 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 2752 Schedule != OMP_sch_static_balanced_chunked)); 2753 // Call __kmpc_dispatch_init( 2754 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 2755 // kmp_int[32|64] lower, kmp_int[32|64] upper, 2756 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 2757 2758 // If the Chunk was not specified in the clause - use default value 1. 2759 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 2760 : CGF.Builder.getIntN(IVSize, 1); 2761 llvm::Value *Args[] = { 2762 emitUpdateLocation(CGF, Loc), 2763 getThreadID(CGF, Loc), 2764 CGF.Builder.getInt32(addMonoNonMonoModifier( 2765 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 2766 DispatchValues.LB, // Lower 2767 DispatchValues.UB, // Upper 2768 CGF.Builder.getIntN(IVSize, 1), // Stride 2769 Chunk // Chunk 2770 }; 2771 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 2772 } 2773 2774 static void emitForStaticInitCall( 2775 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 2776 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 2777 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 2778 const CGOpenMPRuntime::StaticRTInput &Values) { 2779 if (!CGF.HaveInsertPoint()) 2780 return; 2781 2782 assert(!Values.Ordered); 2783 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 2784 Schedule == OMP_sch_static_balanced_chunked || 2785 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 2786 Schedule == OMP_dist_sch_static || 2787 Schedule == OMP_dist_sch_static_chunked); 2788 2789 // Call __kmpc_for_static_init( 2790 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 2791 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 2792 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 2793 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 2794 llvm::Value *Chunk = Values.Chunk; 2795 if (Chunk == nullptr) { 2796 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 2797 Schedule == OMP_dist_sch_static) && 2798 "expected static non-chunked schedule"); 2799 // If the Chunk was not specified in the clause - use default value 1. 2800 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 2801 } else { 2802 assert((Schedule == OMP_sch_static_chunked || 2803 Schedule == OMP_sch_static_balanced_chunked || 2804 Schedule == OMP_ord_static_chunked || 2805 Schedule == OMP_dist_sch_static_chunked) && 2806 "expected static chunked schedule"); 2807 } 2808 llvm::Value *Args[] = { 2809 UpdateLocation, 2810 ThreadId, 2811 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 2812 M2)), // Schedule type 2813 Values.IL.getPointer(), // &isLastIter 2814 Values.LB.getPointer(), // &LB 2815 Values.UB.getPointer(), // &UB 2816 Values.ST.getPointer(), // &Stride 2817 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 2818 Chunk // Chunk 2819 }; 2820 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 2821 } 2822 2823 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 2824 SourceLocation Loc, 2825 OpenMPDirectiveKind DKind, 2826 const OpenMPScheduleTy &ScheduleKind, 2827 const StaticRTInput &Values) { 2828 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 2829 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 2830 assert(isOpenMPWorksharingDirective(DKind) && 2831 "Expected loop-based or sections-based directive."); 2832 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 2833 isOpenMPLoopDirective(DKind) 2834 ? OMP_IDENT_WORK_LOOP 2835 : OMP_IDENT_WORK_SECTIONS); 2836 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2837 llvm::FunctionCallee StaticInitFunction = 2838 createForStaticInitFunction(Values.IVSize, Values.IVSigned, false); 2839 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2840 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2841 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 2842 } 2843 2844 void CGOpenMPRuntime::emitDistributeStaticInit( 2845 CodeGenFunction &CGF, SourceLocation Loc, 2846 OpenMPDistScheduleClauseKind SchedKind, 2847 const CGOpenMPRuntime::StaticRTInput &Values) { 2848 OpenMPSchedType ScheduleNum = 2849 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 2850 llvm::Value *UpdatedLocation = 2851 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 2852 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2853 llvm::FunctionCallee StaticInitFunction; 2854 bool isGPUDistribute = 2855 CGM.getLangOpts().OpenMPIsDevice && 2856 (CGM.getTriple().isAMDGCN() || CGM.getTriple().isNVPTX()); 2857 StaticInitFunction = createForStaticInitFunction( 2858 Values.IVSize, Values.IVSigned, isGPUDistribute); 2859 2860 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2861 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 2862 OMPC_SCHEDULE_MODIFIER_unknown, Values); 2863 } 2864 2865 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 2866 SourceLocation Loc, 2867 OpenMPDirectiveKind DKind) { 2868 if (!CGF.HaveInsertPoint()) 2869 return; 2870 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 2871 llvm::Value *Args[] = { 2872 emitUpdateLocation(CGF, Loc, 2873 isOpenMPDistributeDirective(DKind) 2874 ? OMP_IDENT_WORK_DISTRIBUTE 2875 : isOpenMPLoopDirective(DKind) 2876 ? OMP_IDENT_WORK_LOOP 2877 : OMP_IDENT_WORK_SECTIONS), 2878 getThreadID(CGF, Loc)}; 2879 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2880 if (isOpenMPDistributeDirective(DKind) && CGM.getLangOpts().OpenMPIsDevice && 2881 (CGM.getTriple().isAMDGCN() || CGM.getTriple().isNVPTX())) 2882 CGF.EmitRuntimeCall( 2883 OMPBuilder.getOrCreateRuntimeFunction( 2884 CGM.getModule(), OMPRTL___kmpc_distribute_static_fini), 2885 Args); 2886 else 2887 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2888 CGM.getModule(), OMPRTL___kmpc_for_static_fini), 2889 Args); 2890 } 2891 2892 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 2893 SourceLocation Loc, 2894 unsigned IVSize, 2895 bool IVSigned) { 2896 if (!CGF.HaveInsertPoint()) 2897 return; 2898 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 2899 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2900 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 2901 } 2902 2903 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 2904 SourceLocation Loc, unsigned IVSize, 2905 bool IVSigned, Address IL, 2906 Address LB, Address UB, 2907 Address ST) { 2908 // Call __kmpc_dispatch_next( 2909 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 2910 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 2911 // kmp_int[32|64] *p_stride); 2912 llvm::Value *Args[] = { 2913 emitUpdateLocation(CGF, Loc), 2914 getThreadID(CGF, Loc), 2915 IL.getPointer(), // &isLastIter 2916 LB.getPointer(), // &Lower 2917 UB.getPointer(), // &Upper 2918 ST.getPointer() // &Stride 2919 }; 2920 llvm::Value *Call = 2921 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 2922 return CGF.EmitScalarConversion( 2923 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 2924 CGF.getContext().BoolTy, Loc); 2925 } 2926 2927 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 2928 llvm::Value *NumThreads, 2929 SourceLocation Loc) { 2930 if (!CGF.HaveInsertPoint()) 2931 return; 2932 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 2933 llvm::Value *Args[] = { 2934 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2935 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 2936 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2937 CGM.getModule(), OMPRTL___kmpc_push_num_threads), 2938 Args); 2939 } 2940 2941 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 2942 ProcBindKind ProcBind, 2943 SourceLocation Loc) { 2944 if (!CGF.HaveInsertPoint()) 2945 return; 2946 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 2947 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 2948 llvm::Value *Args[] = { 2949 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2950 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 2951 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2952 CGM.getModule(), OMPRTL___kmpc_push_proc_bind), 2953 Args); 2954 } 2955 2956 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 2957 SourceLocation Loc, llvm::AtomicOrdering AO) { 2958 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2959 OMPBuilder.createFlush(CGF.Builder); 2960 } else { 2961 if (!CGF.HaveInsertPoint()) 2962 return; 2963 // Build call void __kmpc_flush(ident_t *loc) 2964 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2965 CGM.getModule(), OMPRTL___kmpc_flush), 2966 emitUpdateLocation(CGF, Loc)); 2967 } 2968 } 2969 2970 namespace { 2971 /// Indexes of fields for type kmp_task_t. 2972 enum KmpTaskTFields { 2973 /// List of shared variables. 2974 KmpTaskTShareds, 2975 /// Task routine. 2976 KmpTaskTRoutine, 2977 /// Partition id for the untied tasks. 2978 KmpTaskTPartId, 2979 /// Function with call of destructors for private variables. 2980 Data1, 2981 /// Task priority. 2982 Data2, 2983 /// (Taskloops only) Lower bound. 2984 KmpTaskTLowerBound, 2985 /// (Taskloops only) Upper bound. 2986 KmpTaskTUpperBound, 2987 /// (Taskloops only) Stride. 2988 KmpTaskTStride, 2989 /// (Taskloops only) Is last iteration flag. 2990 KmpTaskTLastIter, 2991 /// (Taskloops only) Reduction data. 2992 KmpTaskTReductions, 2993 }; 2994 } // anonymous namespace 2995 2996 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 2997 return OffloadEntriesTargetRegion.empty() && 2998 OffloadEntriesDeviceGlobalVar.empty(); 2999 } 3000 3001 /// Initialize target region entry. 3002 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3003 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3004 StringRef ParentName, unsigned LineNum, 3005 unsigned Order) { 3006 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3007 "only required for the device " 3008 "code generation."); 3009 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3010 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3011 OMPTargetRegionEntryTargetRegion); 3012 ++OffloadingEntriesNum; 3013 } 3014 3015 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3016 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3017 StringRef ParentName, unsigned LineNum, 3018 llvm::Constant *Addr, llvm::Constant *ID, 3019 OMPTargetRegionEntryKind Flags) { 3020 // If we are emitting code for a target, the entry is already initialized, 3021 // only has to be registered. 3022 if (CGM.getLangOpts().OpenMPIsDevice) { 3023 // This could happen if the device compilation is invoked standalone. 3024 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) 3025 return; 3026 auto &Entry = 3027 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3028 Entry.setAddress(Addr); 3029 Entry.setID(ID); 3030 Entry.setFlags(Flags); 3031 } else { 3032 if (Flags == 3033 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion && 3034 hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum, 3035 /*IgnoreAddressId*/ true)) 3036 return; 3037 assert(!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) && 3038 "Target region entry already registered!"); 3039 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3040 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3041 ++OffloadingEntriesNum; 3042 } 3043 } 3044 3045 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3046 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum, 3047 bool IgnoreAddressId) const { 3048 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3049 if (PerDevice == OffloadEntriesTargetRegion.end()) 3050 return false; 3051 auto PerFile = PerDevice->second.find(FileID); 3052 if (PerFile == PerDevice->second.end()) 3053 return false; 3054 auto PerParentName = PerFile->second.find(ParentName); 3055 if (PerParentName == PerFile->second.end()) 3056 return false; 3057 auto PerLine = PerParentName->second.find(LineNum); 3058 if (PerLine == PerParentName->second.end()) 3059 return false; 3060 // Fail if this entry is already registered. 3061 if (!IgnoreAddressId && 3062 (PerLine->second.getAddress() || PerLine->second.getID())) 3063 return false; 3064 return true; 3065 } 3066 3067 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3068 const OffloadTargetRegionEntryInfoActTy &Action) { 3069 // Scan all target region entries and perform the provided action. 3070 for (const auto &D : OffloadEntriesTargetRegion) 3071 for (const auto &F : D.second) 3072 for (const auto &P : F.second) 3073 for (const auto &L : P.second) 3074 Action(D.first, F.first, P.first(), L.first, L.second); 3075 } 3076 3077 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3078 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3079 OMPTargetGlobalVarEntryKind Flags, 3080 unsigned Order) { 3081 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3082 "only required for the device " 3083 "code generation."); 3084 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3085 ++OffloadingEntriesNum; 3086 } 3087 3088 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3089 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3090 CharUnits VarSize, 3091 OMPTargetGlobalVarEntryKind Flags, 3092 llvm::GlobalValue::LinkageTypes Linkage) { 3093 if (CGM.getLangOpts().OpenMPIsDevice) { 3094 // This could happen if the device compilation is invoked standalone. 3095 if (!hasDeviceGlobalVarEntryInfo(VarName)) 3096 return; 3097 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3098 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3099 if (Entry.getVarSize().isZero()) { 3100 Entry.setVarSize(VarSize); 3101 Entry.setLinkage(Linkage); 3102 } 3103 return; 3104 } 3105 Entry.setVarSize(VarSize); 3106 Entry.setLinkage(Linkage); 3107 Entry.setAddress(Addr); 3108 } else { 3109 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3110 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3111 assert(Entry.isValid() && Entry.getFlags() == Flags && 3112 "Entry not initialized!"); 3113 if (Entry.getVarSize().isZero()) { 3114 Entry.setVarSize(VarSize); 3115 Entry.setLinkage(Linkage); 3116 } 3117 return; 3118 } 3119 OffloadEntriesDeviceGlobalVar.try_emplace( 3120 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3121 ++OffloadingEntriesNum; 3122 } 3123 } 3124 3125 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3126 actOnDeviceGlobalVarEntriesInfo( 3127 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 3128 // Scan all target region entries and perform the provided action. 3129 for (const auto &E : OffloadEntriesDeviceGlobalVar) 3130 Action(E.getKey(), E.getValue()); 3131 } 3132 3133 void CGOpenMPRuntime::createOffloadEntry( 3134 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 3135 llvm::GlobalValue::LinkageTypes Linkage) { 3136 StringRef Name = Addr->getName(); 3137 llvm::Module &M = CGM.getModule(); 3138 llvm::LLVMContext &C = M.getContext(); 3139 3140 // Create constant string with the name. 3141 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 3142 3143 std::string StringName = getName({"omp_offloading", "entry_name"}); 3144 auto *Str = new llvm::GlobalVariable( 3145 M, StrPtrInit->getType(), /*isConstant=*/true, 3146 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 3147 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 3148 3149 llvm::Constant *Data[] = { 3150 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(ID, CGM.VoidPtrTy), 3151 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, CGM.Int8PtrTy), 3152 llvm::ConstantInt::get(CGM.SizeTy, Size), 3153 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 3154 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 3155 std::string EntryName = getName({"omp_offloading", "entry", ""}); 3156 llvm::GlobalVariable *Entry = createGlobalStruct( 3157 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 3158 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 3159 3160 // The entry has to be created in the section the linker expects it to be. 3161 Entry->setSection("omp_offloading_entries"); 3162 } 3163 3164 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 3165 // Emit the offloading entries and metadata so that the device codegen side 3166 // can easily figure out what to emit. The produced metadata looks like 3167 // this: 3168 // 3169 // !omp_offload.info = !{!1, ...} 3170 // 3171 // Right now we only generate metadata for function that contain target 3172 // regions. 3173 3174 // If we are in simd mode or there are no entries, we don't need to do 3175 // anything. 3176 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 3177 return; 3178 3179 llvm::Module &M = CGM.getModule(); 3180 llvm::LLVMContext &C = M.getContext(); 3181 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 3182 SourceLocation, StringRef>, 3183 16> 3184 OrderedEntries(OffloadEntriesInfoManager.size()); 3185 llvm::SmallVector<StringRef, 16> ParentFunctions( 3186 OffloadEntriesInfoManager.size()); 3187 3188 // Auxiliary methods to create metadata values and strings. 3189 auto &&GetMDInt = [this](unsigned V) { 3190 return llvm::ConstantAsMetadata::get( 3191 llvm::ConstantInt::get(CGM.Int32Ty, V)); 3192 }; 3193 3194 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 3195 3196 // Create the offloading info metadata node. 3197 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 3198 3199 // Create function that emits metadata for each target region entry; 3200 auto &&TargetRegionMetadataEmitter = 3201 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 3202 &GetMDString]( 3203 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3204 unsigned Line, 3205 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 3206 // Generate metadata for target regions. Each entry of this metadata 3207 // contains: 3208 // - Entry 0 -> Kind of this type of metadata (0). 3209 // - Entry 1 -> Device ID of the file where the entry was identified. 3210 // - Entry 2 -> File ID of the file where the entry was identified. 3211 // - Entry 3 -> Mangled name of the function where the entry was 3212 // identified. 3213 // - Entry 4 -> Line in the file where the entry was identified. 3214 // - Entry 5 -> Order the entry was created. 3215 // The first element of the metadata node is the kind. 3216 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 3217 GetMDInt(FileID), GetMDString(ParentName), 3218 GetMDInt(Line), GetMDInt(E.getOrder())}; 3219 3220 SourceLocation Loc; 3221 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 3222 E = CGM.getContext().getSourceManager().fileinfo_end(); 3223 I != E; ++I) { 3224 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 3225 I->getFirst()->getUniqueID().getFile() == FileID) { 3226 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 3227 I->getFirst(), Line, 1); 3228 break; 3229 } 3230 } 3231 // Save this entry in the right position of the ordered entries array. 3232 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 3233 ParentFunctions[E.getOrder()] = ParentName; 3234 3235 // Add metadata to the named metadata node. 3236 MD->addOperand(llvm::MDNode::get(C, Ops)); 3237 }; 3238 3239 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 3240 TargetRegionMetadataEmitter); 3241 3242 // Create function that emits metadata for each device global variable entry; 3243 auto &&DeviceGlobalVarMetadataEmitter = 3244 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 3245 MD](StringRef MangledName, 3246 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 3247 &E) { 3248 // Generate metadata for global variables. Each entry of this metadata 3249 // contains: 3250 // - Entry 0 -> Kind of this type of metadata (1). 3251 // - Entry 1 -> Mangled name of the variable. 3252 // - Entry 2 -> Declare target kind. 3253 // - Entry 3 -> Order the entry was created. 3254 // The first element of the metadata node is the kind. 3255 llvm::Metadata *Ops[] = { 3256 GetMDInt(E.getKind()), GetMDString(MangledName), 3257 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 3258 3259 // Save this entry in the right position of the ordered entries array. 3260 OrderedEntries[E.getOrder()] = 3261 std::make_tuple(&E, SourceLocation(), MangledName); 3262 3263 // Add metadata to the named metadata node. 3264 MD->addOperand(llvm::MDNode::get(C, Ops)); 3265 }; 3266 3267 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 3268 DeviceGlobalVarMetadataEmitter); 3269 3270 for (const auto &E : OrderedEntries) { 3271 assert(std::get<0>(E) && "All ordered entries must exist!"); 3272 if (const auto *CE = 3273 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 3274 std::get<0>(E))) { 3275 if (!CE->getID() || !CE->getAddress()) { 3276 // Do not blame the entry if the parent funtion is not emitted. 3277 StringRef FnName = ParentFunctions[CE->getOrder()]; 3278 if (!CGM.GetGlobalValue(FnName)) 3279 continue; 3280 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3281 DiagnosticsEngine::Error, 3282 "Offloading entry for target region in %0 is incorrect: either the " 3283 "address or the ID is invalid."); 3284 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 3285 continue; 3286 } 3287 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 3288 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 3289 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 3290 OffloadEntryInfoDeviceGlobalVar>( 3291 std::get<0>(E))) { 3292 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 3293 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3294 CE->getFlags()); 3295 switch (Flags) { 3296 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 3297 if (CGM.getLangOpts().OpenMPIsDevice && 3298 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 3299 continue; 3300 if (!CE->getAddress()) { 3301 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3302 DiagnosticsEngine::Error, "Offloading entry for declare target " 3303 "variable %0 is incorrect: the " 3304 "address is invalid."); 3305 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 3306 continue; 3307 } 3308 // The vaiable has no definition - no need to add the entry. 3309 if (CE->getVarSize().isZero()) 3310 continue; 3311 break; 3312 } 3313 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 3314 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 3315 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 3316 "Declaret target link address is set."); 3317 if (CGM.getLangOpts().OpenMPIsDevice) 3318 continue; 3319 if (!CE->getAddress()) { 3320 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3321 DiagnosticsEngine::Error, 3322 "Offloading entry for declare target variable is incorrect: the " 3323 "address is invalid."); 3324 CGM.getDiags().Report(DiagID); 3325 continue; 3326 } 3327 break; 3328 } 3329 createOffloadEntry(CE->getAddress(), CE->getAddress(), 3330 CE->getVarSize().getQuantity(), Flags, 3331 CE->getLinkage()); 3332 } else { 3333 llvm_unreachable("Unsupported entry kind."); 3334 } 3335 } 3336 } 3337 3338 /// Loads all the offload entries information from the host IR 3339 /// metadata. 3340 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 3341 // If we are in target mode, load the metadata from the host IR. This code has 3342 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 3343 3344 if (!CGM.getLangOpts().OpenMPIsDevice) 3345 return; 3346 3347 if (CGM.getLangOpts().OMPHostIRFile.empty()) 3348 return; 3349 3350 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 3351 if (auto EC = Buf.getError()) { 3352 CGM.getDiags().Report(diag::err_cannot_open_file) 3353 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3354 return; 3355 } 3356 3357 llvm::LLVMContext C; 3358 auto ME = expectedToErrorOrAndEmitErrors( 3359 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 3360 3361 if (auto EC = ME.getError()) { 3362 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3363 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 3364 CGM.getDiags().Report(DiagID) 3365 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3366 return; 3367 } 3368 3369 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 3370 if (!MD) 3371 return; 3372 3373 for (llvm::MDNode *MN : MD->operands()) { 3374 auto &&GetMDInt = [MN](unsigned Idx) { 3375 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 3376 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 3377 }; 3378 3379 auto &&GetMDString = [MN](unsigned Idx) { 3380 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 3381 return V->getString(); 3382 }; 3383 3384 switch (GetMDInt(0)) { 3385 default: 3386 llvm_unreachable("Unexpected metadata!"); 3387 break; 3388 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3389 OffloadingEntryInfoTargetRegion: 3390 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 3391 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 3392 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 3393 /*Order=*/GetMDInt(5)); 3394 break; 3395 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3396 OffloadingEntryInfoDeviceGlobalVar: 3397 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 3398 /*MangledName=*/GetMDString(1), 3399 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3400 /*Flags=*/GetMDInt(2)), 3401 /*Order=*/GetMDInt(3)); 3402 break; 3403 } 3404 } 3405 } 3406 3407 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 3408 if (!KmpRoutineEntryPtrTy) { 3409 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 3410 ASTContext &C = CGM.getContext(); 3411 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 3412 FunctionProtoType::ExtProtoInfo EPI; 3413 KmpRoutineEntryPtrQTy = C.getPointerType( 3414 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 3415 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 3416 } 3417 } 3418 3419 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 3420 // Make sure the type of the entry is already created. This is the type we 3421 // have to create: 3422 // struct __tgt_offload_entry{ 3423 // void *addr; // Pointer to the offload entry info. 3424 // // (function or global) 3425 // char *name; // Name of the function or global. 3426 // size_t size; // Size of the entry info (0 if it a function). 3427 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 3428 // int32_t reserved; // Reserved, to use by the runtime library. 3429 // }; 3430 if (TgtOffloadEntryQTy.isNull()) { 3431 ASTContext &C = CGM.getContext(); 3432 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 3433 RD->startDefinition(); 3434 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3435 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 3436 addFieldToRecordDecl(C, RD, C.getSizeType()); 3437 addFieldToRecordDecl( 3438 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3439 addFieldToRecordDecl( 3440 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3441 RD->completeDefinition(); 3442 RD->addAttr(PackedAttr::CreateImplicit(C)); 3443 TgtOffloadEntryQTy = C.getRecordType(RD); 3444 } 3445 return TgtOffloadEntryQTy; 3446 } 3447 3448 namespace { 3449 struct PrivateHelpersTy { 3450 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original, 3451 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit) 3452 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy), 3453 PrivateElemInit(PrivateElemInit) {} 3454 PrivateHelpersTy(const VarDecl *Original) : Original(Original) {} 3455 const Expr *OriginalRef = nullptr; 3456 const VarDecl *Original = nullptr; 3457 const VarDecl *PrivateCopy = nullptr; 3458 const VarDecl *PrivateElemInit = nullptr; 3459 bool isLocalPrivate() const { 3460 return !OriginalRef && !PrivateCopy && !PrivateElemInit; 3461 } 3462 }; 3463 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 3464 } // anonymous namespace 3465 3466 static bool isAllocatableDecl(const VarDecl *VD) { 3467 const VarDecl *CVD = VD->getCanonicalDecl(); 3468 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 3469 return false; 3470 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 3471 // Use the default allocation. 3472 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc || 3473 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) && 3474 !AA->getAllocator()); 3475 } 3476 3477 static RecordDecl * 3478 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 3479 if (!Privates.empty()) { 3480 ASTContext &C = CGM.getContext(); 3481 // Build struct .kmp_privates_t. { 3482 // /* private vars */ 3483 // }; 3484 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 3485 RD->startDefinition(); 3486 for (const auto &Pair : Privates) { 3487 const VarDecl *VD = Pair.second.Original; 3488 QualType Type = VD->getType().getNonReferenceType(); 3489 // If the private variable is a local variable with lvalue ref type, 3490 // allocate the pointer instead of the pointee type. 3491 if (Pair.second.isLocalPrivate()) { 3492 if (VD->getType()->isLValueReferenceType()) 3493 Type = C.getPointerType(Type); 3494 if (isAllocatableDecl(VD)) 3495 Type = C.getPointerType(Type); 3496 } 3497 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 3498 if (VD->hasAttrs()) { 3499 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 3500 E(VD->getAttrs().end()); 3501 I != E; ++I) 3502 FD->addAttr(*I); 3503 } 3504 } 3505 RD->completeDefinition(); 3506 return RD; 3507 } 3508 return nullptr; 3509 } 3510 3511 static RecordDecl * 3512 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 3513 QualType KmpInt32Ty, 3514 QualType KmpRoutineEntryPointerQTy) { 3515 ASTContext &C = CGM.getContext(); 3516 // Build struct kmp_task_t { 3517 // void * shareds; 3518 // kmp_routine_entry_t routine; 3519 // kmp_int32 part_id; 3520 // kmp_cmplrdata_t data1; 3521 // kmp_cmplrdata_t data2; 3522 // For taskloops additional fields: 3523 // kmp_uint64 lb; 3524 // kmp_uint64 ub; 3525 // kmp_int64 st; 3526 // kmp_int32 liter; 3527 // void * reductions; 3528 // }; 3529 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 3530 UD->startDefinition(); 3531 addFieldToRecordDecl(C, UD, KmpInt32Ty); 3532 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 3533 UD->completeDefinition(); 3534 QualType KmpCmplrdataTy = C.getRecordType(UD); 3535 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 3536 RD->startDefinition(); 3537 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3538 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 3539 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3540 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3541 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3542 if (isOpenMPTaskLoopDirective(Kind)) { 3543 QualType KmpUInt64Ty = 3544 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 3545 QualType KmpInt64Ty = 3546 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 3547 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3548 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3549 addFieldToRecordDecl(C, RD, KmpInt64Ty); 3550 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3551 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3552 } 3553 RD->completeDefinition(); 3554 return RD; 3555 } 3556 3557 static RecordDecl * 3558 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 3559 ArrayRef<PrivateDataTy> Privates) { 3560 ASTContext &C = CGM.getContext(); 3561 // Build struct kmp_task_t_with_privates { 3562 // kmp_task_t task_data; 3563 // .kmp_privates_t. privates; 3564 // }; 3565 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 3566 RD->startDefinition(); 3567 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 3568 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 3569 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 3570 RD->completeDefinition(); 3571 return RD; 3572 } 3573 3574 /// Emit a proxy function which accepts kmp_task_t as the second 3575 /// argument. 3576 /// \code 3577 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 3578 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 3579 /// For taskloops: 3580 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3581 /// tt->reductions, tt->shareds); 3582 /// return 0; 3583 /// } 3584 /// \endcode 3585 static llvm::Function * 3586 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 3587 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 3588 QualType KmpTaskTWithPrivatesPtrQTy, 3589 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 3590 QualType SharedsPtrTy, llvm::Function *TaskFunction, 3591 llvm::Value *TaskPrivatesMap) { 3592 ASTContext &C = CGM.getContext(); 3593 FunctionArgList Args; 3594 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3595 ImplicitParamDecl::Other); 3596 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3597 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3598 ImplicitParamDecl::Other); 3599 Args.push_back(&GtidArg); 3600 Args.push_back(&TaskTypeArg); 3601 const auto &TaskEntryFnInfo = 3602 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3603 llvm::FunctionType *TaskEntryTy = 3604 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 3605 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 3606 auto *TaskEntry = llvm::Function::Create( 3607 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3608 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 3609 TaskEntry->setDoesNotRecurse(); 3610 CodeGenFunction CGF(CGM); 3611 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 3612 Loc, Loc); 3613 3614 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 3615 // tt, 3616 // For taskloops: 3617 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3618 // tt->task_data.shareds); 3619 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 3620 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 3621 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3622 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3623 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3624 const auto *KmpTaskTWithPrivatesQTyRD = 3625 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3626 LValue Base = 3627 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3628 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3629 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 3630 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 3631 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 3632 3633 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 3634 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 3635 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3636 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 3637 CGF.ConvertTypeForMem(SharedsPtrTy)); 3638 3639 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 3640 llvm::Value *PrivatesParam; 3641 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 3642 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 3643 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3644 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 3645 } else { 3646 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3647 } 3648 3649 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 3650 TaskPrivatesMap, 3651 CGF.Builder 3652 .CreatePointerBitCastOrAddrSpaceCast( 3653 TDBase.getAddress(CGF), CGF.VoidPtrTy) 3654 .getPointer()}; 3655 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 3656 std::end(CommonArgs)); 3657 if (isOpenMPTaskLoopDirective(Kind)) { 3658 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 3659 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 3660 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 3661 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 3662 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 3663 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 3664 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 3665 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 3666 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 3667 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3668 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3669 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 3670 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 3671 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 3672 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 3673 CallArgs.push_back(LBParam); 3674 CallArgs.push_back(UBParam); 3675 CallArgs.push_back(StParam); 3676 CallArgs.push_back(LIParam); 3677 CallArgs.push_back(RParam); 3678 } 3679 CallArgs.push_back(SharedsParam); 3680 3681 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 3682 CallArgs); 3683 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 3684 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 3685 CGF.FinishFunction(); 3686 return TaskEntry; 3687 } 3688 3689 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 3690 SourceLocation Loc, 3691 QualType KmpInt32Ty, 3692 QualType KmpTaskTWithPrivatesPtrQTy, 3693 QualType KmpTaskTWithPrivatesQTy) { 3694 ASTContext &C = CGM.getContext(); 3695 FunctionArgList Args; 3696 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3697 ImplicitParamDecl::Other); 3698 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3699 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3700 ImplicitParamDecl::Other); 3701 Args.push_back(&GtidArg); 3702 Args.push_back(&TaskTypeArg); 3703 const auto &DestructorFnInfo = 3704 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3705 llvm::FunctionType *DestructorFnTy = 3706 CGM.getTypes().GetFunctionType(DestructorFnInfo); 3707 std::string Name = 3708 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 3709 auto *DestructorFn = 3710 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 3711 Name, &CGM.getModule()); 3712 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 3713 DestructorFnInfo); 3714 DestructorFn->setDoesNotRecurse(); 3715 CodeGenFunction CGF(CGM); 3716 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 3717 Args, Loc, Loc); 3718 3719 LValue Base = CGF.EmitLoadOfPointerLValue( 3720 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3721 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3722 const auto *KmpTaskTWithPrivatesQTyRD = 3723 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3724 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3725 Base = CGF.EmitLValueForField(Base, *FI); 3726 for (const auto *Field : 3727 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 3728 if (QualType::DestructionKind DtorKind = 3729 Field->getType().isDestructedType()) { 3730 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 3731 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 3732 } 3733 } 3734 CGF.FinishFunction(); 3735 return DestructorFn; 3736 } 3737 3738 /// Emit a privates mapping function for correct handling of private and 3739 /// firstprivate variables. 3740 /// \code 3741 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 3742 /// **noalias priv1,..., <tyn> **noalias privn) { 3743 /// *priv1 = &.privates.priv1; 3744 /// ...; 3745 /// *privn = &.privates.privn; 3746 /// } 3747 /// \endcode 3748 static llvm::Value * 3749 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 3750 const OMPTaskDataTy &Data, QualType PrivatesQTy, 3751 ArrayRef<PrivateDataTy> Privates) { 3752 ASTContext &C = CGM.getContext(); 3753 FunctionArgList Args; 3754 ImplicitParamDecl TaskPrivatesArg( 3755 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3756 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 3757 ImplicitParamDecl::Other); 3758 Args.push_back(&TaskPrivatesArg); 3759 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, unsigned> PrivateVarsPos; 3760 unsigned Counter = 1; 3761 for (const Expr *E : Data.PrivateVars) { 3762 Args.push_back(ImplicitParamDecl::Create( 3763 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3764 C.getPointerType(C.getPointerType(E->getType())) 3765 .withConst() 3766 .withRestrict(), 3767 ImplicitParamDecl::Other)); 3768 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3769 PrivateVarsPos[VD] = Counter; 3770 ++Counter; 3771 } 3772 for (const Expr *E : Data.FirstprivateVars) { 3773 Args.push_back(ImplicitParamDecl::Create( 3774 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3775 C.getPointerType(C.getPointerType(E->getType())) 3776 .withConst() 3777 .withRestrict(), 3778 ImplicitParamDecl::Other)); 3779 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3780 PrivateVarsPos[VD] = Counter; 3781 ++Counter; 3782 } 3783 for (const Expr *E : Data.LastprivateVars) { 3784 Args.push_back(ImplicitParamDecl::Create( 3785 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3786 C.getPointerType(C.getPointerType(E->getType())) 3787 .withConst() 3788 .withRestrict(), 3789 ImplicitParamDecl::Other)); 3790 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3791 PrivateVarsPos[VD] = Counter; 3792 ++Counter; 3793 } 3794 for (const VarDecl *VD : Data.PrivateLocals) { 3795 QualType Ty = VD->getType().getNonReferenceType(); 3796 if (VD->getType()->isLValueReferenceType()) 3797 Ty = C.getPointerType(Ty); 3798 if (isAllocatableDecl(VD)) 3799 Ty = C.getPointerType(Ty); 3800 Args.push_back(ImplicitParamDecl::Create( 3801 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3802 C.getPointerType(C.getPointerType(Ty)).withConst().withRestrict(), 3803 ImplicitParamDecl::Other)); 3804 PrivateVarsPos[VD] = Counter; 3805 ++Counter; 3806 } 3807 const auto &TaskPrivatesMapFnInfo = 3808 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3809 llvm::FunctionType *TaskPrivatesMapTy = 3810 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 3811 std::string Name = 3812 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 3813 auto *TaskPrivatesMap = llvm::Function::Create( 3814 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 3815 &CGM.getModule()); 3816 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 3817 TaskPrivatesMapFnInfo); 3818 if (CGM.getLangOpts().Optimize) { 3819 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 3820 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 3821 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 3822 } 3823 CodeGenFunction CGF(CGM); 3824 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 3825 TaskPrivatesMapFnInfo, Args, Loc, Loc); 3826 3827 // *privi = &.privates.privi; 3828 LValue Base = CGF.EmitLoadOfPointerLValue( 3829 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 3830 TaskPrivatesArg.getType()->castAs<PointerType>()); 3831 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 3832 Counter = 0; 3833 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 3834 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 3835 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 3836 LValue RefLVal = 3837 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 3838 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 3839 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 3840 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 3841 ++Counter; 3842 } 3843 CGF.FinishFunction(); 3844 return TaskPrivatesMap; 3845 } 3846 3847 /// Emit initialization for private variables in task-based directives. 3848 static void emitPrivatesInit(CodeGenFunction &CGF, 3849 const OMPExecutableDirective &D, 3850 Address KmpTaskSharedsPtr, LValue TDBase, 3851 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3852 QualType SharedsTy, QualType SharedsPtrTy, 3853 const OMPTaskDataTy &Data, 3854 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 3855 ASTContext &C = CGF.getContext(); 3856 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3857 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 3858 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 3859 ? OMPD_taskloop 3860 : OMPD_task; 3861 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 3862 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 3863 LValue SrcBase; 3864 bool IsTargetTask = 3865 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 3866 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 3867 // For target-based directives skip 4 firstprivate arrays BasePointersArray, 3868 // PointersArray, SizesArray, and MappersArray. The original variables for 3869 // these arrays are not captured and we get their addresses explicitly. 3870 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) || 3871 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 3872 SrcBase = CGF.MakeAddrLValue( 3873 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3874 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 3875 SharedsTy); 3876 } 3877 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 3878 for (const PrivateDataTy &Pair : Privates) { 3879 // Do not initialize private locals. 3880 if (Pair.second.isLocalPrivate()) { 3881 ++FI; 3882 continue; 3883 } 3884 const VarDecl *VD = Pair.second.PrivateCopy; 3885 const Expr *Init = VD->getAnyInitializer(); 3886 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 3887 !CGF.isTrivialInitializer(Init)))) { 3888 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 3889 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 3890 const VarDecl *OriginalVD = Pair.second.Original; 3891 // Check if the variable is the target-based BasePointersArray, 3892 // PointersArray, SizesArray, or MappersArray. 3893 LValue SharedRefLValue; 3894 QualType Type = PrivateLValue.getType(); 3895 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 3896 if (IsTargetTask && !SharedField) { 3897 assert(isa<ImplicitParamDecl>(OriginalVD) && 3898 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 3899 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3900 ->getNumParams() == 0 && 3901 isa<TranslationUnitDecl>( 3902 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3903 ->getDeclContext()) && 3904 "Expected artificial target data variable."); 3905 SharedRefLValue = 3906 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 3907 } else if (ForDup) { 3908 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 3909 SharedRefLValue = CGF.MakeAddrLValue( 3910 Address(SharedRefLValue.getPointer(CGF), 3911 C.getDeclAlign(OriginalVD)), 3912 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 3913 SharedRefLValue.getTBAAInfo()); 3914 } else if (CGF.LambdaCaptureFields.count( 3915 Pair.second.Original->getCanonicalDecl()) > 0 || 3916 dyn_cast_or_null<BlockDecl>(CGF.CurCodeDecl)) { 3917 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3918 } else { 3919 // Processing for implicitly captured variables. 3920 InlinedOpenMPRegionRAII Region( 3921 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown, 3922 /*HasCancel=*/false, /*NoInheritance=*/true); 3923 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3924 } 3925 if (Type->isArrayType()) { 3926 // Initialize firstprivate array. 3927 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 3928 // Perform simple memcpy. 3929 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 3930 } else { 3931 // Initialize firstprivate array using element-by-element 3932 // initialization. 3933 CGF.EmitOMPAggregateAssign( 3934 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 3935 Type, 3936 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 3937 Address SrcElement) { 3938 // Clean up any temporaries needed by the initialization. 3939 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3940 InitScope.addPrivate( 3941 Elem, [SrcElement]() -> Address { return SrcElement; }); 3942 (void)InitScope.Privatize(); 3943 // Emit initialization for single element. 3944 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 3945 CGF, &CapturesInfo); 3946 CGF.EmitAnyExprToMem(Init, DestElement, 3947 Init->getType().getQualifiers(), 3948 /*IsInitializer=*/false); 3949 }); 3950 } 3951 } else { 3952 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3953 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 3954 return SharedRefLValue.getAddress(CGF); 3955 }); 3956 (void)InitScope.Privatize(); 3957 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 3958 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 3959 /*capturedByInit=*/false); 3960 } 3961 } else { 3962 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 3963 } 3964 } 3965 ++FI; 3966 } 3967 } 3968 3969 /// Check if duplication function is required for taskloops. 3970 static bool checkInitIsRequired(CodeGenFunction &CGF, 3971 ArrayRef<PrivateDataTy> Privates) { 3972 bool InitRequired = false; 3973 for (const PrivateDataTy &Pair : Privates) { 3974 if (Pair.second.isLocalPrivate()) 3975 continue; 3976 const VarDecl *VD = Pair.second.PrivateCopy; 3977 const Expr *Init = VD->getAnyInitializer(); 3978 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 3979 !CGF.isTrivialInitializer(Init)); 3980 if (InitRequired) 3981 break; 3982 } 3983 return InitRequired; 3984 } 3985 3986 3987 /// Emit task_dup function (for initialization of 3988 /// private/firstprivate/lastprivate vars and last_iter flag) 3989 /// \code 3990 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 3991 /// lastpriv) { 3992 /// // setup lastprivate flag 3993 /// task_dst->last = lastpriv; 3994 /// // could be constructor calls here... 3995 /// } 3996 /// \endcode 3997 static llvm::Value * 3998 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 3999 const OMPExecutableDirective &D, 4000 QualType KmpTaskTWithPrivatesPtrQTy, 4001 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4002 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4003 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4004 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4005 ASTContext &C = CGM.getContext(); 4006 FunctionArgList Args; 4007 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4008 KmpTaskTWithPrivatesPtrQTy, 4009 ImplicitParamDecl::Other); 4010 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4011 KmpTaskTWithPrivatesPtrQTy, 4012 ImplicitParamDecl::Other); 4013 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4014 ImplicitParamDecl::Other); 4015 Args.push_back(&DstArg); 4016 Args.push_back(&SrcArg); 4017 Args.push_back(&LastprivArg); 4018 const auto &TaskDupFnInfo = 4019 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4020 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4021 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4022 auto *TaskDup = llvm::Function::Create( 4023 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4024 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4025 TaskDup->setDoesNotRecurse(); 4026 CodeGenFunction CGF(CGM); 4027 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4028 Loc); 4029 4030 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4031 CGF.GetAddrOfLocalVar(&DstArg), 4032 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4033 // task_dst->liter = lastpriv; 4034 if (WithLastIter) { 4035 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4036 LValue Base = CGF.EmitLValueForField( 4037 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4038 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4039 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4040 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4041 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4042 } 4043 4044 // Emit initial values for private copies (if any). 4045 assert(!Privates.empty()); 4046 Address KmpTaskSharedsPtr = Address::invalid(); 4047 if (!Data.FirstprivateVars.empty()) { 4048 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4049 CGF.GetAddrOfLocalVar(&SrcArg), 4050 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4051 LValue Base = CGF.EmitLValueForField( 4052 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4053 KmpTaskSharedsPtr = Address( 4054 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4055 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4056 KmpTaskTShareds)), 4057 Loc), 4058 CGM.getNaturalTypeAlignment(SharedsTy)); 4059 } 4060 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4061 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4062 CGF.FinishFunction(); 4063 return TaskDup; 4064 } 4065 4066 /// Checks if destructor function is required to be generated. 4067 /// \return true if cleanups are required, false otherwise. 4068 static bool 4069 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4070 ArrayRef<PrivateDataTy> Privates) { 4071 for (const PrivateDataTy &P : Privates) { 4072 if (P.second.isLocalPrivate()) 4073 continue; 4074 QualType Ty = P.second.Original->getType().getNonReferenceType(); 4075 if (Ty.isDestructedType()) 4076 return true; 4077 } 4078 return false; 4079 } 4080 4081 namespace { 4082 /// Loop generator for OpenMP iterator expression. 4083 class OMPIteratorGeneratorScope final 4084 : public CodeGenFunction::OMPPrivateScope { 4085 CodeGenFunction &CGF; 4086 const OMPIteratorExpr *E = nullptr; 4087 SmallVector<CodeGenFunction::JumpDest, 4> ContDests; 4088 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests; 4089 OMPIteratorGeneratorScope() = delete; 4090 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete; 4091 4092 public: 4093 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E) 4094 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) { 4095 if (!E) 4096 return; 4097 SmallVector<llvm::Value *, 4> Uppers; 4098 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4099 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper)); 4100 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I)); 4101 addPrivate(VD, [&CGF, VD]() { 4102 return CGF.CreateMemTemp(VD->getType(), VD->getName()); 4103 }); 4104 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4105 addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() { 4106 return CGF.CreateMemTemp(HelperData.CounterVD->getType(), 4107 "counter.addr"); 4108 }); 4109 } 4110 Privatize(); 4111 4112 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4113 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4114 LValue CLVal = 4115 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD), 4116 HelperData.CounterVD->getType()); 4117 // Counter = 0; 4118 CGF.EmitStoreOfScalar( 4119 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0), 4120 CLVal); 4121 CodeGenFunction::JumpDest &ContDest = 4122 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont")); 4123 CodeGenFunction::JumpDest &ExitDest = 4124 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit")); 4125 // N = <number-of_iterations>; 4126 llvm::Value *N = Uppers[I]; 4127 // cont: 4128 // if (Counter < N) goto body; else goto exit; 4129 CGF.EmitBlock(ContDest.getBlock()); 4130 auto *CVal = 4131 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation()); 4132 llvm::Value *Cmp = 4133 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType() 4134 ? CGF.Builder.CreateICmpSLT(CVal, N) 4135 : CGF.Builder.CreateICmpULT(CVal, N); 4136 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body"); 4137 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock()); 4138 // body: 4139 CGF.EmitBlock(BodyBB); 4140 // Iteri = Begini + Counter * Stepi; 4141 CGF.EmitIgnoredExpr(HelperData.Update); 4142 } 4143 } 4144 ~OMPIteratorGeneratorScope() { 4145 if (!E) 4146 return; 4147 for (unsigned I = E->numOfIterators(); I > 0; --I) { 4148 // Counter = Counter + 1; 4149 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1); 4150 CGF.EmitIgnoredExpr(HelperData.CounterUpdate); 4151 // goto cont; 4152 CGF.EmitBranchThroughCleanup(ContDests[I - 1]); 4153 // exit: 4154 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1); 4155 } 4156 } 4157 }; 4158 } // namespace 4159 4160 static std::pair<llvm::Value *, llvm::Value *> 4161 getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { 4162 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E); 4163 llvm::Value *Addr; 4164 if (OASE) { 4165 const Expr *Base = OASE->getBase(); 4166 Addr = CGF.EmitScalarExpr(Base); 4167 } else { 4168 Addr = CGF.EmitLValue(E).getPointer(CGF); 4169 } 4170 llvm::Value *SizeVal; 4171 QualType Ty = E->getType(); 4172 if (OASE) { 4173 SizeVal = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType()); 4174 for (const Expr *SE : OASE->getDimensions()) { 4175 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 4176 Sz = CGF.EmitScalarConversion( 4177 Sz, SE->getType(), CGF.getContext().getSizeType(), SE->getExprLoc()); 4178 SizeVal = CGF.Builder.CreateNUWMul(SizeVal, Sz); 4179 } 4180 } else if (const auto *ASE = 4181 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 4182 LValue UpAddrLVal = 4183 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 4184 Address UpAddrAddress = UpAddrLVal.getAddress(CGF); 4185 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 4186 UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1); 4187 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); 4188 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); 4189 SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 4190 } else { 4191 SizeVal = CGF.getTypeSize(Ty); 4192 } 4193 return std::make_pair(Addr, SizeVal); 4194 } 4195 4196 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4197 static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) { 4198 QualType FlagsTy = C.getIntTypeForBitwidth(32, /*Signed=*/false); 4199 if (KmpTaskAffinityInfoTy.isNull()) { 4200 RecordDecl *KmpAffinityInfoRD = 4201 C.buildImplicitRecord("kmp_task_affinity_info_t"); 4202 KmpAffinityInfoRD->startDefinition(); 4203 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getIntPtrType()); 4204 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType()); 4205 addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy); 4206 KmpAffinityInfoRD->completeDefinition(); 4207 KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD); 4208 } 4209 } 4210 4211 CGOpenMPRuntime::TaskResultTy 4212 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4213 const OMPExecutableDirective &D, 4214 llvm::Function *TaskFunction, QualType SharedsTy, 4215 Address Shareds, const OMPTaskDataTy &Data) { 4216 ASTContext &C = CGM.getContext(); 4217 llvm::SmallVector<PrivateDataTy, 4> Privates; 4218 // Aggregate privates and sort them by the alignment. 4219 const auto *I = Data.PrivateCopies.begin(); 4220 for (const Expr *E : Data.PrivateVars) { 4221 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4222 Privates.emplace_back( 4223 C.getDeclAlign(VD), 4224 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4225 /*PrivateElemInit=*/nullptr)); 4226 ++I; 4227 } 4228 I = Data.FirstprivateCopies.begin(); 4229 const auto *IElemInitRef = Data.FirstprivateInits.begin(); 4230 for (const Expr *E : Data.FirstprivateVars) { 4231 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4232 Privates.emplace_back( 4233 C.getDeclAlign(VD), 4234 PrivateHelpersTy( 4235 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4236 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4237 ++I; 4238 ++IElemInitRef; 4239 } 4240 I = Data.LastprivateCopies.begin(); 4241 for (const Expr *E : Data.LastprivateVars) { 4242 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4243 Privates.emplace_back( 4244 C.getDeclAlign(VD), 4245 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4246 /*PrivateElemInit=*/nullptr)); 4247 ++I; 4248 } 4249 for (const VarDecl *VD : Data.PrivateLocals) { 4250 if (isAllocatableDecl(VD)) 4251 Privates.emplace_back(CGM.getPointerAlign(), PrivateHelpersTy(VD)); 4252 else 4253 Privates.emplace_back(C.getDeclAlign(VD), PrivateHelpersTy(VD)); 4254 } 4255 llvm::stable_sort(Privates, 4256 [](const PrivateDataTy &L, const PrivateDataTy &R) { 4257 return L.first > R.first; 4258 }); 4259 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4260 // Build type kmp_routine_entry_t (if not built yet). 4261 emitKmpRoutineEntryT(KmpInt32Ty); 4262 // Build type kmp_task_t (if not built yet). 4263 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 4264 if (SavedKmpTaskloopTQTy.isNull()) { 4265 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4266 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4267 } 4268 KmpTaskTQTy = SavedKmpTaskloopTQTy; 4269 } else { 4270 assert((D.getDirectiveKind() == OMPD_task || 4271 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 4272 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 4273 "Expected taskloop, task or target directive"); 4274 if (SavedKmpTaskTQTy.isNull()) { 4275 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4276 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4277 } 4278 KmpTaskTQTy = SavedKmpTaskTQTy; 4279 } 4280 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4281 // Build particular struct kmp_task_t for the given task. 4282 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 4283 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 4284 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 4285 QualType KmpTaskTWithPrivatesPtrQTy = 4286 C.getPointerType(KmpTaskTWithPrivatesQTy); 4287 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 4288 llvm::Type *KmpTaskTWithPrivatesPtrTy = 4289 KmpTaskTWithPrivatesTy->getPointerTo(); 4290 llvm::Value *KmpTaskTWithPrivatesTySize = 4291 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 4292 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 4293 4294 // Emit initial values for private copies (if any). 4295 llvm::Value *TaskPrivatesMap = nullptr; 4296 llvm::Type *TaskPrivatesMapTy = 4297 std::next(TaskFunction->arg_begin(), 3)->getType(); 4298 if (!Privates.empty()) { 4299 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4300 TaskPrivatesMap = 4301 emitTaskPrivateMappingFunction(CGM, Loc, Data, FI->getType(), Privates); 4302 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4303 TaskPrivatesMap, TaskPrivatesMapTy); 4304 } else { 4305 TaskPrivatesMap = llvm::ConstantPointerNull::get( 4306 cast<llvm::PointerType>(TaskPrivatesMapTy)); 4307 } 4308 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 4309 // kmp_task_t *tt); 4310 llvm::Function *TaskEntry = emitProxyTaskFunction( 4311 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4312 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 4313 TaskPrivatesMap); 4314 4315 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 4316 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 4317 // kmp_routine_entry_t *task_entry); 4318 // Task flags. Format is taken from 4319 // https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h, 4320 // description of kmp_tasking_flags struct. 4321 enum { 4322 TiedFlag = 0x1, 4323 FinalFlag = 0x2, 4324 DestructorsFlag = 0x8, 4325 PriorityFlag = 0x20, 4326 DetachableFlag = 0x40, 4327 }; 4328 unsigned Flags = Data.Tied ? TiedFlag : 0; 4329 bool NeedsCleanup = false; 4330 if (!Privates.empty()) { 4331 NeedsCleanup = 4332 checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD, Privates); 4333 if (NeedsCleanup) 4334 Flags = Flags | DestructorsFlag; 4335 } 4336 if (Data.Priority.getInt()) 4337 Flags = Flags | PriorityFlag; 4338 if (D.hasClausesOfKind<OMPDetachClause>()) 4339 Flags = Flags | DetachableFlag; 4340 llvm::Value *TaskFlags = 4341 Data.Final.getPointer() 4342 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 4343 CGF.Builder.getInt32(FinalFlag), 4344 CGF.Builder.getInt32(/*C=*/0)) 4345 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 4346 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 4347 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 4348 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 4349 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 4350 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4351 TaskEntry, KmpRoutineEntryPtrTy)}; 4352 llvm::Value *NewTask; 4353 if (D.hasClausesOfKind<OMPNowaitClause>()) { 4354 // Check if we have any device clause associated with the directive. 4355 const Expr *Device = nullptr; 4356 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 4357 Device = C->getDevice(); 4358 // Emit device ID if any otherwise use default value. 4359 llvm::Value *DeviceID; 4360 if (Device) 4361 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 4362 CGF.Int64Ty, /*isSigned=*/true); 4363 else 4364 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 4365 AllocArgs.push_back(DeviceID); 4366 NewTask = CGF.EmitRuntimeCall( 4367 OMPBuilder.getOrCreateRuntimeFunction( 4368 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc), 4369 AllocArgs); 4370 } else { 4371 NewTask = 4372 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 4373 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc), 4374 AllocArgs); 4375 } 4376 // Emit detach clause initialization. 4377 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid, 4378 // task_descriptor); 4379 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) { 4380 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts(); 4381 LValue EvtLVal = CGF.EmitLValue(Evt); 4382 4383 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 4384 // int gtid, kmp_task_t *task); 4385 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc()); 4386 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc()); 4387 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false); 4388 llvm::Value *EvtVal = CGF.EmitRuntimeCall( 4389 OMPBuilder.getOrCreateRuntimeFunction( 4390 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event), 4391 {Loc, Tid, NewTask}); 4392 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(), 4393 Evt->getExprLoc()); 4394 CGF.EmitStoreOfScalar(EvtVal, EvtLVal); 4395 } 4396 // Process affinity clauses. 4397 if (D.hasClausesOfKind<OMPAffinityClause>()) { 4398 // Process list of affinity data. 4399 ASTContext &C = CGM.getContext(); 4400 Address AffinitiesArray = Address::invalid(); 4401 // Calculate number of elements to form the array of affinity data. 4402 llvm::Value *NumOfElements = nullptr; 4403 unsigned NumAffinities = 0; 4404 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4405 if (const Expr *Modifier = C->getModifier()) { 4406 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts()); 4407 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4408 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4409 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4410 NumOfElements = 4411 NumOfElements ? CGF.Builder.CreateNUWMul(NumOfElements, Sz) : Sz; 4412 } 4413 } else { 4414 NumAffinities += C->varlist_size(); 4415 } 4416 } 4417 getKmpAffinityType(CGM.getContext(), KmpTaskAffinityInfoTy); 4418 // Fields ids in kmp_task_affinity_info record. 4419 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags }; 4420 4421 QualType KmpTaskAffinityInfoArrayTy; 4422 if (NumOfElements) { 4423 NumOfElements = CGF.Builder.CreateNUWAdd( 4424 llvm::ConstantInt::get(CGF.SizeTy, NumAffinities), NumOfElements); 4425 auto *OVE = new (C) OpaqueValueExpr( 4426 Loc, 4427 C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0), 4428 VK_PRValue); 4429 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, OVE, 4430 RValue::get(NumOfElements)); 4431 KmpTaskAffinityInfoArrayTy = 4432 C.getVariableArrayType(KmpTaskAffinityInfoTy, OVE, ArrayType::Normal, 4433 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4434 // Properly emit variable-sized array. 4435 auto *PD = ImplicitParamDecl::Create(C, KmpTaskAffinityInfoArrayTy, 4436 ImplicitParamDecl::Other); 4437 CGF.EmitVarDecl(*PD); 4438 AffinitiesArray = CGF.GetAddrOfLocalVar(PD); 4439 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4440 /*isSigned=*/false); 4441 } else { 4442 KmpTaskAffinityInfoArrayTy = C.getConstantArrayType( 4443 KmpTaskAffinityInfoTy, 4444 llvm::APInt(C.getTypeSize(C.getSizeType()), NumAffinities), nullptr, 4445 ArrayType::Normal, /*IndexTypeQuals=*/0); 4446 AffinitiesArray = 4447 CGF.CreateMemTemp(KmpTaskAffinityInfoArrayTy, ".affs.arr.addr"); 4448 AffinitiesArray = CGF.Builder.CreateConstArrayGEP(AffinitiesArray, 0); 4449 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumAffinities, 4450 /*isSigned=*/false); 4451 } 4452 4453 const auto *KmpAffinityInfoRD = KmpTaskAffinityInfoTy->getAsRecordDecl(); 4454 // Fill array by elements without iterators. 4455 unsigned Pos = 0; 4456 bool HasIterator = false; 4457 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4458 if (C->getModifier()) { 4459 HasIterator = true; 4460 continue; 4461 } 4462 for (const Expr *E : C->varlists()) { 4463 llvm::Value *Addr; 4464 llvm::Value *Size; 4465 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4466 LValue Base = 4467 CGF.MakeAddrLValue(CGF.Builder.CreateConstGEP(AffinitiesArray, Pos), 4468 KmpTaskAffinityInfoTy); 4469 // affs[i].base_addr = &<Affinities[i].second>; 4470 LValue BaseAddrLVal = CGF.EmitLValueForField( 4471 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4472 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4473 BaseAddrLVal); 4474 // affs[i].len = sizeof(<Affinities[i].second>); 4475 LValue LenLVal = CGF.EmitLValueForField( 4476 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4477 CGF.EmitStoreOfScalar(Size, LenLVal); 4478 ++Pos; 4479 } 4480 } 4481 LValue PosLVal; 4482 if (HasIterator) { 4483 PosLVal = CGF.MakeAddrLValue( 4484 CGF.CreateMemTemp(C.getSizeType(), "affs.counter.addr"), 4485 C.getSizeType()); 4486 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4487 } 4488 // Process elements with iterators. 4489 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4490 const Expr *Modifier = C->getModifier(); 4491 if (!Modifier) 4492 continue; 4493 OMPIteratorGeneratorScope IteratorScope( 4494 CGF, cast_or_null<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts())); 4495 for (const Expr *E : C->varlists()) { 4496 llvm::Value *Addr; 4497 llvm::Value *Size; 4498 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4499 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4500 LValue Base = CGF.MakeAddrLValue( 4501 Address(CGF.Builder.CreateGEP(AffinitiesArray.getElementType(), 4502 AffinitiesArray.getPointer(), Idx), 4503 AffinitiesArray.getAlignment()), 4504 KmpTaskAffinityInfoTy); 4505 // affs[i].base_addr = &<Affinities[i].second>; 4506 LValue BaseAddrLVal = CGF.EmitLValueForField( 4507 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4508 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4509 BaseAddrLVal); 4510 // affs[i].len = sizeof(<Affinities[i].second>); 4511 LValue LenLVal = CGF.EmitLValueForField( 4512 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4513 CGF.EmitStoreOfScalar(Size, LenLVal); 4514 Idx = CGF.Builder.CreateNUWAdd( 4515 Idx, llvm::ConstantInt::get(Idx->getType(), 1)); 4516 CGF.EmitStoreOfScalar(Idx, PosLVal); 4517 } 4518 } 4519 // Call to kmp_int32 __kmpc_omp_reg_task_with_affinity(ident_t *loc_ref, 4520 // kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 4521 // naffins, kmp_task_affinity_info_t *affin_list); 4522 llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); 4523 llvm::Value *GTid = getThreadID(CGF, Loc); 4524 llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4525 AffinitiesArray.getPointer(), CGM.VoidPtrTy); 4526 // FIXME: Emit the function and ignore its result for now unless the 4527 // runtime function is properly implemented. 4528 (void)CGF.EmitRuntimeCall( 4529 OMPBuilder.getOrCreateRuntimeFunction( 4530 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity), 4531 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr}); 4532 } 4533 llvm::Value *NewTaskNewTaskTTy = 4534 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4535 NewTask, KmpTaskTWithPrivatesPtrTy); 4536 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 4537 KmpTaskTWithPrivatesQTy); 4538 LValue TDBase = 4539 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4540 // Fill the data in the resulting kmp_task_t record. 4541 // Copy shareds if there are any. 4542 Address KmpTaskSharedsPtr = Address::invalid(); 4543 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 4544 KmpTaskSharedsPtr = 4545 Address(CGF.EmitLoadOfScalar( 4546 CGF.EmitLValueForField( 4547 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 4548 KmpTaskTShareds)), 4549 Loc), 4550 CGM.getNaturalTypeAlignment(SharedsTy)); 4551 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 4552 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 4553 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 4554 } 4555 // Emit initial values for private copies (if any). 4556 TaskResultTy Result; 4557 if (!Privates.empty()) { 4558 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 4559 SharedsTy, SharedsPtrTy, Data, Privates, 4560 /*ForDup=*/false); 4561 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 4562 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 4563 Result.TaskDupFn = emitTaskDupFunction( 4564 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 4565 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 4566 /*WithLastIter=*/!Data.LastprivateVars.empty()); 4567 } 4568 } 4569 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 4570 enum { Priority = 0, Destructors = 1 }; 4571 // Provide pointer to function with destructors for privates. 4572 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 4573 const RecordDecl *KmpCmplrdataUD = 4574 (*FI)->getType()->getAsUnionType()->getDecl(); 4575 if (NeedsCleanup) { 4576 llvm::Value *DestructorFn = emitDestructorsFunction( 4577 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4578 KmpTaskTWithPrivatesQTy); 4579 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 4580 LValue DestructorsLV = CGF.EmitLValueForField( 4581 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 4582 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4583 DestructorFn, KmpRoutineEntryPtrTy), 4584 DestructorsLV); 4585 } 4586 // Set priority. 4587 if (Data.Priority.getInt()) { 4588 LValue Data2LV = CGF.EmitLValueForField( 4589 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 4590 LValue PriorityLV = CGF.EmitLValueForField( 4591 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 4592 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 4593 } 4594 Result.NewTask = NewTask; 4595 Result.TaskEntry = TaskEntry; 4596 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 4597 Result.TDBase = TDBase; 4598 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 4599 return Result; 4600 } 4601 4602 namespace { 4603 /// Dependence kind for RTL. 4604 enum RTLDependenceKindTy { 4605 DepIn = 0x01, 4606 DepInOut = 0x3, 4607 DepMutexInOutSet = 0x4 4608 }; 4609 /// Fields ids in kmp_depend_info record. 4610 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 4611 } // namespace 4612 4613 /// Translates internal dependency kind into the runtime kind. 4614 static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { 4615 RTLDependenceKindTy DepKind; 4616 switch (K) { 4617 case OMPC_DEPEND_in: 4618 DepKind = DepIn; 4619 break; 4620 // Out and InOut dependencies must use the same code. 4621 case OMPC_DEPEND_out: 4622 case OMPC_DEPEND_inout: 4623 DepKind = DepInOut; 4624 break; 4625 case OMPC_DEPEND_mutexinoutset: 4626 DepKind = DepMutexInOutSet; 4627 break; 4628 case OMPC_DEPEND_source: 4629 case OMPC_DEPEND_sink: 4630 case OMPC_DEPEND_depobj: 4631 case OMPC_DEPEND_unknown: 4632 llvm_unreachable("Unknown task dependence type"); 4633 } 4634 return DepKind; 4635 } 4636 4637 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4638 static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, 4639 QualType &FlagsTy) { 4640 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 4641 if (KmpDependInfoTy.isNull()) { 4642 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 4643 KmpDependInfoRD->startDefinition(); 4644 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 4645 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 4646 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 4647 KmpDependInfoRD->completeDefinition(); 4648 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 4649 } 4650 } 4651 4652 std::pair<llvm::Value *, LValue> 4653 CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, 4654 SourceLocation Loc) { 4655 ASTContext &C = CGM.getContext(); 4656 QualType FlagsTy; 4657 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4658 RecordDecl *KmpDependInfoRD = 4659 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4660 LValue Base = CGF.EmitLoadOfPointerLValue( 4661 DepobjLVal.getAddress(CGF), 4662 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4663 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4664 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4665 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 4666 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4667 Base.getTBAAInfo()); 4668 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4669 Addr.getElementType(), Addr.getPointer(), 4670 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4671 LValue NumDepsBase = CGF.MakeAddrLValue( 4672 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4673 Base.getBaseInfo(), Base.getTBAAInfo()); 4674 // NumDeps = deps[i].base_addr; 4675 LValue BaseAddrLVal = CGF.EmitLValueForField( 4676 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4677 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc); 4678 return std::make_pair(NumDeps, Base); 4679 } 4680 4681 static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4682 llvm::PointerUnion<unsigned *, LValue *> Pos, 4683 const OMPTaskDataTy::DependData &Data, 4684 Address DependenciesArray) { 4685 CodeGenModule &CGM = CGF.CGM; 4686 ASTContext &C = CGM.getContext(); 4687 QualType FlagsTy; 4688 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4689 RecordDecl *KmpDependInfoRD = 4690 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4691 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 4692 4693 OMPIteratorGeneratorScope IteratorScope( 4694 CGF, cast_or_null<OMPIteratorExpr>( 4695 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4696 : nullptr)); 4697 for (const Expr *E : Data.DepExprs) { 4698 llvm::Value *Addr; 4699 llvm::Value *Size; 4700 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4701 LValue Base; 4702 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4703 Base = CGF.MakeAddrLValue( 4704 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy); 4705 } else { 4706 LValue &PosLVal = *Pos.get<LValue *>(); 4707 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4708 Base = CGF.MakeAddrLValue( 4709 Address(CGF.Builder.CreateGEP(DependenciesArray.getElementType(), 4710 DependenciesArray.getPointer(), Idx), 4711 DependenciesArray.getAlignment()), 4712 KmpDependInfoTy); 4713 } 4714 // deps[i].base_addr = &<Dependencies[i].second>; 4715 LValue BaseAddrLVal = CGF.EmitLValueForField( 4716 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4717 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4718 BaseAddrLVal); 4719 // deps[i].len = sizeof(<Dependencies[i].second>); 4720 LValue LenLVal = CGF.EmitLValueForField( 4721 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 4722 CGF.EmitStoreOfScalar(Size, LenLVal); 4723 // deps[i].flags = <Dependencies[i].first>; 4724 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind); 4725 LValue FlagsLVal = CGF.EmitLValueForField( 4726 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 4727 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 4728 FlagsLVal); 4729 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4730 ++(*P); 4731 } else { 4732 LValue &PosLVal = *Pos.get<LValue *>(); 4733 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4734 Idx = CGF.Builder.CreateNUWAdd(Idx, 4735 llvm::ConstantInt::get(Idx->getType(), 1)); 4736 CGF.EmitStoreOfScalar(Idx, PosLVal); 4737 } 4738 } 4739 } 4740 4741 static SmallVector<llvm::Value *, 4> 4742 emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4743 const OMPTaskDataTy::DependData &Data) { 4744 assert(Data.DepKind == OMPC_DEPEND_depobj && 4745 "Expected depobj dependecy kind."); 4746 SmallVector<llvm::Value *, 4> Sizes; 4747 SmallVector<LValue, 4> SizeLVals; 4748 ASTContext &C = CGF.getContext(); 4749 QualType FlagsTy; 4750 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4751 RecordDecl *KmpDependInfoRD = 4752 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4753 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4754 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4755 { 4756 OMPIteratorGeneratorScope IteratorScope( 4757 CGF, cast_or_null<OMPIteratorExpr>( 4758 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4759 : nullptr)); 4760 for (const Expr *E : Data.DepExprs) { 4761 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4762 LValue Base = CGF.EmitLoadOfPointerLValue( 4763 DepobjLVal.getAddress(CGF), 4764 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4765 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4766 Base.getAddress(CGF), KmpDependInfoPtrT); 4767 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4768 Base.getTBAAInfo()); 4769 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4770 Addr.getElementType(), Addr.getPointer(), 4771 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4772 LValue NumDepsBase = CGF.MakeAddrLValue( 4773 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4774 Base.getBaseInfo(), Base.getTBAAInfo()); 4775 // NumDeps = deps[i].base_addr; 4776 LValue BaseAddrLVal = CGF.EmitLValueForField( 4777 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4778 llvm::Value *NumDeps = 4779 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4780 LValue NumLVal = CGF.MakeAddrLValue( 4781 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"), 4782 C.getUIntPtrType()); 4783 CGF.InitTempAlloca(NumLVal.getAddress(CGF), 4784 llvm::ConstantInt::get(CGF.IntPtrTy, 0)); 4785 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc()); 4786 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps); 4787 CGF.EmitStoreOfScalar(Add, NumLVal); 4788 SizeLVals.push_back(NumLVal); 4789 } 4790 } 4791 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) { 4792 llvm::Value *Size = 4793 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc()); 4794 Sizes.push_back(Size); 4795 } 4796 return Sizes; 4797 } 4798 4799 static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4800 LValue PosLVal, 4801 const OMPTaskDataTy::DependData &Data, 4802 Address DependenciesArray) { 4803 assert(Data.DepKind == OMPC_DEPEND_depobj && 4804 "Expected depobj dependecy kind."); 4805 ASTContext &C = CGF.getContext(); 4806 QualType FlagsTy; 4807 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4808 RecordDecl *KmpDependInfoRD = 4809 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4810 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4811 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4812 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy); 4813 { 4814 OMPIteratorGeneratorScope IteratorScope( 4815 CGF, cast_or_null<OMPIteratorExpr>( 4816 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4817 : nullptr)); 4818 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) { 4819 const Expr *E = Data.DepExprs[I]; 4820 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4821 LValue Base = CGF.EmitLoadOfPointerLValue( 4822 DepobjLVal.getAddress(CGF), 4823 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4824 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4825 Base.getAddress(CGF), KmpDependInfoPtrT); 4826 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4827 Base.getTBAAInfo()); 4828 4829 // Get number of elements in a single depobj. 4830 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4831 Addr.getElementType(), Addr.getPointer(), 4832 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4833 LValue NumDepsBase = CGF.MakeAddrLValue( 4834 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4835 Base.getBaseInfo(), Base.getTBAAInfo()); 4836 // NumDeps = deps[i].base_addr; 4837 LValue BaseAddrLVal = CGF.EmitLValueForField( 4838 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4839 llvm::Value *NumDeps = 4840 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4841 4842 // memcopy dependency data. 4843 llvm::Value *Size = CGF.Builder.CreateNUWMul( 4844 ElSize, 4845 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); 4846 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4847 Address DepAddr = 4848 Address(CGF.Builder.CreateGEP(DependenciesArray.getElementType(), 4849 DependenciesArray.getPointer(), Pos), 4850 DependenciesArray.getAlignment()); 4851 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); 4852 4853 // Increase pos. 4854 // pos += size; 4855 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps); 4856 CGF.EmitStoreOfScalar(Add, PosLVal); 4857 } 4858 } 4859 } 4860 4861 std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause( 4862 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies, 4863 SourceLocation Loc) { 4864 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) { 4865 return D.DepExprs.empty(); 4866 })) 4867 return std::make_pair(nullptr, Address::invalid()); 4868 // Process list of dependencies. 4869 ASTContext &C = CGM.getContext(); 4870 Address DependenciesArray = Address::invalid(); 4871 llvm::Value *NumOfElements = nullptr; 4872 unsigned NumDependencies = std::accumulate( 4873 Dependencies.begin(), Dependencies.end(), 0, 4874 [](unsigned V, const OMPTaskDataTy::DependData &D) { 4875 return D.DepKind == OMPC_DEPEND_depobj 4876 ? V 4877 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size())); 4878 }); 4879 QualType FlagsTy; 4880 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4881 bool HasDepobjDeps = false; 4882 bool HasRegularWithIterators = false; 4883 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0); 4884 llvm::Value *NumOfRegularWithIterators = 4885 llvm::ConstantInt::get(CGF.IntPtrTy, 0); 4886 // Calculate number of depobj dependecies and regular deps with the iterators. 4887 for (const OMPTaskDataTy::DependData &D : Dependencies) { 4888 if (D.DepKind == OMPC_DEPEND_depobj) { 4889 SmallVector<llvm::Value *, 4> Sizes = 4890 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D); 4891 for (llvm::Value *Size : Sizes) { 4892 NumOfDepobjElements = 4893 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size); 4894 } 4895 HasDepobjDeps = true; 4896 continue; 4897 } 4898 // Include number of iterations, if any. 4899 4900 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) { 4901 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4902 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4903 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false); 4904 llvm::Value *NumClauseDeps = CGF.Builder.CreateNUWMul( 4905 Sz, llvm::ConstantInt::get(CGF.IntPtrTy, D.DepExprs.size())); 4906 NumOfRegularWithIterators = 4907 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumClauseDeps); 4908 } 4909 HasRegularWithIterators = true; 4910 continue; 4911 } 4912 } 4913 4914 QualType KmpDependInfoArrayTy; 4915 if (HasDepobjDeps || HasRegularWithIterators) { 4916 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies, 4917 /*isSigned=*/false); 4918 if (HasDepobjDeps) { 4919 NumOfElements = 4920 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements); 4921 } 4922 if (HasRegularWithIterators) { 4923 NumOfElements = 4924 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements); 4925 } 4926 auto *OVE = new (C) OpaqueValueExpr( 4927 Loc, C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0), 4928 VK_PRValue); 4929 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, OVE, 4930 RValue::get(NumOfElements)); 4931 KmpDependInfoArrayTy = 4932 C.getVariableArrayType(KmpDependInfoTy, OVE, ArrayType::Normal, 4933 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4934 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy); 4935 // Properly emit variable-sized array. 4936 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy, 4937 ImplicitParamDecl::Other); 4938 CGF.EmitVarDecl(*PD); 4939 DependenciesArray = CGF.GetAddrOfLocalVar(PD); 4940 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4941 /*isSigned=*/false); 4942 } else { 4943 KmpDependInfoArrayTy = C.getConstantArrayType( 4944 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr, 4945 ArrayType::Normal, /*IndexTypeQuals=*/0); 4946 DependenciesArray = 4947 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 4948 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0); 4949 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 4950 /*isSigned=*/false); 4951 } 4952 unsigned Pos = 0; 4953 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4954 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4955 Dependencies[I].IteratorExpr) 4956 continue; 4957 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I], 4958 DependenciesArray); 4959 } 4960 // Copy regular dependecies with iterators. 4961 LValue PosLVal = CGF.MakeAddrLValue( 4962 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType()); 4963 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4964 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4965 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4966 !Dependencies[I].IteratorExpr) 4967 continue; 4968 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I], 4969 DependenciesArray); 4970 } 4971 // Copy final depobj arrays without iterators. 4972 if (HasDepobjDeps) { 4973 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4974 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj) 4975 continue; 4976 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I], 4977 DependenciesArray); 4978 } 4979 } 4980 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4981 DependenciesArray, CGF.VoidPtrTy); 4982 return std::make_pair(NumOfElements, DependenciesArray); 4983 } 4984 4985 Address CGOpenMPRuntime::emitDepobjDependClause( 4986 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, 4987 SourceLocation Loc) { 4988 if (Dependencies.DepExprs.empty()) 4989 return Address::invalid(); 4990 // Process list of dependencies. 4991 ASTContext &C = CGM.getContext(); 4992 Address DependenciesArray = Address::invalid(); 4993 unsigned NumDependencies = Dependencies.DepExprs.size(); 4994 QualType FlagsTy; 4995 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4996 RecordDecl *KmpDependInfoRD = 4997 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4998 4999 llvm::Value *Size; 5000 // Define type kmp_depend_info[<Dependencies.size()>]; 5001 // For depobj reserve one extra element to store the number of elements. 5002 // It is required to handle depobj(x) update(in) construct. 5003 // kmp_depend_info[<Dependencies.size()>] deps; 5004 llvm::Value *NumDepsVal; 5005 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy); 5006 if (const auto *IE = 5007 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) { 5008 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1); 5009 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 5010 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 5011 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 5012 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz); 5013 } 5014 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1), 5015 NumDepsVal); 5016 CharUnits SizeInBytes = 5017 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align); 5018 llvm::Value *RecSize = CGM.getSize(SizeInBytes); 5019 Size = CGF.Builder.CreateNUWMul(Size, RecSize); 5020 NumDepsVal = 5021 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false); 5022 } else { 5023 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5024 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1), 5025 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5026 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy); 5027 Size = CGM.getSize(Sz.alignTo(Align)); 5028 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies); 5029 } 5030 // Need to allocate on the dynamic memory. 5031 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5032 // Use default allocator. 5033 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5034 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 5035 5036 llvm::Value *Addr = 5037 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5038 CGM.getModule(), OMPRTL___kmpc_alloc), 5039 Args, ".dep.arr.addr"); 5040 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5041 Addr, CGF.ConvertTypeForMem(KmpDependInfoTy)->getPointerTo()); 5042 DependenciesArray = Address(Addr, Align); 5043 // Write number of elements in the first element of array for depobj. 5044 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy); 5045 // deps[i].base_addr = NumDependencies; 5046 LValue BaseAddrLVal = CGF.EmitLValueForField( 5047 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5048 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal); 5049 llvm::PointerUnion<unsigned *, LValue *> Pos; 5050 unsigned Idx = 1; 5051 LValue PosLVal; 5052 if (Dependencies.IteratorExpr) { 5053 PosLVal = CGF.MakeAddrLValue( 5054 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"), 5055 C.getSizeType()); 5056 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal, 5057 /*IsInit=*/true); 5058 Pos = &PosLVal; 5059 } else { 5060 Pos = &Idx; 5061 } 5062 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray); 5063 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5064 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy); 5065 return DependenciesArray; 5066 } 5067 5068 void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 5069 SourceLocation Loc) { 5070 ASTContext &C = CGM.getContext(); 5071 QualType FlagsTy; 5072 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5073 LValue Base = CGF.EmitLoadOfPointerLValue( 5074 DepobjLVal.getAddress(CGF), 5075 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5076 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5077 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5078 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 5079 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5080 Addr.getElementType(), Addr.getPointer(), 5081 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5082 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, 5083 CGF.VoidPtrTy); 5084 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5085 // Use default allocator. 5086 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5087 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator}; 5088 5089 // _kmpc_free(gtid, addr, nullptr); 5090 (void)CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5091 CGM.getModule(), OMPRTL___kmpc_free), 5092 Args); 5093 } 5094 5095 void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 5096 OpenMPDependClauseKind NewDepKind, 5097 SourceLocation Loc) { 5098 ASTContext &C = CGM.getContext(); 5099 QualType FlagsTy; 5100 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5101 RecordDecl *KmpDependInfoRD = 5102 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5103 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5104 llvm::Value *NumDeps; 5105 LValue Base; 5106 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 5107 5108 Address Begin = Base.getAddress(CGF); 5109 // Cast from pointer to array type to pointer to single element. 5110 llvm::Value *End = CGF.Builder.CreateGEP( 5111 Begin.getElementType(), Begin.getPointer(), NumDeps); 5112 // The basic structure here is a while-do loop. 5113 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); 5114 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); 5115 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5116 CGF.EmitBlock(BodyBB); 5117 llvm::PHINode *ElementPHI = 5118 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); 5119 ElementPHI->addIncoming(Begin.getPointer(), EntryBB); 5120 Begin = Address(ElementPHI, Begin.getAlignment()); 5121 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), 5122 Base.getTBAAInfo()); 5123 // deps[i].flags = NewDepKind; 5124 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind); 5125 LValue FlagsLVal = CGF.EmitLValueForField( 5126 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5127 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5128 FlagsLVal); 5129 5130 // Shift the address forward by one element. 5131 Address ElementNext = 5132 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); 5133 ElementPHI->addIncoming(ElementNext.getPointer(), 5134 CGF.Builder.GetInsertBlock()); 5135 llvm::Value *IsEmpty = 5136 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); 5137 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5138 // Done. 5139 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5140 } 5141 5142 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5143 const OMPExecutableDirective &D, 5144 llvm::Function *TaskFunction, 5145 QualType SharedsTy, Address Shareds, 5146 const Expr *IfCond, 5147 const OMPTaskDataTy &Data) { 5148 if (!CGF.HaveInsertPoint()) 5149 return; 5150 5151 TaskResultTy Result = 5152 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5153 llvm::Value *NewTask = Result.NewTask; 5154 llvm::Function *TaskEntry = Result.TaskEntry; 5155 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5156 LValue TDBase = Result.TDBase; 5157 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5158 // Process list of dependences. 5159 Address DependenciesArray = Address::invalid(); 5160 llvm::Value *NumOfElements; 5161 std::tie(NumOfElements, DependenciesArray) = 5162 emitDependClause(CGF, Data.Dependences, Loc); 5163 5164 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5165 // libcall. 5166 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5167 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5168 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5169 // list is not empty 5170 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5171 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5172 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5173 llvm::Value *DepTaskArgs[7]; 5174 if (!Data.Dependences.empty()) { 5175 DepTaskArgs[0] = UpLoc; 5176 DepTaskArgs[1] = ThreadID; 5177 DepTaskArgs[2] = NewTask; 5178 DepTaskArgs[3] = NumOfElements; 5179 DepTaskArgs[4] = DependenciesArray.getPointer(); 5180 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5181 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5182 } 5183 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs, 5184 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5185 if (!Data.Tied) { 5186 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5187 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5188 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5189 } 5190 if (!Data.Dependences.empty()) { 5191 CGF.EmitRuntimeCall( 5192 OMPBuilder.getOrCreateRuntimeFunction( 5193 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps), 5194 DepTaskArgs); 5195 } else { 5196 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5197 CGM.getModule(), OMPRTL___kmpc_omp_task), 5198 TaskArgs); 5199 } 5200 // Check if parent region is untied and build return for untied task; 5201 if (auto *Region = 5202 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5203 Region->emitUntiedSwitch(CGF); 5204 }; 5205 5206 llvm::Value *DepWaitTaskArgs[6]; 5207 if (!Data.Dependences.empty()) { 5208 DepWaitTaskArgs[0] = UpLoc; 5209 DepWaitTaskArgs[1] = ThreadID; 5210 DepWaitTaskArgs[2] = NumOfElements; 5211 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5212 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5213 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5214 } 5215 auto &M = CGM.getModule(); 5216 auto &&ElseCodeGen = [this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy, 5217 TaskEntry, &Data, &DepWaitTaskArgs, 5218 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5219 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5220 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5221 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5222 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5223 // is specified. 5224 if (!Data.Dependences.empty()) 5225 CGF.EmitRuntimeCall( 5226 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps), 5227 DepWaitTaskArgs); 5228 // Call proxy_task_entry(gtid, new_task); 5229 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5230 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5231 Action.Enter(CGF); 5232 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5233 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5234 OutlinedFnArgs); 5235 }; 5236 5237 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5238 // kmp_task_t *new_task); 5239 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5240 // kmp_task_t *new_task); 5241 RegionCodeGenTy RCG(CodeGen); 5242 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 5243 M, OMPRTL___kmpc_omp_task_begin_if0), 5244 TaskArgs, 5245 OMPBuilder.getOrCreateRuntimeFunction( 5246 M, OMPRTL___kmpc_omp_task_complete_if0), 5247 TaskArgs); 5248 RCG.setAction(Action); 5249 RCG(CGF); 5250 }; 5251 5252 if (IfCond) { 5253 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5254 } else { 5255 RegionCodeGenTy ThenRCG(ThenCodeGen); 5256 ThenRCG(CGF); 5257 } 5258 } 5259 5260 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5261 const OMPLoopDirective &D, 5262 llvm::Function *TaskFunction, 5263 QualType SharedsTy, Address Shareds, 5264 const Expr *IfCond, 5265 const OMPTaskDataTy &Data) { 5266 if (!CGF.HaveInsertPoint()) 5267 return; 5268 TaskResultTy Result = 5269 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5270 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5271 // libcall. 5272 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5273 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5274 // sched, kmp_uint64 grainsize, void *task_dup); 5275 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5276 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5277 llvm::Value *IfVal; 5278 if (IfCond) { 5279 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5280 /*isSigned=*/true); 5281 } else { 5282 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5283 } 5284 5285 LValue LBLVal = CGF.EmitLValueForField( 5286 Result.TDBase, 5287 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5288 const auto *LBVar = 5289 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5290 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5291 LBLVal.getQuals(), 5292 /*IsInitializer=*/true); 5293 LValue UBLVal = CGF.EmitLValueForField( 5294 Result.TDBase, 5295 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5296 const auto *UBVar = 5297 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5298 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5299 UBLVal.getQuals(), 5300 /*IsInitializer=*/true); 5301 LValue StLVal = CGF.EmitLValueForField( 5302 Result.TDBase, 5303 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5304 const auto *StVar = 5305 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5306 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5307 StLVal.getQuals(), 5308 /*IsInitializer=*/true); 5309 // Store reductions address. 5310 LValue RedLVal = CGF.EmitLValueForField( 5311 Result.TDBase, 5312 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5313 if (Data.Reductions) { 5314 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5315 } else { 5316 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5317 CGF.getContext().VoidPtrTy); 5318 } 5319 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5320 llvm::Value *TaskArgs[] = { 5321 UpLoc, 5322 ThreadID, 5323 Result.NewTask, 5324 IfVal, 5325 LBLVal.getPointer(CGF), 5326 UBLVal.getPointer(CGF), 5327 CGF.EmitLoadOfScalar(StLVal, Loc), 5328 llvm::ConstantInt::getSigned( 5329 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5330 llvm::ConstantInt::getSigned( 5331 CGF.IntTy, Data.Schedule.getPointer() 5332 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5333 : NoSchedule), 5334 Data.Schedule.getPointer() 5335 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5336 /*isSigned=*/false) 5337 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5338 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5339 Result.TaskDupFn, CGF.VoidPtrTy) 5340 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5341 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5342 CGM.getModule(), OMPRTL___kmpc_taskloop), 5343 TaskArgs); 5344 } 5345 5346 /// Emit reduction operation for each element of array (required for 5347 /// array sections) LHS op = RHS. 5348 /// \param Type Type of array. 5349 /// \param LHSVar Variable on the left side of the reduction operation 5350 /// (references element of array in original variable). 5351 /// \param RHSVar Variable on the right side of the reduction operation 5352 /// (references element of array in original variable). 5353 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5354 /// RHSVar. 5355 static void EmitOMPAggregateReduction( 5356 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5357 const VarDecl *RHSVar, 5358 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5359 const Expr *, const Expr *)> &RedOpGen, 5360 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5361 const Expr *UpExpr = nullptr) { 5362 // Perform element-by-element initialization. 5363 QualType ElementTy; 5364 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5365 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5366 5367 // Drill down to the base element type on both arrays. 5368 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5369 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5370 5371 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5372 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5373 // Cast from pointer to array type to pointer to single element. 5374 llvm::Value *LHSEnd = 5375 CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements); 5376 // The basic structure here is a while-do loop. 5377 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5378 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5379 llvm::Value *IsEmpty = 5380 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5381 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5382 5383 // Enter the loop body, making that address the current address. 5384 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5385 CGF.EmitBlock(BodyBB); 5386 5387 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5388 5389 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5390 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5391 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5392 Address RHSElementCurrent = 5393 Address(RHSElementPHI, 5394 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5395 5396 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5397 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5398 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5399 Address LHSElementCurrent = 5400 Address(LHSElementPHI, 5401 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5402 5403 // Emit copy. 5404 CodeGenFunction::OMPPrivateScope Scope(CGF); 5405 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5406 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5407 Scope.Privatize(); 5408 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5409 Scope.ForceCleanup(); 5410 5411 // Shift the address forward by one element. 5412 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5413 LHSAddr.getElementType(), LHSElementPHI, /*Idx0=*/1, 5414 "omp.arraycpy.dest.element"); 5415 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5416 RHSAddr.getElementType(), RHSElementPHI, /*Idx0=*/1, 5417 "omp.arraycpy.src.element"); 5418 // Check whether we've reached the end. 5419 llvm::Value *Done = 5420 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5421 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5422 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5423 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5424 5425 // Done. 5426 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5427 } 5428 5429 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5430 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5431 /// UDR combiner function. 5432 static void emitReductionCombiner(CodeGenFunction &CGF, 5433 const Expr *ReductionOp) { 5434 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5435 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5436 if (const auto *DRE = 5437 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5438 if (const auto *DRD = 5439 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5440 std::pair<llvm::Function *, llvm::Function *> Reduction = 5441 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5442 RValue Func = RValue::get(Reduction.first); 5443 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5444 CGF.EmitIgnoredExpr(ReductionOp); 5445 return; 5446 } 5447 CGF.EmitIgnoredExpr(ReductionOp); 5448 } 5449 5450 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5451 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5452 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5453 ArrayRef<const Expr *> ReductionOps) { 5454 ASTContext &C = CGM.getContext(); 5455 5456 // void reduction_func(void *LHSArg, void *RHSArg); 5457 FunctionArgList Args; 5458 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5459 ImplicitParamDecl::Other); 5460 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5461 ImplicitParamDecl::Other); 5462 Args.push_back(&LHSArg); 5463 Args.push_back(&RHSArg); 5464 const auto &CGFI = 5465 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5466 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5467 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5468 llvm::GlobalValue::InternalLinkage, Name, 5469 &CGM.getModule()); 5470 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5471 Fn->setDoesNotRecurse(); 5472 CodeGenFunction CGF(CGM); 5473 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5474 5475 // Dst = (void*[n])(LHSArg); 5476 // Src = (void*[n])(RHSArg); 5477 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5478 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5479 ArgsType), CGF.getPointerAlign()); 5480 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5481 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5482 ArgsType), CGF.getPointerAlign()); 5483 5484 // ... 5485 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5486 // ... 5487 CodeGenFunction::OMPPrivateScope Scope(CGF); 5488 auto IPriv = Privates.begin(); 5489 unsigned Idx = 0; 5490 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5491 const auto *RHSVar = 5492 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5493 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5494 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5495 }); 5496 const auto *LHSVar = 5497 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5498 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5499 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5500 }); 5501 QualType PrivTy = (*IPriv)->getType(); 5502 if (PrivTy->isVariablyModifiedType()) { 5503 // Get array size and emit VLA type. 5504 ++Idx; 5505 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5506 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5507 const VariableArrayType *VLA = 5508 CGF.getContext().getAsVariableArrayType(PrivTy); 5509 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5510 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5511 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5512 CGF.EmitVariablyModifiedType(PrivTy); 5513 } 5514 } 5515 Scope.Privatize(); 5516 IPriv = Privates.begin(); 5517 auto ILHS = LHSExprs.begin(); 5518 auto IRHS = RHSExprs.begin(); 5519 for (const Expr *E : ReductionOps) { 5520 if ((*IPriv)->getType()->isArrayType()) { 5521 // Emit reduction for array section. 5522 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5523 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5524 EmitOMPAggregateReduction( 5525 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5526 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5527 emitReductionCombiner(CGF, E); 5528 }); 5529 } else { 5530 // Emit reduction for array subscript or single variable. 5531 emitReductionCombiner(CGF, E); 5532 } 5533 ++IPriv; 5534 ++ILHS; 5535 ++IRHS; 5536 } 5537 Scope.ForceCleanup(); 5538 CGF.FinishFunction(); 5539 return Fn; 5540 } 5541 5542 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5543 const Expr *ReductionOp, 5544 const Expr *PrivateRef, 5545 const DeclRefExpr *LHS, 5546 const DeclRefExpr *RHS) { 5547 if (PrivateRef->getType()->isArrayType()) { 5548 // Emit reduction for array section. 5549 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5550 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5551 EmitOMPAggregateReduction( 5552 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5553 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5554 emitReductionCombiner(CGF, ReductionOp); 5555 }); 5556 } else { 5557 // Emit reduction for array subscript or single variable. 5558 emitReductionCombiner(CGF, ReductionOp); 5559 } 5560 } 5561 5562 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5563 ArrayRef<const Expr *> Privates, 5564 ArrayRef<const Expr *> LHSExprs, 5565 ArrayRef<const Expr *> RHSExprs, 5566 ArrayRef<const Expr *> ReductionOps, 5567 ReductionOptionsTy Options) { 5568 if (!CGF.HaveInsertPoint()) 5569 return; 5570 5571 bool WithNowait = Options.WithNowait; 5572 bool SimpleReduction = Options.SimpleReduction; 5573 5574 // Next code should be emitted for reduction: 5575 // 5576 // static kmp_critical_name lock = { 0 }; 5577 // 5578 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5579 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5580 // ... 5581 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5582 // *(Type<n>-1*)rhs[<n>-1]); 5583 // } 5584 // 5585 // ... 5586 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5587 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5588 // RedList, reduce_func, &<lock>)) { 5589 // case 1: 5590 // ... 5591 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5592 // ... 5593 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5594 // break; 5595 // case 2: 5596 // ... 5597 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5598 // ... 5599 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5600 // break; 5601 // default:; 5602 // } 5603 // 5604 // if SimpleReduction is true, only the next code is generated: 5605 // ... 5606 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5607 // ... 5608 5609 ASTContext &C = CGM.getContext(); 5610 5611 if (SimpleReduction) { 5612 CodeGenFunction::RunCleanupsScope Scope(CGF); 5613 auto IPriv = Privates.begin(); 5614 auto ILHS = LHSExprs.begin(); 5615 auto IRHS = RHSExprs.begin(); 5616 for (const Expr *E : ReductionOps) { 5617 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5618 cast<DeclRefExpr>(*IRHS)); 5619 ++IPriv; 5620 ++ILHS; 5621 ++IRHS; 5622 } 5623 return; 5624 } 5625 5626 // 1. Build a list of reduction variables. 5627 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5628 auto Size = RHSExprs.size(); 5629 for (const Expr *E : Privates) { 5630 if (E->getType()->isVariablyModifiedType()) 5631 // Reserve place for array size. 5632 ++Size; 5633 } 5634 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5635 QualType ReductionArrayTy = 5636 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5637 /*IndexTypeQuals=*/0); 5638 Address ReductionList = 5639 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5640 auto IPriv = Privates.begin(); 5641 unsigned Idx = 0; 5642 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5643 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5644 CGF.Builder.CreateStore( 5645 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5646 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5647 Elem); 5648 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5649 // Store array size. 5650 ++Idx; 5651 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5652 llvm::Value *Size = CGF.Builder.CreateIntCast( 5653 CGF.getVLASize( 5654 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5655 .NumElts, 5656 CGF.SizeTy, /*isSigned=*/false); 5657 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5658 Elem); 5659 } 5660 } 5661 5662 // 2. Emit reduce_func(). 5663 llvm::Function *ReductionFn = emitReductionFunction( 5664 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5665 LHSExprs, RHSExprs, ReductionOps); 5666 5667 // 3. Create static kmp_critical_name lock = { 0 }; 5668 std::string Name = getName({"reduction"}); 5669 llvm::Value *Lock = getCriticalRegionLock(Name); 5670 5671 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5672 // RedList, reduce_func, &<lock>); 5673 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5674 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5675 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5676 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5677 ReductionList.getPointer(), CGF.VoidPtrTy); 5678 llvm::Value *Args[] = { 5679 IdentTLoc, // ident_t *<loc> 5680 ThreadId, // i32 <gtid> 5681 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5682 ReductionArrayTySize, // size_type sizeof(RedList) 5683 RL, // void *RedList 5684 ReductionFn, // void (*) (void *, void *) <reduce_func> 5685 Lock // kmp_critical_name *&<lock> 5686 }; 5687 llvm::Value *Res = CGF.EmitRuntimeCall( 5688 OMPBuilder.getOrCreateRuntimeFunction( 5689 CGM.getModule(), 5690 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce), 5691 Args); 5692 5693 // 5. Build switch(res) 5694 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5695 llvm::SwitchInst *SwInst = 5696 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5697 5698 // 6. Build case 1: 5699 // ... 5700 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5701 // ... 5702 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5703 // break; 5704 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5705 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5706 CGF.EmitBlock(Case1BB); 5707 5708 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5709 llvm::Value *EndArgs[] = { 5710 IdentTLoc, // ident_t *<loc> 5711 ThreadId, // i32 <gtid> 5712 Lock // kmp_critical_name *&<lock> 5713 }; 5714 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5715 CodeGenFunction &CGF, PrePostActionTy &Action) { 5716 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5717 auto IPriv = Privates.begin(); 5718 auto ILHS = LHSExprs.begin(); 5719 auto IRHS = RHSExprs.begin(); 5720 for (const Expr *E : ReductionOps) { 5721 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5722 cast<DeclRefExpr>(*IRHS)); 5723 ++IPriv; 5724 ++ILHS; 5725 ++IRHS; 5726 } 5727 }; 5728 RegionCodeGenTy RCG(CodeGen); 5729 CommonActionTy Action( 5730 nullptr, llvm::None, 5731 OMPBuilder.getOrCreateRuntimeFunction( 5732 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait 5733 : OMPRTL___kmpc_end_reduce), 5734 EndArgs); 5735 RCG.setAction(Action); 5736 RCG(CGF); 5737 5738 CGF.EmitBranch(DefaultBB); 5739 5740 // 7. Build case 2: 5741 // ... 5742 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5743 // ... 5744 // break; 5745 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5746 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5747 CGF.EmitBlock(Case2BB); 5748 5749 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5750 CodeGenFunction &CGF, PrePostActionTy &Action) { 5751 auto ILHS = LHSExprs.begin(); 5752 auto IRHS = RHSExprs.begin(); 5753 auto IPriv = Privates.begin(); 5754 for (const Expr *E : ReductionOps) { 5755 const Expr *XExpr = nullptr; 5756 const Expr *EExpr = nullptr; 5757 const Expr *UpExpr = nullptr; 5758 BinaryOperatorKind BO = BO_Comma; 5759 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5760 if (BO->getOpcode() == BO_Assign) { 5761 XExpr = BO->getLHS(); 5762 UpExpr = BO->getRHS(); 5763 } 5764 } 5765 // Try to emit update expression as a simple atomic. 5766 const Expr *RHSExpr = UpExpr; 5767 if (RHSExpr) { 5768 // Analyze RHS part of the whole expression. 5769 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5770 RHSExpr->IgnoreParenImpCasts())) { 5771 // If this is a conditional operator, analyze its condition for 5772 // min/max reduction operator. 5773 RHSExpr = ACO->getCond(); 5774 } 5775 if (const auto *BORHS = 5776 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5777 EExpr = BORHS->getRHS(); 5778 BO = BORHS->getOpcode(); 5779 } 5780 } 5781 if (XExpr) { 5782 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5783 auto &&AtomicRedGen = [BO, VD, 5784 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5785 const Expr *EExpr, const Expr *UpExpr) { 5786 LValue X = CGF.EmitLValue(XExpr); 5787 RValue E; 5788 if (EExpr) 5789 E = CGF.EmitAnyExpr(EExpr); 5790 CGF.EmitOMPAtomicSimpleUpdateExpr( 5791 X, E, BO, /*IsXLHSInRHSPart=*/true, 5792 llvm::AtomicOrdering::Monotonic, Loc, 5793 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5794 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5795 PrivateScope.addPrivate( 5796 VD, [&CGF, VD, XRValue, Loc]() { 5797 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5798 CGF.emitOMPSimpleStore( 5799 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5800 VD->getType().getNonReferenceType(), Loc); 5801 return LHSTemp; 5802 }); 5803 (void)PrivateScope.Privatize(); 5804 return CGF.EmitAnyExpr(UpExpr); 5805 }); 5806 }; 5807 if ((*IPriv)->getType()->isArrayType()) { 5808 // Emit atomic reduction for array section. 5809 const auto *RHSVar = 5810 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5811 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5812 AtomicRedGen, XExpr, EExpr, UpExpr); 5813 } else { 5814 // Emit atomic reduction for array subscript or single variable. 5815 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5816 } 5817 } else { 5818 // Emit as a critical region. 5819 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5820 const Expr *, const Expr *) { 5821 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5822 std::string Name = RT.getName({"atomic_reduction"}); 5823 RT.emitCriticalRegion( 5824 CGF, Name, 5825 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5826 Action.Enter(CGF); 5827 emitReductionCombiner(CGF, E); 5828 }, 5829 Loc); 5830 }; 5831 if ((*IPriv)->getType()->isArrayType()) { 5832 const auto *LHSVar = 5833 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5834 const auto *RHSVar = 5835 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5836 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5837 CritRedGen); 5838 } else { 5839 CritRedGen(CGF, nullptr, nullptr, nullptr); 5840 } 5841 } 5842 ++ILHS; 5843 ++IRHS; 5844 ++IPriv; 5845 } 5846 }; 5847 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5848 if (!WithNowait) { 5849 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5850 llvm::Value *EndArgs[] = { 5851 IdentTLoc, // ident_t *<loc> 5852 ThreadId, // i32 <gtid> 5853 Lock // kmp_critical_name *&<lock> 5854 }; 5855 CommonActionTy Action(nullptr, llvm::None, 5856 OMPBuilder.getOrCreateRuntimeFunction( 5857 CGM.getModule(), OMPRTL___kmpc_end_reduce), 5858 EndArgs); 5859 AtomicRCG.setAction(Action); 5860 AtomicRCG(CGF); 5861 } else { 5862 AtomicRCG(CGF); 5863 } 5864 5865 CGF.EmitBranch(DefaultBB); 5866 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5867 } 5868 5869 /// Generates unique name for artificial threadprivate variables. 5870 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5871 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5872 const Expr *Ref) { 5873 SmallString<256> Buffer; 5874 llvm::raw_svector_ostream Out(Buffer); 5875 const clang::DeclRefExpr *DE; 5876 const VarDecl *D = ::getBaseDecl(Ref, DE); 5877 if (!D) 5878 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5879 D = D->getCanonicalDecl(); 5880 std::string Name = CGM.getOpenMPRuntime().getName( 5881 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5882 Out << Prefix << Name << "_" 5883 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5884 return std::string(Out.str()); 5885 } 5886 5887 /// Emits reduction initializer function: 5888 /// \code 5889 /// void @.red_init(void* %arg, void* %orig) { 5890 /// %0 = bitcast void* %arg to <type>* 5891 /// store <type> <init>, <type>* %0 5892 /// ret void 5893 /// } 5894 /// \endcode 5895 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 5896 SourceLocation Loc, 5897 ReductionCodeGen &RCG, unsigned N) { 5898 ASTContext &C = CGM.getContext(); 5899 QualType VoidPtrTy = C.VoidPtrTy; 5900 VoidPtrTy.addRestrict(); 5901 FunctionArgList Args; 5902 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5903 ImplicitParamDecl::Other); 5904 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5905 ImplicitParamDecl::Other); 5906 Args.emplace_back(&Param); 5907 Args.emplace_back(&ParamOrig); 5908 const auto &FnInfo = 5909 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5910 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5911 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 5912 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5913 Name, &CGM.getModule()); 5914 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5915 Fn->setDoesNotRecurse(); 5916 CodeGenFunction CGF(CGM); 5917 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5918 Address PrivateAddr = CGF.EmitLoadOfPointer( 5919 CGF.GetAddrOfLocalVar(&Param), 5920 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5921 llvm::Value *Size = nullptr; 5922 // If the size of the reduction item is non-constant, load it from global 5923 // threadprivate variable. 5924 if (RCG.getSizes(N).second) { 5925 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5926 CGF, CGM.getContext().getSizeType(), 5927 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5928 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5929 CGM.getContext().getSizeType(), Loc); 5930 } 5931 RCG.emitAggregateType(CGF, N, Size); 5932 LValue OrigLVal; 5933 // If initializer uses initializer from declare reduction construct, emit a 5934 // pointer to the address of the original reduction item (reuired by reduction 5935 // initializer) 5936 if (RCG.usesReductionInitializer(N)) { 5937 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig); 5938 SharedAddr = CGF.EmitLoadOfPointer( 5939 SharedAddr, 5940 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 5941 OrigLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 5942 } else { 5943 OrigLVal = CGF.MakeNaturalAlignAddrLValue( 5944 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 5945 CGM.getContext().VoidPtrTy); 5946 } 5947 // Emit the initializer: 5948 // %0 = bitcast void* %arg to <type>* 5949 // store <type> <init>, <type>* %0 5950 RCG.emitInitialization(CGF, N, PrivateAddr, OrigLVal, 5951 [](CodeGenFunction &) { return false; }); 5952 CGF.FinishFunction(); 5953 return Fn; 5954 } 5955 5956 /// Emits reduction combiner function: 5957 /// \code 5958 /// void @.red_comb(void* %arg0, void* %arg1) { 5959 /// %lhs = bitcast void* %arg0 to <type>* 5960 /// %rhs = bitcast void* %arg1 to <type>* 5961 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 5962 /// store <type> %2, <type>* %lhs 5963 /// ret void 5964 /// } 5965 /// \endcode 5966 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 5967 SourceLocation Loc, 5968 ReductionCodeGen &RCG, unsigned N, 5969 const Expr *ReductionOp, 5970 const Expr *LHS, const Expr *RHS, 5971 const Expr *PrivateRef) { 5972 ASTContext &C = CGM.getContext(); 5973 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 5974 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 5975 FunctionArgList Args; 5976 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 5977 C.VoidPtrTy, ImplicitParamDecl::Other); 5978 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5979 ImplicitParamDecl::Other); 5980 Args.emplace_back(&ParamInOut); 5981 Args.emplace_back(&ParamIn); 5982 const auto &FnInfo = 5983 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5984 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5985 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 5986 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5987 Name, &CGM.getModule()); 5988 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5989 Fn->setDoesNotRecurse(); 5990 CodeGenFunction CGF(CGM); 5991 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5992 llvm::Value *Size = nullptr; 5993 // If the size of the reduction item is non-constant, load it from global 5994 // threadprivate variable. 5995 if (RCG.getSizes(N).second) { 5996 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5997 CGF, CGM.getContext().getSizeType(), 5998 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5999 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6000 CGM.getContext().getSizeType(), Loc); 6001 } 6002 RCG.emitAggregateType(CGF, N, Size); 6003 // Remap lhs and rhs variables to the addresses of the function arguments. 6004 // %lhs = bitcast void* %arg0 to <type>* 6005 // %rhs = bitcast void* %arg1 to <type>* 6006 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6007 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6008 // Pull out the pointer to the variable. 6009 Address PtrAddr = CGF.EmitLoadOfPointer( 6010 CGF.GetAddrOfLocalVar(&ParamInOut), 6011 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6012 return CGF.Builder.CreateElementBitCast( 6013 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6014 }); 6015 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6016 // Pull out the pointer to the variable. 6017 Address PtrAddr = CGF.EmitLoadOfPointer( 6018 CGF.GetAddrOfLocalVar(&ParamIn), 6019 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6020 return CGF.Builder.CreateElementBitCast( 6021 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6022 }); 6023 PrivateScope.Privatize(); 6024 // Emit the combiner body: 6025 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6026 // store <type> %2, <type>* %lhs 6027 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6028 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6029 cast<DeclRefExpr>(RHS)); 6030 CGF.FinishFunction(); 6031 return Fn; 6032 } 6033 6034 /// Emits reduction finalizer function: 6035 /// \code 6036 /// void @.red_fini(void* %arg) { 6037 /// %0 = bitcast void* %arg to <type>* 6038 /// <destroy>(<type>* %0) 6039 /// ret void 6040 /// } 6041 /// \endcode 6042 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6043 SourceLocation Loc, 6044 ReductionCodeGen &RCG, unsigned N) { 6045 if (!RCG.needCleanups(N)) 6046 return nullptr; 6047 ASTContext &C = CGM.getContext(); 6048 FunctionArgList Args; 6049 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6050 ImplicitParamDecl::Other); 6051 Args.emplace_back(&Param); 6052 const auto &FnInfo = 6053 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6054 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6055 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6056 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6057 Name, &CGM.getModule()); 6058 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6059 Fn->setDoesNotRecurse(); 6060 CodeGenFunction CGF(CGM); 6061 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6062 Address PrivateAddr = CGF.EmitLoadOfPointer( 6063 CGF.GetAddrOfLocalVar(&Param), 6064 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6065 llvm::Value *Size = nullptr; 6066 // If the size of the reduction item is non-constant, load it from global 6067 // threadprivate variable. 6068 if (RCG.getSizes(N).second) { 6069 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6070 CGF, CGM.getContext().getSizeType(), 6071 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6072 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6073 CGM.getContext().getSizeType(), Loc); 6074 } 6075 RCG.emitAggregateType(CGF, N, Size); 6076 // Emit the finalizer body: 6077 // <destroy>(<type>* %0) 6078 RCG.emitCleanups(CGF, N, PrivateAddr); 6079 CGF.FinishFunction(Loc); 6080 return Fn; 6081 } 6082 6083 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6084 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6085 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6086 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6087 return nullptr; 6088 6089 // Build typedef struct: 6090 // kmp_taskred_input { 6091 // void *reduce_shar; // shared reduction item 6092 // void *reduce_orig; // original reduction item used for initialization 6093 // size_t reduce_size; // size of data item 6094 // void *reduce_init; // data initialization routine 6095 // void *reduce_fini; // data finalization routine 6096 // void *reduce_comb; // data combiner routine 6097 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6098 // } kmp_taskred_input_t; 6099 ASTContext &C = CGM.getContext(); 6100 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t"); 6101 RD->startDefinition(); 6102 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6103 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6104 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6105 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6106 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6107 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6108 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6109 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6110 RD->completeDefinition(); 6111 QualType RDType = C.getRecordType(RD); 6112 unsigned Size = Data.ReductionVars.size(); 6113 llvm::APInt ArraySize(/*numBits=*/64, Size); 6114 QualType ArrayRDType = C.getConstantArrayType( 6115 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6116 // kmp_task_red_input_t .rd_input.[Size]; 6117 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6118 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, 6119 Data.ReductionCopies, Data.ReductionOps); 6120 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6121 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6122 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6123 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6124 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6125 TaskRedInput.getPointer(), Idxs, 6126 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6127 ".rd_input.gep."); 6128 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6129 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6130 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6131 RCG.emitSharedOrigLValue(CGF, Cnt); 6132 llvm::Value *CastedShared = 6133 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6134 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6135 // ElemLVal.reduce_orig = &Origs[Cnt]; 6136 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD); 6137 llvm::Value *CastedOrig = 6138 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF)); 6139 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal); 6140 RCG.emitAggregateType(CGF, Cnt); 6141 llvm::Value *SizeValInChars; 6142 llvm::Value *SizeVal; 6143 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6144 // We use delayed creation/initialization for VLAs and array sections. It is 6145 // required because runtime does not provide the way to pass the sizes of 6146 // VLAs/array sections to initializer/combiner/finalizer functions. Instead 6147 // threadprivate global variables are used to store these values and use 6148 // them in the functions. 6149 bool DelayedCreation = !!SizeVal; 6150 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6151 /*isSigned=*/false); 6152 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6153 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6154 // ElemLVal.reduce_init = init; 6155 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6156 llvm::Value *InitAddr = 6157 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6158 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6159 // ElemLVal.reduce_fini = fini; 6160 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6161 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6162 llvm::Value *FiniAddr = Fini 6163 ? CGF.EmitCastToVoidPtr(Fini) 6164 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6165 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6166 // ElemLVal.reduce_comb = comb; 6167 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6168 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6169 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6170 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6171 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6172 // ElemLVal.flags = 0; 6173 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6174 if (DelayedCreation) { 6175 CGF.EmitStoreOfScalar( 6176 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6177 FlagsLVal); 6178 } else 6179 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6180 FlagsLVal.getType()); 6181 } 6182 if (Data.IsReductionWithTaskMod) { 6183 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6184 // is_ws, int num, void *data); 6185 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6186 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6187 CGM.IntTy, /*isSigned=*/true); 6188 llvm::Value *Args[] = { 6189 IdentTLoc, GTid, 6190 llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0, 6191 /*isSigned=*/true), 6192 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6193 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6194 TaskRedInput.getPointer(), CGM.VoidPtrTy)}; 6195 return CGF.EmitRuntimeCall( 6196 OMPBuilder.getOrCreateRuntimeFunction( 6197 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init), 6198 Args); 6199 } 6200 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data); 6201 llvm::Value *Args[] = { 6202 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6203 /*isSigned=*/true), 6204 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6205 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6206 CGM.VoidPtrTy)}; 6207 return CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6208 CGM.getModule(), OMPRTL___kmpc_taskred_init), 6209 Args); 6210 } 6211 6212 void CGOpenMPRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 6213 SourceLocation Loc, 6214 bool IsWorksharingReduction) { 6215 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6216 // is_ws, int num, void *data); 6217 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6218 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6219 CGM.IntTy, /*isSigned=*/true); 6220 llvm::Value *Args[] = {IdentTLoc, GTid, 6221 llvm::ConstantInt::get(CGM.IntTy, 6222 IsWorksharingReduction ? 1 : 0, 6223 /*isSigned=*/true)}; 6224 (void)CGF.EmitRuntimeCall( 6225 OMPBuilder.getOrCreateRuntimeFunction( 6226 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini), 6227 Args); 6228 } 6229 6230 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6231 SourceLocation Loc, 6232 ReductionCodeGen &RCG, 6233 unsigned N) { 6234 auto Sizes = RCG.getSizes(N); 6235 // Emit threadprivate global variable if the type is non-constant 6236 // (Sizes.second = nullptr). 6237 if (Sizes.second) { 6238 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6239 /*isSigned=*/false); 6240 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6241 CGF, CGM.getContext().getSizeType(), 6242 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6243 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6244 } 6245 } 6246 6247 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6248 SourceLocation Loc, 6249 llvm::Value *ReductionsPtr, 6250 LValue SharedLVal) { 6251 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6252 // *d); 6253 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6254 CGM.IntTy, 6255 /*isSigned=*/true), 6256 ReductionsPtr, 6257 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6258 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6259 return Address( 6260 CGF.EmitRuntimeCall( 6261 OMPBuilder.getOrCreateRuntimeFunction( 6262 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data), 6263 Args), 6264 SharedLVal.getAlignment()); 6265 } 6266 6267 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6268 SourceLocation Loc) { 6269 if (!CGF.HaveInsertPoint()) 6270 return; 6271 6272 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 6273 OMPBuilder.createTaskwait(CGF.Builder); 6274 } else { 6275 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6276 // global_tid); 6277 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6278 // Ignore return result until untied tasks are supported. 6279 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6280 CGM.getModule(), OMPRTL___kmpc_omp_taskwait), 6281 Args); 6282 } 6283 6284 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6285 Region->emitUntiedSwitch(CGF); 6286 } 6287 6288 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6289 OpenMPDirectiveKind InnerKind, 6290 const RegionCodeGenTy &CodeGen, 6291 bool HasCancel) { 6292 if (!CGF.HaveInsertPoint()) 6293 return; 6294 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel, 6295 InnerKind != OMPD_critical && 6296 InnerKind != OMPD_master && 6297 InnerKind != OMPD_masked); 6298 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6299 } 6300 6301 namespace { 6302 enum RTCancelKind { 6303 CancelNoreq = 0, 6304 CancelParallel = 1, 6305 CancelLoop = 2, 6306 CancelSections = 3, 6307 CancelTaskgroup = 4 6308 }; 6309 } // anonymous namespace 6310 6311 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6312 RTCancelKind CancelKind = CancelNoreq; 6313 if (CancelRegion == OMPD_parallel) 6314 CancelKind = CancelParallel; 6315 else if (CancelRegion == OMPD_for) 6316 CancelKind = CancelLoop; 6317 else if (CancelRegion == OMPD_sections) 6318 CancelKind = CancelSections; 6319 else { 6320 assert(CancelRegion == OMPD_taskgroup); 6321 CancelKind = CancelTaskgroup; 6322 } 6323 return CancelKind; 6324 } 6325 6326 void CGOpenMPRuntime::emitCancellationPointCall( 6327 CodeGenFunction &CGF, SourceLocation Loc, 6328 OpenMPDirectiveKind CancelRegion) { 6329 if (!CGF.HaveInsertPoint()) 6330 return; 6331 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6332 // global_tid, kmp_int32 cncl_kind); 6333 if (auto *OMPRegionInfo = 6334 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6335 // For 'cancellation point taskgroup', the task region info may not have a 6336 // cancel. This may instead happen in another adjacent task. 6337 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6338 llvm::Value *Args[] = { 6339 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6340 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6341 // Ignore return result until untied tasks are supported. 6342 llvm::Value *Result = CGF.EmitRuntimeCall( 6343 OMPBuilder.getOrCreateRuntimeFunction( 6344 CGM.getModule(), OMPRTL___kmpc_cancellationpoint), 6345 Args); 6346 // if (__kmpc_cancellationpoint()) { 6347 // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only 6348 // exit from construct; 6349 // } 6350 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6351 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6352 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6353 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6354 CGF.EmitBlock(ExitBB); 6355 if (CancelRegion == OMPD_parallel) 6356 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 6357 // exit from construct; 6358 CodeGenFunction::JumpDest CancelDest = 6359 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6360 CGF.EmitBranchThroughCleanup(CancelDest); 6361 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6362 } 6363 } 6364 } 6365 6366 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6367 const Expr *IfCond, 6368 OpenMPDirectiveKind CancelRegion) { 6369 if (!CGF.HaveInsertPoint()) 6370 return; 6371 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6372 // kmp_int32 cncl_kind); 6373 auto &M = CGM.getModule(); 6374 if (auto *OMPRegionInfo = 6375 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6376 auto &&ThenGen = [this, &M, Loc, CancelRegion, 6377 OMPRegionInfo](CodeGenFunction &CGF, PrePostActionTy &) { 6378 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6379 llvm::Value *Args[] = { 6380 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6381 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6382 // Ignore return result until untied tasks are supported. 6383 llvm::Value *Result = CGF.EmitRuntimeCall( 6384 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args); 6385 // if (__kmpc_cancel()) { 6386 // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only 6387 // exit from construct; 6388 // } 6389 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6390 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6391 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6392 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6393 CGF.EmitBlock(ExitBB); 6394 if (CancelRegion == OMPD_parallel) 6395 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 6396 // exit from construct; 6397 CodeGenFunction::JumpDest CancelDest = 6398 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6399 CGF.EmitBranchThroughCleanup(CancelDest); 6400 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6401 }; 6402 if (IfCond) { 6403 emitIfClause(CGF, IfCond, ThenGen, 6404 [](CodeGenFunction &, PrePostActionTy &) {}); 6405 } else { 6406 RegionCodeGenTy ThenRCG(ThenGen); 6407 ThenRCG(CGF); 6408 } 6409 } 6410 } 6411 6412 namespace { 6413 /// Cleanup action for uses_allocators support. 6414 class OMPUsesAllocatorsActionTy final : public PrePostActionTy { 6415 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators; 6416 6417 public: 6418 OMPUsesAllocatorsActionTy( 6419 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators) 6420 : Allocators(Allocators) {} 6421 void Enter(CodeGenFunction &CGF) override { 6422 if (!CGF.HaveInsertPoint()) 6423 return; 6424 for (const auto &AllocatorData : Allocators) { 6425 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsInit( 6426 CGF, AllocatorData.first, AllocatorData.second); 6427 } 6428 } 6429 void Exit(CodeGenFunction &CGF) override { 6430 if (!CGF.HaveInsertPoint()) 6431 return; 6432 for (const auto &AllocatorData : Allocators) { 6433 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsFini(CGF, 6434 AllocatorData.first); 6435 } 6436 } 6437 }; 6438 } // namespace 6439 6440 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6441 const OMPExecutableDirective &D, StringRef ParentName, 6442 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6443 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6444 assert(!ParentName.empty() && "Invalid target region parent name!"); 6445 HasEmittedTargetRegion = true; 6446 SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators; 6447 for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) { 6448 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 6449 const OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 6450 if (!D.AllocatorTraits) 6451 continue; 6452 Allocators.emplace_back(D.Allocator, D.AllocatorTraits); 6453 } 6454 } 6455 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators); 6456 CodeGen.setAction(UsesAllocatorAction); 6457 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6458 IsOffloadEntry, CodeGen); 6459 } 6460 6461 void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, 6462 const Expr *Allocator, 6463 const Expr *AllocatorTraits) { 6464 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6465 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6466 // Use default memspace handle. 6467 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 6468 llvm::Value *NumTraits = llvm::ConstantInt::get( 6469 CGF.IntTy, cast<ConstantArrayType>( 6470 AllocatorTraits->getType()->getAsArrayTypeUnsafe()) 6471 ->getSize() 6472 .getLimitedValue()); 6473 LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits); 6474 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6475 AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy); 6476 AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, 6477 AllocatorTraitsLVal.getBaseInfo(), 6478 AllocatorTraitsLVal.getTBAAInfo()); 6479 llvm::Value *Traits = 6480 CGF.EmitLoadOfScalar(AllocatorTraitsLVal, AllocatorTraits->getExprLoc()); 6481 6482 llvm::Value *AllocatorVal = 6483 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6484 CGM.getModule(), OMPRTL___kmpc_init_allocator), 6485 {ThreadId, MemSpaceHandle, NumTraits, Traits}); 6486 // Store to allocator. 6487 CGF.EmitVarDecl(*cast<VarDecl>( 6488 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl())); 6489 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6490 AllocatorVal = 6491 CGF.EmitScalarConversion(AllocatorVal, CGF.getContext().VoidPtrTy, 6492 Allocator->getType(), Allocator->getExprLoc()); 6493 CGF.EmitStoreOfScalar(AllocatorVal, AllocatorLVal); 6494 } 6495 6496 void CGOpenMPRuntime::emitUsesAllocatorsFini(CodeGenFunction &CGF, 6497 const Expr *Allocator) { 6498 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6499 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6500 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6501 llvm::Value *AllocatorVal = 6502 CGF.EmitLoadOfScalar(AllocatorLVal, Allocator->getExprLoc()); 6503 AllocatorVal = CGF.EmitScalarConversion(AllocatorVal, Allocator->getType(), 6504 CGF.getContext().VoidPtrTy, 6505 Allocator->getExprLoc()); 6506 (void)CGF.EmitRuntimeCall( 6507 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 6508 OMPRTL___kmpc_destroy_allocator), 6509 {ThreadId, AllocatorVal}); 6510 } 6511 6512 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6513 const OMPExecutableDirective &D, StringRef ParentName, 6514 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6515 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6516 // Create a unique name for the entry function using the source location 6517 // information of the current target region. The name will be something like: 6518 // 6519 // __omp_offloading_DD_FFFF_PP_lBB 6520 // 6521 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6522 // mangled name of the function that encloses the target region and BB is the 6523 // line number of the target region. 6524 6525 unsigned DeviceID; 6526 unsigned FileID; 6527 unsigned Line; 6528 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6529 Line); 6530 SmallString<64> EntryFnName; 6531 { 6532 llvm::raw_svector_ostream OS(EntryFnName); 6533 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6534 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6535 } 6536 6537 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6538 6539 CodeGenFunction CGF(CGM, true); 6540 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6541 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6542 6543 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6544 6545 // If this target outline function is not an offload entry, we don't need to 6546 // register it. 6547 if (!IsOffloadEntry) 6548 return; 6549 6550 // The target region ID is used by the runtime library to identify the current 6551 // target region, so it only has to be unique and not necessarily point to 6552 // anything. It could be the pointer to the outlined function that implements 6553 // the target region, but we aren't using that so that the compiler doesn't 6554 // need to keep that, and could therefore inline the host function if proven 6555 // worthwhile during optimization. In the other hand, if emitting code for the 6556 // device, the ID has to be the function address so that it can retrieved from 6557 // the offloading entry and launched by the runtime library. We also mark the 6558 // outlined function to have external linkage in case we are emitting code for 6559 // the device, because these functions will be entry points to the device. 6560 6561 if (CGM.getLangOpts().OpenMPIsDevice) { 6562 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6563 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6564 OutlinedFn->setDSOLocal(false); 6565 if (CGM.getTriple().isAMDGCN()) 6566 OutlinedFn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); 6567 } else { 6568 std::string Name = getName({EntryFnName, "region_id"}); 6569 OutlinedFnID = new llvm::GlobalVariable( 6570 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6571 llvm::GlobalValue::WeakAnyLinkage, 6572 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6573 } 6574 6575 // Register the information for the entry associated with this target region. 6576 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6577 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6578 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6579 6580 // Add NumTeams and ThreadLimit attributes to the outlined GPU function 6581 int32_t DefaultValTeams = -1; 6582 getNumTeamsExprForTargetDirective(CGF, D, DefaultValTeams); 6583 if (DefaultValTeams > 0) { 6584 OutlinedFn->addFnAttr("omp_target_num_teams", 6585 std::to_string(DefaultValTeams)); 6586 } 6587 int32_t DefaultValThreads = -1; 6588 getNumThreadsExprForTargetDirective(CGF, D, DefaultValThreads); 6589 if (DefaultValThreads > 0) { 6590 OutlinedFn->addFnAttr("omp_target_thread_limit", 6591 std::to_string(DefaultValThreads)); 6592 } 6593 } 6594 6595 /// Checks if the expression is constant or does not have non-trivial function 6596 /// calls. 6597 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6598 // We can skip constant expressions. 6599 // We can skip expressions with trivial calls or simple expressions. 6600 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6601 !E->hasNonTrivialCall(Ctx)) && 6602 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6603 } 6604 6605 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6606 const Stmt *Body) { 6607 const Stmt *Child = Body->IgnoreContainers(); 6608 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6609 Child = nullptr; 6610 for (const Stmt *S : C->body()) { 6611 if (const auto *E = dyn_cast<Expr>(S)) { 6612 if (isTrivial(Ctx, E)) 6613 continue; 6614 } 6615 // Some of the statements can be ignored. 6616 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6617 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6618 continue; 6619 // Analyze declarations. 6620 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6621 if (llvm::all_of(DS->decls(), [](const Decl *D) { 6622 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6623 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6624 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6625 isa<UsingDirectiveDecl>(D) || 6626 isa<OMPDeclareReductionDecl>(D) || 6627 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6628 return true; 6629 const auto *VD = dyn_cast<VarDecl>(D); 6630 if (!VD) 6631 return false; 6632 return VD->hasGlobalStorage() || !VD->isUsed(); 6633 })) 6634 continue; 6635 } 6636 // Found multiple children - cannot get the one child only. 6637 if (Child) 6638 return nullptr; 6639 Child = S; 6640 } 6641 if (Child) 6642 Child = Child->IgnoreContainers(); 6643 } 6644 return Child; 6645 } 6646 6647 const Expr *CGOpenMPRuntime::getNumTeamsExprForTargetDirective( 6648 CodeGenFunction &CGF, const OMPExecutableDirective &D, 6649 int32_t &DefaultVal) { 6650 6651 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6652 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6653 "Expected target-based executable directive."); 6654 switch (DirectiveKind) { 6655 case OMPD_target: { 6656 const auto *CS = D.getInnermostCapturedStmt(); 6657 const auto *Body = 6658 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6659 const Stmt *ChildStmt = 6660 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6661 if (const auto *NestedDir = 6662 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6663 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6664 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6665 const Expr *NumTeams = 6666 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6667 if (NumTeams->isIntegerConstantExpr(CGF.getContext())) 6668 if (auto Constant = 6669 NumTeams->getIntegerConstantExpr(CGF.getContext())) 6670 DefaultVal = Constant->getExtValue(); 6671 return NumTeams; 6672 } 6673 DefaultVal = 0; 6674 return nullptr; 6675 } 6676 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6677 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) { 6678 DefaultVal = 1; 6679 return nullptr; 6680 } 6681 DefaultVal = 1; 6682 return nullptr; 6683 } 6684 // A value of -1 is used to check if we need to emit no teams region 6685 DefaultVal = -1; 6686 return nullptr; 6687 } 6688 case OMPD_target_teams: 6689 case OMPD_target_teams_distribute: 6690 case OMPD_target_teams_distribute_simd: 6691 case OMPD_target_teams_distribute_parallel_for: 6692 case OMPD_target_teams_distribute_parallel_for_simd: { 6693 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6694 const Expr *NumTeams = 6695 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6696 if (NumTeams->isIntegerConstantExpr(CGF.getContext())) 6697 if (auto Constant = NumTeams->getIntegerConstantExpr(CGF.getContext())) 6698 DefaultVal = Constant->getExtValue(); 6699 return NumTeams; 6700 } 6701 DefaultVal = 0; 6702 return nullptr; 6703 } 6704 case OMPD_target_parallel: 6705 case OMPD_target_parallel_for: 6706 case OMPD_target_parallel_for_simd: 6707 case OMPD_target_simd: 6708 DefaultVal = 1; 6709 return nullptr; 6710 case OMPD_parallel: 6711 case OMPD_for: 6712 case OMPD_parallel_for: 6713 case OMPD_parallel_master: 6714 case OMPD_parallel_sections: 6715 case OMPD_for_simd: 6716 case OMPD_parallel_for_simd: 6717 case OMPD_cancel: 6718 case OMPD_cancellation_point: 6719 case OMPD_ordered: 6720 case OMPD_threadprivate: 6721 case OMPD_allocate: 6722 case OMPD_task: 6723 case OMPD_simd: 6724 case OMPD_tile: 6725 case OMPD_unroll: 6726 case OMPD_sections: 6727 case OMPD_section: 6728 case OMPD_single: 6729 case OMPD_master: 6730 case OMPD_critical: 6731 case OMPD_taskyield: 6732 case OMPD_barrier: 6733 case OMPD_taskwait: 6734 case OMPD_taskgroup: 6735 case OMPD_atomic: 6736 case OMPD_flush: 6737 case OMPD_depobj: 6738 case OMPD_scan: 6739 case OMPD_teams: 6740 case OMPD_target_data: 6741 case OMPD_target_exit_data: 6742 case OMPD_target_enter_data: 6743 case OMPD_distribute: 6744 case OMPD_distribute_simd: 6745 case OMPD_distribute_parallel_for: 6746 case OMPD_distribute_parallel_for_simd: 6747 case OMPD_teams_distribute: 6748 case OMPD_teams_distribute_simd: 6749 case OMPD_teams_distribute_parallel_for: 6750 case OMPD_teams_distribute_parallel_for_simd: 6751 case OMPD_target_update: 6752 case OMPD_declare_simd: 6753 case OMPD_declare_variant: 6754 case OMPD_begin_declare_variant: 6755 case OMPD_end_declare_variant: 6756 case OMPD_declare_target: 6757 case OMPD_end_declare_target: 6758 case OMPD_declare_reduction: 6759 case OMPD_declare_mapper: 6760 case OMPD_taskloop: 6761 case OMPD_taskloop_simd: 6762 case OMPD_master_taskloop: 6763 case OMPD_master_taskloop_simd: 6764 case OMPD_parallel_master_taskloop: 6765 case OMPD_parallel_master_taskloop_simd: 6766 case OMPD_requires: 6767 case OMPD_metadirective: 6768 case OMPD_unknown: 6769 break; 6770 default: 6771 break; 6772 } 6773 llvm_unreachable("Unexpected directive kind."); 6774 } 6775 6776 llvm::Value *CGOpenMPRuntime::emitNumTeamsForTargetDirective( 6777 CodeGenFunction &CGF, const OMPExecutableDirective &D) { 6778 assert(!CGF.getLangOpts().OpenMPIsDevice && 6779 "Clauses associated with the teams directive expected to be emitted " 6780 "only for the host!"); 6781 CGBuilderTy &Bld = CGF.Builder; 6782 int32_t DefaultNT = -1; 6783 const Expr *NumTeams = getNumTeamsExprForTargetDirective(CGF, D, DefaultNT); 6784 if (NumTeams != nullptr) { 6785 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6786 6787 switch (DirectiveKind) { 6788 case OMPD_target: { 6789 const auto *CS = D.getInnermostCapturedStmt(); 6790 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6791 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6792 llvm::Value *NumTeamsVal = CGF.EmitScalarExpr(NumTeams, 6793 /*IgnoreResultAssign*/ true); 6794 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6795 /*isSigned=*/true); 6796 } 6797 case OMPD_target_teams: 6798 case OMPD_target_teams_distribute: 6799 case OMPD_target_teams_distribute_simd: 6800 case OMPD_target_teams_distribute_parallel_for: 6801 case OMPD_target_teams_distribute_parallel_for_simd: { 6802 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6803 llvm::Value *NumTeamsVal = CGF.EmitScalarExpr(NumTeams, 6804 /*IgnoreResultAssign*/ true); 6805 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6806 /*isSigned=*/true); 6807 } 6808 default: 6809 break; 6810 } 6811 } else if (DefaultNT == -1) { 6812 return nullptr; 6813 } 6814 6815 return Bld.getInt32(DefaultNT); 6816 } 6817 6818 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6819 llvm::Value *DefaultThreadLimitVal) { 6820 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6821 CGF.getContext(), CS->getCapturedStmt()); 6822 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6823 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6824 llvm::Value *NumThreads = nullptr; 6825 llvm::Value *CondVal = nullptr; 6826 // Handle if clause. If if clause present, the number of threads is 6827 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6828 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6829 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6830 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6831 const OMPIfClause *IfClause = nullptr; 6832 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6833 if (C->getNameModifier() == OMPD_unknown || 6834 C->getNameModifier() == OMPD_parallel) { 6835 IfClause = C; 6836 break; 6837 } 6838 } 6839 if (IfClause) { 6840 const Expr *Cond = IfClause->getCondition(); 6841 bool Result; 6842 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6843 if (!Result) 6844 return CGF.Builder.getInt32(1); 6845 } else { 6846 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6847 if (const auto *PreInit = 6848 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6849 for (const auto *I : PreInit->decls()) { 6850 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6851 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6852 } else { 6853 CodeGenFunction::AutoVarEmission Emission = 6854 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6855 CGF.EmitAutoVarCleanups(Emission); 6856 } 6857 } 6858 } 6859 CondVal = CGF.EvaluateExprAsBool(Cond); 6860 } 6861 } 6862 } 6863 // Check the value of num_threads clause iff if clause was not specified 6864 // or is not evaluated to false. 6865 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6866 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6867 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6868 const auto *NumThreadsClause = 6869 Dir->getSingleClause<OMPNumThreadsClause>(); 6870 CodeGenFunction::LexicalScope Scope( 6871 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6872 if (const auto *PreInit = 6873 cast_or_null<DeclStmt>(NumThreadsClause->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 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6885 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6886 /*isSigned=*/false); 6887 if (DefaultThreadLimitVal) 6888 NumThreads = CGF.Builder.CreateSelect( 6889 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6890 DefaultThreadLimitVal, NumThreads); 6891 } else { 6892 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6893 : CGF.Builder.getInt32(0); 6894 } 6895 // Process condition of the if clause. 6896 if (CondVal) { 6897 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6898 CGF.Builder.getInt32(1)); 6899 } 6900 return NumThreads; 6901 } 6902 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6903 return CGF.Builder.getInt32(1); 6904 return DefaultThreadLimitVal; 6905 } 6906 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6907 : CGF.Builder.getInt32(0); 6908 } 6909 6910 const Expr *CGOpenMPRuntime::getNumThreadsExprForTargetDirective( 6911 CodeGenFunction &CGF, const OMPExecutableDirective &D, 6912 int32_t &DefaultVal) { 6913 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6914 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6915 "Expected target-based executable directive."); 6916 6917 switch (DirectiveKind) { 6918 case OMPD_target: 6919 // Teams have no clause thread_limit 6920 return nullptr; 6921 case OMPD_target_teams: 6922 case OMPD_target_teams_distribute: 6923 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6924 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6925 const Expr *ThreadLimit = ThreadLimitClause->getThreadLimit(); 6926 if (ThreadLimit->isIntegerConstantExpr(CGF.getContext())) 6927 if (auto Constant = 6928 ThreadLimit->getIntegerConstantExpr(CGF.getContext())) 6929 DefaultVal = Constant->getExtValue(); 6930 return ThreadLimit; 6931 } 6932 return nullptr; 6933 case OMPD_target_parallel: 6934 case OMPD_target_parallel_for: 6935 case OMPD_target_parallel_for_simd: 6936 case OMPD_target_teams_distribute_parallel_for: 6937 case OMPD_target_teams_distribute_parallel_for_simd: { 6938 Expr *ThreadLimit = nullptr; 6939 Expr *NumThreads = nullptr; 6940 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6941 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6942 ThreadLimit = ThreadLimitClause->getThreadLimit(); 6943 if (ThreadLimit->isIntegerConstantExpr(CGF.getContext())) 6944 if (auto Constant = 6945 ThreadLimit->getIntegerConstantExpr(CGF.getContext())) 6946 DefaultVal = Constant->getExtValue(); 6947 } 6948 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6949 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6950 NumThreads = NumThreadsClause->getNumThreads(); 6951 if (NumThreads->isIntegerConstantExpr(CGF.getContext())) { 6952 if (auto Constant = 6953 NumThreads->getIntegerConstantExpr(CGF.getContext())) { 6954 if (Constant->getExtValue() < DefaultVal) { 6955 DefaultVal = Constant->getExtValue(); 6956 ThreadLimit = NumThreads; 6957 } 6958 } 6959 } 6960 } 6961 return ThreadLimit; 6962 } 6963 case OMPD_target_teams_distribute_simd: 6964 case OMPD_target_simd: 6965 DefaultVal = 1; 6966 return nullptr; 6967 case OMPD_parallel: 6968 case OMPD_for: 6969 case OMPD_parallel_for: 6970 case OMPD_parallel_master: 6971 case OMPD_parallel_sections: 6972 case OMPD_for_simd: 6973 case OMPD_parallel_for_simd: 6974 case OMPD_cancel: 6975 case OMPD_cancellation_point: 6976 case OMPD_ordered: 6977 case OMPD_threadprivate: 6978 case OMPD_allocate: 6979 case OMPD_task: 6980 case OMPD_simd: 6981 case OMPD_tile: 6982 case OMPD_unroll: 6983 case OMPD_sections: 6984 case OMPD_section: 6985 case OMPD_single: 6986 case OMPD_master: 6987 case OMPD_critical: 6988 case OMPD_taskyield: 6989 case OMPD_barrier: 6990 case OMPD_taskwait: 6991 case OMPD_taskgroup: 6992 case OMPD_atomic: 6993 case OMPD_flush: 6994 case OMPD_depobj: 6995 case OMPD_scan: 6996 case OMPD_teams: 6997 case OMPD_target_data: 6998 case OMPD_target_exit_data: 6999 case OMPD_target_enter_data: 7000 case OMPD_distribute: 7001 case OMPD_distribute_simd: 7002 case OMPD_distribute_parallel_for: 7003 case OMPD_distribute_parallel_for_simd: 7004 case OMPD_teams_distribute: 7005 case OMPD_teams_distribute_simd: 7006 case OMPD_teams_distribute_parallel_for: 7007 case OMPD_teams_distribute_parallel_for_simd: 7008 case OMPD_target_update: 7009 case OMPD_declare_simd: 7010 case OMPD_declare_variant: 7011 case OMPD_begin_declare_variant: 7012 case OMPD_end_declare_variant: 7013 case OMPD_declare_target: 7014 case OMPD_end_declare_target: 7015 case OMPD_declare_reduction: 7016 case OMPD_declare_mapper: 7017 case OMPD_taskloop: 7018 case OMPD_taskloop_simd: 7019 case OMPD_master_taskloop: 7020 case OMPD_master_taskloop_simd: 7021 case OMPD_parallel_master_taskloop: 7022 case OMPD_parallel_master_taskloop_simd: 7023 case OMPD_requires: 7024 case OMPD_unknown: 7025 break; 7026 default: 7027 break; 7028 } 7029 llvm_unreachable("Unsupported directive kind."); 7030 } 7031 7032 llvm::Value *CGOpenMPRuntime::emitNumThreadsForTargetDirective( 7033 CodeGenFunction &CGF, const OMPExecutableDirective &D) { 7034 assert(!CGF.getLangOpts().OpenMPIsDevice && 7035 "Clauses associated with the teams directive expected to be emitted " 7036 "only for the host!"); 7037 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 7038 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 7039 "Expected target-based executable directive."); 7040 CGBuilderTy &Bld = CGF.Builder; 7041 llvm::Value *ThreadLimitVal = nullptr; 7042 llvm::Value *NumThreadsVal = nullptr; 7043 switch (DirectiveKind) { 7044 case OMPD_target: { 7045 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7046 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7047 return NumThreads; 7048 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7049 CGF.getContext(), CS->getCapturedStmt()); 7050 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7051 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 7052 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7053 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7054 const auto *ThreadLimitClause = 7055 Dir->getSingleClause<OMPThreadLimitClause>(); 7056 CodeGenFunction::LexicalScope Scope( 7057 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 7058 if (const auto *PreInit = 7059 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 7060 for (const auto *I : PreInit->decls()) { 7061 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7062 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7063 } else { 7064 CodeGenFunction::AutoVarEmission Emission = 7065 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7066 CGF.EmitAutoVarCleanups(Emission); 7067 } 7068 } 7069 } 7070 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7071 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7072 ThreadLimitVal = 7073 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7074 } 7075 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 7076 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 7077 CS = Dir->getInnermostCapturedStmt(); 7078 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7079 CGF.getContext(), CS->getCapturedStmt()); 7080 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 7081 } 7082 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 7083 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 7084 CS = Dir->getInnermostCapturedStmt(); 7085 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7086 return NumThreads; 7087 } 7088 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 7089 return Bld.getInt32(1); 7090 } 7091 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7092 } 7093 case OMPD_target_teams: { 7094 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7095 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7096 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7097 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7098 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7099 ThreadLimitVal = 7100 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7101 } 7102 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7103 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7104 return NumThreads; 7105 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7106 CGF.getContext(), CS->getCapturedStmt()); 7107 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7108 if (Dir->getDirectiveKind() == OMPD_distribute) { 7109 CS = Dir->getInnermostCapturedStmt(); 7110 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7111 return NumThreads; 7112 } 7113 } 7114 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7115 } 7116 case OMPD_target_teams_distribute: 7117 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7118 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7119 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7120 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7121 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7122 ThreadLimitVal = 7123 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7124 } 7125 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 7126 case OMPD_target_parallel: 7127 case OMPD_target_parallel_for: 7128 case OMPD_target_parallel_for_simd: 7129 case OMPD_target_teams_distribute_parallel_for: 7130 case OMPD_target_teams_distribute_parallel_for_simd: { 7131 llvm::Value *CondVal = nullptr; 7132 // Handle if clause. If if clause present, the number of threads is 7133 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 7134 if (D.hasClausesOfKind<OMPIfClause>()) { 7135 const OMPIfClause *IfClause = nullptr; 7136 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 7137 if (C->getNameModifier() == OMPD_unknown || 7138 C->getNameModifier() == OMPD_parallel) { 7139 IfClause = C; 7140 break; 7141 } 7142 } 7143 if (IfClause) { 7144 const Expr *Cond = IfClause->getCondition(); 7145 bool Result; 7146 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7147 if (!Result) 7148 return Bld.getInt32(1); 7149 } else { 7150 CodeGenFunction::RunCleanupsScope Scope(CGF); 7151 CondVal = CGF.EvaluateExprAsBool(Cond); 7152 } 7153 } 7154 } 7155 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7156 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7157 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7158 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7159 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7160 ThreadLimitVal = 7161 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7162 } 7163 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 7164 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 7165 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 7166 llvm::Value *NumThreads = CGF.EmitScalarExpr( 7167 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 7168 NumThreadsVal = 7169 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 7170 ThreadLimitVal = ThreadLimitVal 7171 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 7172 ThreadLimitVal), 7173 NumThreadsVal, ThreadLimitVal) 7174 : NumThreadsVal; 7175 } 7176 if (!ThreadLimitVal) 7177 ThreadLimitVal = Bld.getInt32(0); 7178 if (CondVal) 7179 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 7180 return ThreadLimitVal; 7181 } 7182 case OMPD_target_teams_distribute_simd: 7183 case OMPD_target_simd: 7184 return Bld.getInt32(1); 7185 case OMPD_parallel: 7186 case OMPD_for: 7187 case OMPD_parallel_for: 7188 case OMPD_parallel_master: 7189 case OMPD_parallel_sections: 7190 case OMPD_for_simd: 7191 case OMPD_parallel_for_simd: 7192 case OMPD_cancel: 7193 case OMPD_cancellation_point: 7194 case OMPD_ordered: 7195 case OMPD_threadprivate: 7196 case OMPD_allocate: 7197 case OMPD_task: 7198 case OMPD_simd: 7199 case OMPD_tile: 7200 case OMPD_unroll: 7201 case OMPD_sections: 7202 case OMPD_section: 7203 case OMPD_single: 7204 case OMPD_master: 7205 case OMPD_critical: 7206 case OMPD_taskyield: 7207 case OMPD_barrier: 7208 case OMPD_taskwait: 7209 case OMPD_taskgroup: 7210 case OMPD_atomic: 7211 case OMPD_flush: 7212 case OMPD_depobj: 7213 case OMPD_scan: 7214 case OMPD_teams: 7215 case OMPD_target_data: 7216 case OMPD_target_exit_data: 7217 case OMPD_target_enter_data: 7218 case OMPD_distribute: 7219 case OMPD_distribute_simd: 7220 case OMPD_distribute_parallel_for: 7221 case OMPD_distribute_parallel_for_simd: 7222 case OMPD_teams_distribute: 7223 case OMPD_teams_distribute_simd: 7224 case OMPD_teams_distribute_parallel_for: 7225 case OMPD_teams_distribute_parallel_for_simd: 7226 case OMPD_target_update: 7227 case OMPD_declare_simd: 7228 case OMPD_declare_variant: 7229 case OMPD_begin_declare_variant: 7230 case OMPD_end_declare_variant: 7231 case OMPD_declare_target: 7232 case OMPD_end_declare_target: 7233 case OMPD_declare_reduction: 7234 case OMPD_declare_mapper: 7235 case OMPD_taskloop: 7236 case OMPD_taskloop_simd: 7237 case OMPD_master_taskloop: 7238 case OMPD_master_taskloop_simd: 7239 case OMPD_parallel_master_taskloop: 7240 case OMPD_parallel_master_taskloop_simd: 7241 case OMPD_requires: 7242 case OMPD_metadirective: 7243 case OMPD_unknown: 7244 break; 7245 default: 7246 break; 7247 } 7248 llvm_unreachable("Unsupported directive kind."); 7249 } 7250 7251 namespace { 7252 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7253 7254 // Utility to handle information from clauses associated with a given 7255 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7256 // It provides a convenient interface to obtain the information and generate 7257 // code for that information. 7258 class MappableExprsHandler { 7259 public: 7260 /// Values for bit flags used to specify the mapping type for 7261 /// offloading. 7262 enum OpenMPOffloadMappingFlags : uint64_t { 7263 /// No flags 7264 OMP_MAP_NONE = 0x0, 7265 /// Allocate memory on the device and move data from host to device. 7266 OMP_MAP_TO = 0x01, 7267 /// Allocate memory on the device and move data from device to host. 7268 OMP_MAP_FROM = 0x02, 7269 /// Always perform the requested mapping action on the element, even 7270 /// if it was already mapped before. 7271 OMP_MAP_ALWAYS = 0x04, 7272 /// Delete the element from the device environment, ignoring the 7273 /// current reference count associated with the element. 7274 OMP_MAP_DELETE = 0x08, 7275 /// The element being mapped is a pointer-pointee pair; both the 7276 /// pointer and the pointee should be mapped. 7277 OMP_MAP_PTR_AND_OBJ = 0x10, 7278 /// This flags signals that the base address of an entry should be 7279 /// passed to the target kernel as an argument. 7280 OMP_MAP_TARGET_PARAM = 0x20, 7281 /// Signal that the runtime library has to return the device pointer 7282 /// in the current position for the data being mapped. Used when we have the 7283 /// use_device_ptr or use_device_addr clause. 7284 OMP_MAP_RETURN_PARAM = 0x40, 7285 /// This flag signals that the reference being passed is a pointer to 7286 /// private data. 7287 OMP_MAP_PRIVATE = 0x80, 7288 /// Pass the element to the device by value. 7289 OMP_MAP_LITERAL = 0x100, 7290 /// Implicit map 7291 OMP_MAP_IMPLICIT = 0x200, 7292 /// Close is a hint to the runtime to allocate memory close to 7293 /// the target device. 7294 OMP_MAP_CLOSE = 0x400, 7295 /// 0x800 is reserved for compatibility with XLC. 7296 /// Produce a runtime error if the data is not already allocated. 7297 OMP_MAP_PRESENT = 0x1000, 7298 // Increment and decrement a separate reference counter so that the data 7299 // cannot be unmapped within the associated region. Thus, this flag is 7300 // intended to be used on 'target' and 'target data' directives because they 7301 // are inherently structured. It is not intended to be used on 'target 7302 // enter data' and 'target exit data' directives because they are inherently 7303 // dynamic. 7304 // This is an OpenMP extension for the sake of OpenACC support. 7305 OMP_MAP_OMPX_HOLD = 0x2000, 7306 /// Signal that the runtime library should use args as an array of 7307 /// descriptor_dim pointers and use args_size as dims. Used when we have 7308 /// non-contiguous list items in target update directive 7309 OMP_MAP_NON_CONTIG = 0x100000000000, 7310 /// The 16 MSBs of the flags indicate whether the entry is member of some 7311 /// struct/class. 7312 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7313 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7314 }; 7315 7316 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7317 static unsigned getFlagMemberOffset() { 7318 unsigned Offset = 0; 7319 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7320 Remain = Remain >> 1) 7321 Offset++; 7322 return Offset; 7323 } 7324 7325 /// Class that holds debugging information for a data mapping to be passed to 7326 /// the runtime library. 7327 class MappingExprInfo { 7328 /// The variable declaration used for the data mapping. 7329 const ValueDecl *MapDecl = nullptr; 7330 /// The original expression used in the map clause, or null if there is 7331 /// none. 7332 const Expr *MapExpr = nullptr; 7333 7334 public: 7335 MappingExprInfo(const ValueDecl *MapDecl, const Expr *MapExpr = nullptr) 7336 : MapDecl(MapDecl), MapExpr(MapExpr) {} 7337 7338 const ValueDecl *getMapDecl() const { return MapDecl; } 7339 const Expr *getMapExpr() const { return MapExpr; } 7340 }; 7341 7342 /// Class that associates information with a base pointer to be passed to the 7343 /// runtime library. 7344 class BasePointerInfo { 7345 /// The base pointer. 7346 llvm::Value *Ptr = nullptr; 7347 /// The base declaration that refers to this device pointer, or null if 7348 /// there is none. 7349 const ValueDecl *DevPtrDecl = nullptr; 7350 7351 public: 7352 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7353 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7354 llvm::Value *operator*() const { return Ptr; } 7355 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7356 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7357 }; 7358 7359 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>; 7360 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7361 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7362 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7363 using MapMappersArrayTy = SmallVector<const ValueDecl *, 4>; 7364 using MapDimArrayTy = SmallVector<uint64_t, 4>; 7365 using MapNonContiguousArrayTy = SmallVector<MapValuesArrayTy, 4>; 7366 7367 /// This structure contains combined information generated for mappable 7368 /// clauses, including base pointers, pointers, sizes, map types, user-defined 7369 /// mappers, and non-contiguous information. 7370 struct MapCombinedInfoTy { 7371 struct StructNonContiguousInfo { 7372 bool IsNonContiguous = false; 7373 MapDimArrayTy Dims; 7374 MapNonContiguousArrayTy Offsets; 7375 MapNonContiguousArrayTy Counts; 7376 MapNonContiguousArrayTy Strides; 7377 }; 7378 MapExprsArrayTy Exprs; 7379 MapBaseValuesArrayTy BasePointers; 7380 MapValuesArrayTy Pointers; 7381 MapValuesArrayTy Sizes; 7382 MapFlagsArrayTy Types; 7383 MapMappersArrayTy Mappers; 7384 StructNonContiguousInfo NonContigInfo; 7385 7386 /// Append arrays in \a CurInfo. 7387 void append(MapCombinedInfoTy &CurInfo) { 7388 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end()); 7389 BasePointers.append(CurInfo.BasePointers.begin(), 7390 CurInfo.BasePointers.end()); 7391 Pointers.append(CurInfo.Pointers.begin(), CurInfo.Pointers.end()); 7392 Sizes.append(CurInfo.Sizes.begin(), CurInfo.Sizes.end()); 7393 Types.append(CurInfo.Types.begin(), CurInfo.Types.end()); 7394 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end()); 7395 NonContigInfo.Dims.append(CurInfo.NonContigInfo.Dims.begin(), 7396 CurInfo.NonContigInfo.Dims.end()); 7397 NonContigInfo.Offsets.append(CurInfo.NonContigInfo.Offsets.begin(), 7398 CurInfo.NonContigInfo.Offsets.end()); 7399 NonContigInfo.Counts.append(CurInfo.NonContigInfo.Counts.begin(), 7400 CurInfo.NonContigInfo.Counts.end()); 7401 NonContigInfo.Strides.append(CurInfo.NonContigInfo.Strides.begin(), 7402 CurInfo.NonContigInfo.Strides.end()); 7403 } 7404 }; 7405 7406 /// Map between a struct and the its lowest & highest elements which have been 7407 /// mapped. 7408 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7409 /// HE(FieldIndex, Pointer)} 7410 struct StructRangeInfoTy { 7411 MapCombinedInfoTy PreliminaryMapData; 7412 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7413 0, Address::invalid()}; 7414 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7415 0, Address::invalid()}; 7416 Address Base = Address::invalid(); 7417 Address LB = Address::invalid(); 7418 bool IsArraySection = false; 7419 bool HasCompleteRecord = false; 7420 }; 7421 7422 private: 7423 /// Kind that defines how a device pointer has to be returned. 7424 struct MapInfo { 7425 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7426 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7427 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7428 ArrayRef<OpenMPMotionModifierKind> MotionModifiers; 7429 bool ReturnDevicePointer = false; 7430 bool IsImplicit = false; 7431 const ValueDecl *Mapper = nullptr; 7432 const Expr *VarRef = nullptr; 7433 bool ForDeviceAddr = false; 7434 7435 MapInfo() = default; 7436 MapInfo( 7437 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7438 OpenMPMapClauseKind MapType, 7439 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7440 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7441 bool ReturnDevicePointer, bool IsImplicit, 7442 const ValueDecl *Mapper = nullptr, const Expr *VarRef = nullptr, 7443 bool ForDeviceAddr = false) 7444 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7445 MotionModifiers(MotionModifiers), 7446 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit), 7447 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {} 7448 }; 7449 7450 /// If use_device_ptr or use_device_addr is used on a decl which is a struct 7451 /// member and there is no map information about it, then emission of that 7452 /// entry is deferred until the whole struct has been processed. 7453 struct DeferredDevicePtrEntryTy { 7454 const Expr *IE = nullptr; 7455 const ValueDecl *VD = nullptr; 7456 bool ForDeviceAddr = false; 7457 7458 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD, 7459 bool ForDeviceAddr) 7460 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {} 7461 }; 7462 7463 /// The target directive from where the mappable clauses were extracted. It 7464 /// is either a executable directive or a user-defined mapper directive. 7465 llvm::PointerUnion<const OMPExecutableDirective *, 7466 const OMPDeclareMapperDecl *> 7467 CurDir; 7468 7469 /// Function the directive is being generated for. 7470 CodeGenFunction &CGF; 7471 7472 /// Set of all first private variables in the current directive. 7473 /// bool data is set to true if the variable is implicitly marked as 7474 /// firstprivate, false otherwise. 7475 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7476 7477 /// Map between device pointer declarations and their expression components. 7478 /// The key value for declarations in 'this' is null. 7479 llvm::DenseMap< 7480 const ValueDecl *, 7481 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7482 DevPointersMap; 7483 7484 /// Map between lambda declarations and their map type. 7485 llvm::DenseMap<const ValueDecl *, const OMPMapClause *> LambdasMap; 7486 7487 llvm::Value *getExprTypeSize(const Expr *E) const { 7488 QualType ExprTy = E->getType().getCanonicalType(); 7489 7490 // Calculate the size for array shaping expression. 7491 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) { 7492 llvm::Value *Size = 7493 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType()); 7494 for (const Expr *SE : OAE->getDimensions()) { 7495 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 7496 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 7497 CGF.getContext().getSizeType(), 7498 SE->getExprLoc()); 7499 Size = CGF.Builder.CreateNUWMul(Size, Sz); 7500 } 7501 return Size; 7502 } 7503 7504 // Reference types are ignored for mapping purposes. 7505 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7506 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7507 7508 // Given that an array section is considered a built-in type, we need to 7509 // do the calculation based on the length of the section instead of relying 7510 // on CGF.getTypeSize(E->getType()). 7511 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7512 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7513 OAE->getBase()->IgnoreParenImpCasts()) 7514 .getCanonicalType(); 7515 7516 // If there is no length associated with the expression and lower bound is 7517 // not specified too, that means we are using the whole length of the 7518 // base. 7519 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7520 !OAE->getLowerBound()) 7521 return CGF.getTypeSize(BaseTy); 7522 7523 llvm::Value *ElemSize; 7524 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7525 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7526 } else { 7527 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7528 assert(ATy && "Expecting array type if not a pointer type."); 7529 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7530 } 7531 7532 // If we don't have a length at this point, that is because we have an 7533 // array section with a single element. 7534 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid()) 7535 return ElemSize; 7536 7537 if (const Expr *LenExpr = OAE->getLength()) { 7538 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7539 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7540 CGF.getContext().getSizeType(), 7541 LenExpr->getExprLoc()); 7542 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7543 } 7544 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7545 OAE->getLowerBound() && "expected array_section[lb:]."); 7546 // Size = sizetype - lb * elemtype; 7547 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7548 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7549 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7550 CGF.getContext().getSizeType(), 7551 OAE->getLowerBound()->getExprLoc()); 7552 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7553 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7554 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7555 LengthVal = CGF.Builder.CreateSelect( 7556 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7557 return LengthVal; 7558 } 7559 return CGF.getTypeSize(ExprTy); 7560 } 7561 7562 /// Return the corresponding bits for a given map clause modifier. Add 7563 /// a flag marking the map as a pointer if requested. Add a flag marking the 7564 /// map as the first one of a series of maps that relate to the same map 7565 /// expression. 7566 OpenMPOffloadMappingFlags getMapTypeBits( 7567 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7568 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit, 7569 bool AddPtrFlag, bool AddIsTargetParamFlag, bool IsNonContiguous) const { 7570 OpenMPOffloadMappingFlags Bits = 7571 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7572 switch (MapType) { 7573 case OMPC_MAP_alloc: 7574 case OMPC_MAP_release: 7575 // alloc and release is the default behavior in the runtime library, i.e. 7576 // if we don't pass any bits alloc/release that is what the runtime is 7577 // going to do. Therefore, we don't need to signal anything for these two 7578 // type modifiers. 7579 break; 7580 case OMPC_MAP_to: 7581 Bits |= OMP_MAP_TO; 7582 break; 7583 case OMPC_MAP_from: 7584 Bits |= OMP_MAP_FROM; 7585 break; 7586 case OMPC_MAP_tofrom: 7587 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7588 break; 7589 case OMPC_MAP_delete: 7590 Bits |= OMP_MAP_DELETE; 7591 break; 7592 case OMPC_MAP_unknown: 7593 llvm_unreachable("Unexpected map type!"); 7594 } 7595 if (AddPtrFlag) 7596 Bits |= OMP_MAP_PTR_AND_OBJ; 7597 if (AddIsTargetParamFlag) 7598 Bits |= OMP_MAP_TARGET_PARAM; 7599 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7600 != MapModifiers.end()) 7601 Bits |= OMP_MAP_ALWAYS; 7602 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7603 != MapModifiers.end()) 7604 Bits |= OMP_MAP_CLOSE; 7605 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_present) != 7606 MapModifiers.end() || 7607 llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present) != 7608 MotionModifiers.end()) 7609 Bits |= OMP_MAP_PRESENT; 7610 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold) != 7611 MapModifiers.end()) 7612 Bits |= OMP_MAP_OMPX_HOLD; 7613 if (IsNonContiguous) 7614 Bits |= OMP_MAP_NON_CONTIG; 7615 return Bits; 7616 } 7617 7618 /// Return true if the provided expression is a final array section. A 7619 /// final array section, is one whose length can't be proved to be one. 7620 bool isFinalArraySectionExpression(const Expr *E) const { 7621 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7622 7623 // It is not an array section and therefore not a unity-size one. 7624 if (!OASE) 7625 return false; 7626 7627 // An array section with no colon always refer to a single element. 7628 if (OASE->getColonLocFirst().isInvalid()) 7629 return false; 7630 7631 const Expr *Length = OASE->getLength(); 7632 7633 // If we don't have a length we have to check if the array has size 1 7634 // for this dimension. Also, we should always expect a length if the 7635 // base type is pointer. 7636 if (!Length) { 7637 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7638 OASE->getBase()->IgnoreParenImpCasts()) 7639 .getCanonicalType(); 7640 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7641 return ATy->getSize().getSExtValue() != 1; 7642 // If we don't have a constant dimension length, we have to consider 7643 // the current section as having any size, so it is not necessarily 7644 // unitary. If it happen to be unity size, that's user fault. 7645 return true; 7646 } 7647 7648 // Check if the length evaluates to 1. 7649 Expr::EvalResult Result; 7650 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7651 return true; // Can have more that size 1. 7652 7653 llvm::APSInt ConstLength = Result.Val.getInt(); 7654 return ConstLength.getSExtValue() != 1; 7655 } 7656 7657 /// Generate the base pointers, section pointers, sizes, map type bits, and 7658 /// user-defined mappers (all included in \a CombinedInfo) for the provided 7659 /// map type, map or motion modifiers, and expression components. 7660 /// \a IsFirstComponent should be set to true if the provided set of 7661 /// components is the first associated with a capture. 7662 void generateInfoForComponentList( 7663 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7664 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7665 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7666 MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct, 7667 bool IsFirstComponentList, bool IsImplicit, 7668 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false, 7669 const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr, 7670 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7671 OverlappedElements = llvm::None) const { 7672 // The following summarizes what has to be generated for each map and the 7673 // types below. The generated information is expressed in this order: 7674 // base pointer, section pointer, size, flags 7675 // (to add to the ones that come from the map type and modifier). 7676 // 7677 // double d; 7678 // int i[100]; 7679 // float *p; 7680 // 7681 // struct S1 { 7682 // int i; 7683 // float f[50]; 7684 // } 7685 // struct S2 { 7686 // int i; 7687 // float f[50]; 7688 // S1 s; 7689 // double *p; 7690 // struct S2 *ps; 7691 // int &ref; 7692 // } 7693 // S2 s; 7694 // S2 *ps; 7695 // 7696 // map(d) 7697 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7698 // 7699 // map(i) 7700 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7701 // 7702 // map(i[1:23]) 7703 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7704 // 7705 // map(p) 7706 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7707 // 7708 // map(p[1:24]) 7709 // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ 7710 // in unified shared memory mode or for local pointers 7711 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7712 // 7713 // map(s) 7714 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7715 // 7716 // map(s.i) 7717 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7718 // 7719 // map(s.s.f) 7720 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7721 // 7722 // map(s.p) 7723 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7724 // 7725 // map(to: s.p[:22]) 7726 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7727 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7728 // &(s.p), &(s.p[0]), 22*sizeof(double), 7729 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7730 // (*) alloc space for struct members, only this is a target parameter 7731 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7732 // optimizes this entry out, same in the examples below) 7733 // (***) map the pointee (map: to) 7734 // 7735 // map(to: s.ref) 7736 // &s, &(s.ref), sizeof(int*), TARGET_PARAM (*) 7737 // &s, &(s.ref), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7738 // (*) alloc space for struct members, only this is a target parameter 7739 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7740 // optimizes this entry out, same in the examples below) 7741 // (***) map the pointee (map: to) 7742 // 7743 // map(s.ps) 7744 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7745 // 7746 // map(from: s.ps->s.i) 7747 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7748 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7749 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7750 // 7751 // map(to: s.ps->ps) 7752 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7753 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7754 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7755 // 7756 // map(s.ps->ps->ps) 7757 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7758 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7759 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7760 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7761 // 7762 // map(to: s.ps->ps->s.f[:22]) 7763 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7764 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7765 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7766 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7767 // 7768 // map(ps) 7769 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7770 // 7771 // map(ps->i) 7772 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7773 // 7774 // map(ps->s.f) 7775 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7776 // 7777 // map(from: ps->p) 7778 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7779 // 7780 // map(to: ps->p[:22]) 7781 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7782 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7783 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7784 // 7785 // map(ps->ps) 7786 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7787 // 7788 // map(from: ps->ps->s.i) 7789 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7790 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7791 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7792 // 7793 // map(from: ps->ps->ps) 7794 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7795 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7796 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7797 // 7798 // map(ps->ps->ps->ps) 7799 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7800 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7801 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7802 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7803 // 7804 // map(to: ps->ps->ps->s.f[:22]) 7805 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7806 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7807 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7808 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7809 // 7810 // map(to: s.f[:22]) map(from: s.p[:33]) 7811 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7812 // sizeof(double*) (**), TARGET_PARAM 7813 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7814 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7815 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7816 // (*) allocate contiguous space needed to fit all mapped members even if 7817 // we allocate space for members not mapped (in this example, 7818 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7819 // them as well because they fall between &s.f[0] and &s.p) 7820 // 7821 // map(from: s.f[:22]) map(to: ps->p[:33]) 7822 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7823 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7824 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7825 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7826 // (*) the struct this entry pertains to is the 2nd element in the list of 7827 // arguments, hence MEMBER_OF(2) 7828 // 7829 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7830 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7831 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7832 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7833 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7834 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7835 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7836 // (*) the struct this entry pertains to is the 4th element in the list 7837 // of arguments, hence MEMBER_OF(4) 7838 7839 // Track if the map information being generated is the first for a capture. 7840 bool IsCaptureFirstInfo = IsFirstComponentList; 7841 // When the variable is on a declare target link or in a to clause with 7842 // unified memory, a reference is needed to hold the host/device address 7843 // of the variable. 7844 bool RequiresReference = false; 7845 7846 // Scan the components from the base to the complete expression. 7847 auto CI = Components.rbegin(); 7848 auto CE = Components.rend(); 7849 auto I = CI; 7850 7851 // Track if the map information being generated is the first for a list of 7852 // components. 7853 bool IsExpressionFirstInfo = true; 7854 bool FirstPointerInComplexData = false; 7855 Address BP = Address::invalid(); 7856 const Expr *AssocExpr = I->getAssociatedExpression(); 7857 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7858 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7859 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr); 7860 7861 if (isa<MemberExpr>(AssocExpr)) { 7862 // The base is the 'this' pointer. The content of the pointer is going 7863 // to be the base of the field being mapped. 7864 BP = CGF.LoadCXXThisAddress(); 7865 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7866 (OASE && 7867 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7868 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7869 } else if (OAShE && 7870 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) { 7871 BP = Address( 7872 CGF.EmitScalarExpr(OAShE->getBase()), 7873 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType())); 7874 } else { 7875 // The base is the reference to the variable. 7876 // BP = &Var. 7877 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7878 if (const auto *VD = 7879 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7880 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7881 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7882 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7883 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7884 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7885 RequiresReference = true; 7886 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7887 } 7888 } 7889 } 7890 7891 // If the variable is a pointer and is being dereferenced (i.e. is not 7892 // the last component), the base has to be the pointer itself, not its 7893 // reference. References are ignored for mapping purposes. 7894 QualType Ty = 7895 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7896 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7897 // No need to generate individual map information for the pointer, it 7898 // can be associated with the combined storage if shared memory mode is 7899 // active or the base declaration is not global variable. 7900 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration()); 7901 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 7902 !VD || VD->hasLocalStorage()) 7903 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7904 else 7905 FirstPointerInComplexData = true; 7906 ++I; 7907 } 7908 } 7909 7910 // Track whether a component of the list should be marked as MEMBER_OF some 7911 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7912 // in a component list should be marked as MEMBER_OF, all subsequent entries 7913 // do not belong to the base struct. E.g. 7914 // struct S2 s; 7915 // s.ps->ps->ps->f[:] 7916 // (1) (2) (3) (4) 7917 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7918 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7919 // is the pointee of ps(2) which is not member of struct s, so it should not 7920 // be marked as such (it is still PTR_AND_OBJ). 7921 // The variable is initialized to false so that PTR_AND_OBJ entries which 7922 // are not struct members are not considered (e.g. array of pointers to 7923 // data). 7924 bool ShouldBeMemberOf = false; 7925 7926 // Variable keeping track of whether or not we have encountered a component 7927 // in the component list which is a member expression. Useful when we have a 7928 // pointer or a final array section, in which case it is the previous 7929 // component in the list which tells us whether we have a member expression. 7930 // E.g. X.f[:] 7931 // While processing the final array section "[:]" it is "f" which tells us 7932 // whether we are dealing with a member of a declared struct. 7933 const MemberExpr *EncounteredME = nullptr; 7934 7935 // Track for the total number of dimension. Start from one for the dummy 7936 // dimension. 7937 uint64_t DimSize = 1; 7938 7939 bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous; 7940 bool IsPrevMemberReference = false; 7941 7942 for (; I != CE; ++I) { 7943 // If the current component is member of a struct (parent struct) mark it. 7944 if (!EncounteredME) { 7945 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7946 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7947 // as MEMBER_OF the parent struct. 7948 if (EncounteredME) { 7949 ShouldBeMemberOf = true; 7950 // Do not emit as complex pointer if this is actually not array-like 7951 // expression. 7952 if (FirstPointerInComplexData) { 7953 QualType Ty = std::prev(I) 7954 ->getAssociatedDeclaration() 7955 ->getType() 7956 .getNonReferenceType(); 7957 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7958 FirstPointerInComplexData = false; 7959 } 7960 } 7961 } 7962 7963 auto Next = std::next(I); 7964 7965 // We need to generate the addresses and sizes if this is the last 7966 // component, if the component is a pointer or if it is an array section 7967 // whose length can't be proved to be one. If this is a pointer, it 7968 // becomes the base address for the following components. 7969 7970 // A final array section, is one whose length can't be proved to be one. 7971 // If the map item is non-contiguous then we don't treat any array section 7972 // as final array section. 7973 bool IsFinalArraySection = 7974 !IsNonContiguous && 7975 isFinalArraySectionExpression(I->getAssociatedExpression()); 7976 7977 // If we have a declaration for the mapping use that, otherwise use 7978 // the base declaration of the map clause. 7979 const ValueDecl *MapDecl = (I->getAssociatedDeclaration()) 7980 ? I->getAssociatedDeclaration() 7981 : BaseDecl; 7982 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression() 7983 : MapExpr; 7984 7985 // Get information on whether the element is a pointer. Have to do a 7986 // special treatment for array sections given that they are built-in 7987 // types. 7988 const auto *OASE = 7989 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7990 const auto *OAShE = 7991 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression()); 7992 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 7993 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 7994 bool IsPointer = 7995 OAShE || 7996 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7997 .getCanonicalType() 7998 ->isAnyPointerType()) || 7999 I->getAssociatedExpression()->getType()->isAnyPointerType(); 8000 bool IsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) && 8001 MapDecl && 8002 MapDecl->getType()->isLValueReferenceType(); 8003 bool IsNonDerefPointer = IsPointer && !UO && !BO && !IsNonContiguous; 8004 8005 if (OASE) 8006 ++DimSize; 8007 8008 if (Next == CE || IsMemberReference || IsNonDerefPointer || 8009 IsFinalArraySection) { 8010 // If this is not the last component, we expect the pointer to be 8011 // associated with an array expression or member expression. 8012 assert((Next == CE || 8013 isa<MemberExpr>(Next->getAssociatedExpression()) || 8014 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 8015 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 8016 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || 8017 isa<UnaryOperator>(Next->getAssociatedExpression()) || 8018 isa<BinaryOperator>(Next->getAssociatedExpression())) && 8019 "Unexpected expression"); 8020 8021 Address LB = Address::invalid(); 8022 Address LowestElem = Address::invalid(); 8023 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF, 8024 const MemberExpr *E) { 8025 const Expr *BaseExpr = E->getBase(); 8026 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a 8027 // scalar. 8028 LValue BaseLV; 8029 if (E->isArrow()) { 8030 LValueBaseInfo BaseInfo; 8031 TBAAAccessInfo TBAAInfo; 8032 Address Addr = 8033 CGF.EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo); 8034 QualType PtrTy = BaseExpr->getType()->getPointeeType(); 8035 BaseLV = CGF.MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); 8036 } else { 8037 BaseLV = CGF.EmitOMPSharedLValue(BaseExpr); 8038 } 8039 return BaseLV; 8040 }; 8041 if (OAShE) { 8042 LowestElem = LB = Address(CGF.EmitScalarExpr(OAShE->getBase()), 8043 CGF.getContext().getTypeAlignInChars( 8044 OAShE->getBase()->getType())); 8045 } else if (IsMemberReference) { 8046 const auto *ME = cast<MemberExpr>(I->getAssociatedExpression()); 8047 LValue BaseLVal = EmitMemberExprBase(CGF, ME); 8048 LowestElem = CGF.EmitLValueForFieldInitialization( 8049 BaseLVal, cast<FieldDecl>(MapDecl)) 8050 .getAddress(CGF); 8051 LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType()) 8052 .getAddress(CGF); 8053 } else { 8054 LowestElem = LB = 8055 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 8056 .getAddress(CGF); 8057 } 8058 8059 // If this component is a pointer inside the base struct then we don't 8060 // need to create any entry for it - it will be combined with the object 8061 // it is pointing to into a single PTR_AND_OBJ entry. 8062 bool IsMemberPointerOrAddr = 8063 EncounteredME && 8064 (((IsPointer || ForDeviceAddr) && 8065 I->getAssociatedExpression() == EncounteredME) || 8066 (IsPrevMemberReference && !IsPointer) || 8067 (IsMemberReference && Next != CE && 8068 !Next->getAssociatedExpression()->getType()->isPointerType())); 8069 if (!OverlappedElements.empty() && Next == CE) { 8070 // Handle base element with the info for overlapped elements. 8071 assert(!PartialStruct.Base.isValid() && "The base element is set."); 8072 assert(!IsPointer && 8073 "Unexpected base element with the pointer type."); 8074 // Mark the whole struct as the struct that requires allocation on the 8075 // device. 8076 PartialStruct.LowestElem = {0, LowestElem}; 8077 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 8078 I->getAssociatedExpression()->getType()); 8079 Address HB = CGF.Builder.CreateConstGEP( 8080 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LowestElem, 8081 CGF.VoidPtrTy), 8082 TypeSize.getQuantity() - 1); 8083 PartialStruct.HighestElem = { 8084 std::numeric_limits<decltype( 8085 PartialStruct.HighestElem.first)>::max(), 8086 HB}; 8087 PartialStruct.Base = BP; 8088 PartialStruct.LB = LB; 8089 assert( 8090 PartialStruct.PreliminaryMapData.BasePointers.empty() && 8091 "Overlapped elements must be used only once for the variable."); 8092 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo); 8093 // Emit data for non-overlapped data. 8094 OpenMPOffloadMappingFlags Flags = 8095 OMP_MAP_MEMBER_OF | 8096 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, 8097 /*AddPtrFlag=*/false, 8098 /*AddIsTargetParamFlag=*/false, IsNonContiguous); 8099 llvm::Value *Size = nullptr; 8100 // Do bitcopy of all non-overlapped structure elements. 8101 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 8102 Component : OverlappedElements) { 8103 Address ComponentLB = Address::invalid(); 8104 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 8105 Component) { 8106 if (const ValueDecl *VD = MC.getAssociatedDeclaration()) { 8107 const auto *FD = dyn_cast<FieldDecl>(VD); 8108 if (FD && FD->getType()->isLValueReferenceType()) { 8109 const auto *ME = 8110 cast<MemberExpr>(MC.getAssociatedExpression()); 8111 LValue BaseLVal = EmitMemberExprBase(CGF, ME); 8112 ComponentLB = 8113 CGF.EmitLValueForFieldInitialization(BaseLVal, FD) 8114 .getAddress(CGF); 8115 } else { 8116 ComponentLB = 8117 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 8118 .getAddress(CGF); 8119 } 8120 Size = CGF.Builder.CreatePtrDiff( 8121 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 8122 CGF.EmitCastToVoidPtr(LB.getPointer())); 8123 break; 8124 } 8125 } 8126 assert(Size && "Failed to determine structure size"); 8127 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8128 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8129 CombinedInfo.Pointers.push_back(LB.getPointer()); 8130 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8131 Size, CGF.Int64Ty, /*isSigned=*/true)); 8132 CombinedInfo.Types.push_back(Flags); 8133 CombinedInfo.Mappers.push_back(nullptr); 8134 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8135 : 1); 8136 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 8137 } 8138 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8139 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8140 CombinedInfo.Pointers.push_back(LB.getPointer()); 8141 Size = CGF.Builder.CreatePtrDiff( 8142 CGF.Builder.CreateConstGEP(HB, 1).getPointer(), 8143 CGF.EmitCastToVoidPtr(LB.getPointer())); 8144 CombinedInfo.Sizes.push_back( 8145 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8146 CombinedInfo.Types.push_back(Flags); 8147 CombinedInfo.Mappers.push_back(nullptr); 8148 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8149 : 1); 8150 break; 8151 } 8152 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 8153 if (!IsMemberPointerOrAddr || 8154 (Next == CE && MapType != OMPC_MAP_unknown)) { 8155 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8156 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8157 CombinedInfo.Pointers.push_back(LB.getPointer()); 8158 CombinedInfo.Sizes.push_back( 8159 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8160 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8161 : 1); 8162 8163 // If Mapper is valid, the last component inherits the mapper. 8164 bool HasMapper = Mapper && Next == CE; 8165 CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr); 8166 8167 // We need to add a pointer flag for each map that comes from the 8168 // same expression except for the first one. We also need to signal 8169 // this map is the first one that relates with the current capture 8170 // (there is a set of entries for each capture). 8171 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 8172 MapType, MapModifiers, MotionModifiers, IsImplicit, 8173 !IsExpressionFirstInfo || RequiresReference || 8174 FirstPointerInComplexData || IsMemberReference, 8175 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous); 8176 8177 if (!IsExpressionFirstInfo || IsMemberReference) { 8178 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 8179 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 8180 if (IsPointer || (IsMemberReference && Next != CE)) 8181 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 8182 OMP_MAP_DELETE | OMP_MAP_CLOSE); 8183 8184 if (ShouldBeMemberOf) { 8185 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 8186 // should be later updated with the correct value of MEMBER_OF. 8187 Flags |= OMP_MAP_MEMBER_OF; 8188 // From now on, all subsequent PTR_AND_OBJ entries should not be 8189 // marked as MEMBER_OF. 8190 ShouldBeMemberOf = false; 8191 } 8192 } 8193 8194 CombinedInfo.Types.push_back(Flags); 8195 } 8196 8197 // If we have encountered a member expression so far, keep track of the 8198 // mapped member. If the parent is "*this", then the value declaration 8199 // is nullptr. 8200 if (EncounteredME) { 8201 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 8202 unsigned FieldIndex = FD->getFieldIndex(); 8203 8204 // Update info about the lowest and highest elements for this struct 8205 if (!PartialStruct.Base.isValid()) { 8206 PartialStruct.LowestElem = {FieldIndex, LowestElem}; 8207 if (IsFinalArraySection) { 8208 Address HB = 8209 CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false) 8210 .getAddress(CGF); 8211 PartialStruct.HighestElem = {FieldIndex, HB}; 8212 } else { 8213 PartialStruct.HighestElem = {FieldIndex, LowestElem}; 8214 } 8215 PartialStruct.Base = BP; 8216 PartialStruct.LB = BP; 8217 } else if (FieldIndex < PartialStruct.LowestElem.first) { 8218 PartialStruct.LowestElem = {FieldIndex, LowestElem}; 8219 } else if (FieldIndex > PartialStruct.HighestElem.first) { 8220 PartialStruct.HighestElem = {FieldIndex, LowestElem}; 8221 } 8222 } 8223 8224 // Need to emit combined struct for array sections. 8225 if (IsFinalArraySection || IsNonContiguous) 8226 PartialStruct.IsArraySection = true; 8227 8228 // If we have a final array section, we are done with this expression. 8229 if (IsFinalArraySection) 8230 break; 8231 8232 // The pointer becomes the base for the next element. 8233 if (Next != CE) 8234 BP = IsMemberReference ? LowestElem : LB; 8235 8236 IsExpressionFirstInfo = false; 8237 IsCaptureFirstInfo = false; 8238 FirstPointerInComplexData = false; 8239 IsPrevMemberReference = IsMemberReference; 8240 } else if (FirstPointerInComplexData) { 8241 QualType Ty = Components.rbegin() 8242 ->getAssociatedDeclaration() 8243 ->getType() 8244 .getNonReferenceType(); 8245 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 8246 FirstPointerInComplexData = false; 8247 } 8248 } 8249 // If ran into the whole component - allocate the space for the whole 8250 // record. 8251 if (!EncounteredME) 8252 PartialStruct.HasCompleteRecord = true; 8253 8254 if (!IsNonContiguous) 8255 return; 8256 8257 const ASTContext &Context = CGF.getContext(); 8258 8259 // For supporting stride in array section, we need to initialize the first 8260 // dimension size as 1, first offset as 0, and first count as 1 8261 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 0)}; 8262 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 8263 MapValuesArrayTy CurStrides; 8264 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 8265 uint64_t ElementTypeSize; 8266 8267 // Collect Size information for each dimension and get the element size as 8268 // the first Stride. For example, for `int arr[10][10]`, the DimSizes 8269 // should be [10, 10] and the first stride is 4 btyes. 8270 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 8271 Components) { 8272 const Expr *AssocExpr = Component.getAssociatedExpression(); 8273 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8274 8275 if (!OASE) 8276 continue; 8277 8278 QualType Ty = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase()); 8279 auto *CAT = Context.getAsConstantArrayType(Ty); 8280 auto *VAT = Context.getAsVariableArrayType(Ty); 8281 8282 // We need all the dimension size except for the last dimension. 8283 assert((VAT || CAT || &Component == &*Components.begin()) && 8284 "Should be either ConstantArray or VariableArray if not the " 8285 "first Component"); 8286 8287 // Get element size if CurStrides is empty. 8288 if (CurStrides.empty()) { 8289 const Type *ElementType = nullptr; 8290 if (CAT) 8291 ElementType = CAT->getElementType().getTypePtr(); 8292 else if (VAT) 8293 ElementType = VAT->getElementType().getTypePtr(); 8294 else 8295 assert(&Component == &*Components.begin() && 8296 "Only expect pointer (non CAT or VAT) when this is the " 8297 "first Component"); 8298 // If ElementType is null, then it means the base is a pointer 8299 // (neither CAT nor VAT) and we'll attempt to get ElementType again 8300 // for next iteration. 8301 if (ElementType) { 8302 // For the case that having pointer as base, we need to remove one 8303 // level of indirection. 8304 if (&Component != &*Components.begin()) 8305 ElementType = ElementType->getPointeeOrArrayElementType(); 8306 ElementTypeSize = 8307 Context.getTypeSizeInChars(ElementType).getQuantity(); 8308 CurStrides.push_back( 8309 llvm::ConstantInt::get(CGF.Int64Ty, ElementTypeSize)); 8310 } 8311 } 8312 // Get dimension value except for the last dimension since we don't need 8313 // it. 8314 if (DimSizes.size() < Components.size() - 1) { 8315 if (CAT) 8316 DimSizes.push_back(llvm::ConstantInt::get( 8317 CGF.Int64Ty, CAT->getSize().getZExtValue())); 8318 else if (VAT) 8319 DimSizes.push_back(CGF.Builder.CreateIntCast( 8320 CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty, 8321 /*IsSigned=*/false)); 8322 } 8323 } 8324 8325 // Skip the dummy dimension since we have already have its information. 8326 auto DI = DimSizes.begin() + 1; 8327 // Product of dimension. 8328 llvm::Value *DimProd = 8329 llvm::ConstantInt::get(CGF.CGM.Int64Ty, ElementTypeSize); 8330 8331 // Collect info for non-contiguous. Notice that offset, count, and stride 8332 // are only meaningful for array-section, so we insert a null for anything 8333 // other than array-section. 8334 // Also, the size of offset, count, and stride are not the same as 8335 // pointers, base_pointers, sizes, or dims. Instead, the size of offset, 8336 // count, and stride are the same as the number of non-contiguous 8337 // declaration in target update to/from clause. 8338 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 8339 Components) { 8340 const Expr *AssocExpr = Component.getAssociatedExpression(); 8341 8342 if (const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) { 8343 llvm::Value *Offset = CGF.Builder.CreateIntCast( 8344 CGF.EmitScalarExpr(AE->getIdx()), CGF.Int64Ty, 8345 /*isSigned=*/false); 8346 CurOffsets.push_back(Offset); 8347 CurCounts.push_back(llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/1)); 8348 CurStrides.push_back(CurStrides.back()); 8349 continue; 8350 } 8351 8352 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8353 8354 if (!OASE) 8355 continue; 8356 8357 // Offset 8358 const Expr *OffsetExpr = OASE->getLowerBound(); 8359 llvm::Value *Offset = nullptr; 8360 if (!OffsetExpr) { 8361 // If offset is absent, then we just set it to zero. 8362 Offset = llvm::ConstantInt::get(CGF.Int64Ty, 0); 8363 } else { 8364 Offset = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(OffsetExpr), 8365 CGF.Int64Ty, 8366 /*isSigned=*/false); 8367 } 8368 CurOffsets.push_back(Offset); 8369 8370 // Count 8371 const Expr *CountExpr = OASE->getLength(); 8372 llvm::Value *Count = nullptr; 8373 if (!CountExpr) { 8374 // In Clang, once a high dimension is an array section, we construct all 8375 // the lower dimension as array section, however, for case like 8376 // arr[0:2][2], Clang construct the inner dimension as an array section 8377 // but it actually is not in an array section form according to spec. 8378 if (!OASE->getColonLocFirst().isValid() && 8379 !OASE->getColonLocSecond().isValid()) { 8380 Count = llvm::ConstantInt::get(CGF.Int64Ty, 1); 8381 } else { 8382 // OpenMP 5.0, 2.1.5 Array Sections, Description. 8383 // When the length is absent it defaults to ⌈(size − 8384 // lower-bound)/stride⌉, where size is the size of the array 8385 // dimension. 8386 const Expr *StrideExpr = OASE->getStride(); 8387 llvm::Value *Stride = 8388 StrideExpr 8389 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8390 CGF.Int64Ty, /*isSigned=*/false) 8391 : nullptr; 8392 if (Stride) 8393 Count = CGF.Builder.CreateUDiv( 8394 CGF.Builder.CreateNUWSub(*DI, Offset), Stride); 8395 else 8396 Count = CGF.Builder.CreateNUWSub(*DI, Offset); 8397 } 8398 } else { 8399 Count = CGF.EmitScalarExpr(CountExpr); 8400 } 8401 Count = CGF.Builder.CreateIntCast(Count, CGF.Int64Ty, /*isSigned=*/false); 8402 CurCounts.push_back(Count); 8403 8404 // Stride_n' = Stride_n * (D_0 * D_1 ... * D_n-1) * Unit size 8405 // Take `int arr[5][5][5]` and `arr[0:2:2][1:2:1][0:2:2]` as an example: 8406 // Offset Count Stride 8407 // D0 0 1 4 (int) <- dummy dimension 8408 // D1 0 2 8 (2 * (1) * 4) 8409 // D2 1 2 20 (1 * (1 * 5) * 4) 8410 // D3 0 2 200 (2 * (1 * 5 * 4) * 4) 8411 const Expr *StrideExpr = OASE->getStride(); 8412 llvm::Value *Stride = 8413 StrideExpr 8414 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8415 CGF.Int64Ty, /*isSigned=*/false) 8416 : nullptr; 8417 DimProd = CGF.Builder.CreateNUWMul(DimProd, *(DI - 1)); 8418 if (Stride) 8419 CurStrides.push_back(CGF.Builder.CreateNUWMul(DimProd, Stride)); 8420 else 8421 CurStrides.push_back(DimProd); 8422 if (DI != DimSizes.end()) 8423 ++DI; 8424 } 8425 8426 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets); 8427 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts); 8428 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides); 8429 } 8430 8431 /// Return the adjusted map modifiers if the declaration a capture refers to 8432 /// appears in a first-private clause. This is expected to be used only with 8433 /// directives that start with 'target'. 8434 MappableExprsHandler::OpenMPOffloadMappingFlags 8435 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 8436 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 8437 8438 // A first private variable captured by reference will use only the 8439 // 'private ptr' and 'map to' flag. Return the right flags if the captured 8440 // declaration is known as first-private in this handler. 8441 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 8442 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 8443 return MappableExprsHandler::OMP_MAP_TO | 8444 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 8445 return MappableExprsHandler::OMP_MAP_PRIVATE | 8446 MappableExprsHandler::OMP_MAP_TO; 8447 } 8448 auto I = LambdasMap.find(Cap.getCapturedVar()->getCanonicalDecl()); 8449 if (I != LambdasMap.end()) 8450 // for map(to: lambda): using user specified map type. 8451 return getMapTypeBits( 8452 I->getSecond()->getMapType(), I->getSecond()->getMapTypeModifiers(), 8453 /*MotionModifiers=*/llvm::None, I->getSecond()->isImplicit(), 8454 /*AddPtrFlag=*/false, 8455 /*AddIsTargetParamFlag=*/false, 8456 /*isNonContiguous=*/false); 8457 return MappableExprsHandler::OMP_MAP_TO | 8458 MappableExprsHandler::OMP_MAP_FROM; 8459 } 8460 8461 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 8462 // Rotate by getFlagMemberOffset() bits. 8463 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 8464 << getFlagMemberOffset()); 8465 } 8466 8467 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 8468 OpenMPOffloadMappingFlags MemberOfFlag) { 8469 // If the entry is PTR_AND_OBJ but has not been marked with the special 8470 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 8471 // marked as MEMBER_OF. 8472 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 8473 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 8474 return; 8475 8476 // Reset the placeholder value to prepare the flag for the assignment of the 8477 // proper MEMBER_OF value. 8478 Flags &= ~OMP_MAP_MEMBER_OF; 8479 Flags |= MemberOfFlag; 8480 } 8481 8482 void getPlainLayout(const CXXRecordDecl *RD, 8483 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 8484 bool AsBase) const { 8485 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 8486 8487 llvm::StructType *St = 8488 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 8489 8490 unsigned NumElements = St->getNumElements(); 8491 llvm::SmallVector< 8492 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 8493 RecordLayout(NumElements); 8494 8495 // Fill bases. 8496 for (const auto &I : RD->bases()) { 8497 if (I.isVirtual()) 8498 continue; 8499 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8500 // Ignore empty bases. 8501 if (Base->isEmpty() || CGF.getContext() 8502 .getASTRecordLayout(Base) 8503 .getNonVirtualSize() 8504 .isZero()) 8505 continue; 8506 8507 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 8508 RecordLayout[FieldIndex] = Base; 8509 } 8510 // Fill in virtual bases. 8511 for (const auto &I : RD->vbases()) { 8512 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8513 // Ignore empty bases. 8514 if (Base->isEmpty()) 8515 continue; 8516 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 8517 if (RecordLayout[FieldIndex]) 8518 continue; 8519 RecordLayout[FieldIndex] = Base; 8520 } 8521 // Fill in all the fields. 8522 assert(!RD->isUnion() && "Unexpected union."); 8523 for (const auto *Field : RD->fields()) { 8524 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 8525 // will fill in later.) 8526 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 8527 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 8528 RecordLayout[FieldIndex] = Field; 8529 } 8530 } 8531 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 8532 &Data : RecordLayout) { 8533 if (Data.isNull()) 8534 continue; 8535 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 8536 getPlainLayout(Base, Layout, /*AsBase=*/true); 8537 else 8538 Layout.push_back(Data.get<const FieldDecl *>()); 8539 } 8540 } 8541 8542 /// Generate all the base pointers, section pointers, sizes, map types, and 8543 /// mappers for the extracted mappable expressions (all included in \a 8544 /// CombinedInfo). Also, for each item that relates with a device pointer, a 8545 /// pair of the relevant declaration and index where it occurs is appended to 8546 /// the device pointers info array. 8547 void generateAllInfoForClauses( 8548 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo, 8549 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 8550 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 8551 // We have to process the component lists that relate with the same 8552 // declaration in a single chunk so that we can generate the map flags 8553 // correctly. Therefore, we organize all lists in a map. 8554 enum MapKind { Present, Allocs, Other, Total }; 8555 llvm::MapVector<CanonicalDeclPtr<const Decl>, 8556 SmallVector<SmallVector<MapInfo, 8>, 4>> 8557 Info; 8558 8559 // Helper function to fill the information map for the different supported 8560 // clauses. 8561 auto &&InfoGen = 8562 [&Info, &SkipVarSet]( 8563 const ValueDecl *D, MapKind Kind, 8564 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8565 OpenMPMapClauseKind MapType, 8566 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8567 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 8568 bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper, 8569 const Expr *VarRef = nullptr, bool ForDeviceAddr = false) { 8570 if (SkipVarSet.contains(D)) 8571 return; 8572 auto It = Info.find(D); 8573 if (It == Info.end()) 8574 It = Info 8575 .insert(std::make_pair( 8576 D, SmallVector<SmallVector<MapInfo, 8>, 4>(Total))) 8577 .first; 8578 It->second[Kind].emplace_back( 8579 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer, 8580 IsImplicit, Mapper, VarRef, ForDeviceAddr); 8581 }; 8582 8583 for (const auto *Cl : Clauses) { 8584 const auto *C = dyn_cast<OMPMapClause>(Cl); 8585 if (!C) 8586 continue; 8587 MapKind Kind = Other; 8588 if (!C->getMapTypeModifiers().empty() && 8589 llvm::any_of(C->getMapTypeModifiers(), [](OpenMPMapModifierKind K) { 8590 return K == OMPC_MAP_MODIFIER_present; 8591 })) 8592 Kind = Present; 8593 else if (C->getMapType() == OMPC_MAP_alloc) 8594 Kind = Allocs; 8595 const auto *EI = C->getVarRefs().begin(); 8596 for (const auto L : C->component_lists()) { 8597 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 8598 InfoGen(std::get<0>(L), Kind, std::get<1>(L), C->getMapType(), 8599 C->getMapTypeModifiers(), llvm::None, 8600 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L), 8601 E); 8602 ++EI; 8603 } 8604 } 8605 for (const auto *Cl : Clauses) { 8606 const auto *C = dyn_cast<OMPToClause>(Cl); 8607 if (!C) 8608 continue; 8609 MapKind Kind = Other; 8610 if (!C->getMotionModifiers().empty() && 8611 llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) { 8612 return K == OMPC_MOTION_MODIFIER_present; 8613 })) 8614 Kind = Present; 8615 const auto *EI = C->getVarRefs().begin(); 8616 for (const auto L : C->component_lists()) { 8617 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, llvm::None, 8618 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8619 C->isImplicit(), std::get<2>(L), *EI); 8620 ++EI; 8621 } 8622 } 8623 for (const auto *Cl : Clauses) { 8624 const auto *C = dyn_cast<OMPFromClause>(Cl); 8625 if (!C) 8626 continue; 8627 MapKind Kind = Other; 8628 if (!C->getMotionModifiers().empty() && 8629 llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) { 8630 return K == OMPC_MOTION_MODIFIER_present; 8631 })) 8632 Kind = Present; 8633 const auto *EI = C->getVarRefs().begin(); 8634 for (const auto L : C->component_lists()) { 8635 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, llvm::None, 8636 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8637 C->isImplicit(), std::get<2>(L), *EI); 8638 ++EI; 8639 } 8640 } 8641 8642 // Look at the use_device_ptr clause information and mark the existing map 8643 // entries as such. If there is no map information for an entry in the 8644 // use_device_ptr list, we create one with map type 'alloc' and zero size 8645 // section. It is the user fault if that was not mapped before. If there is 8646 // no map information and the pointer is a struct member, then we defer the 8647 // emission of that entry until the whole struct has been processed. 8648 llvm::MapVector<CanonicalDeclPtr<const Decl>, 8649 SmallVector<DeferredDevicePtrEntryTy, 4>> 8650 DeferredInfo; 8651 MapCombinedInfoTy UseDevicePtrCombinedInfo; 8652 8653 for (const auto *Cl : Clauses) { 8654 const auto *C = dyn_cast<OMPUseDevicePtrClause>(Cl); 8655 if (!C) 8656 continue; 8657 for (const auto L : C->component_lists()) { 8658 OMPClauseMappableExprCommon::MappableExprComponentListRef Components = 8659 std::get<1>(L); 8660 assert(!Components.empty() && 8661 "Not expecting empty list of components!"); 8662 const ValueDecl *VD = Components.back().getAssociatedDeclaration(); 8663 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8664 const Expr *IE = Components.back().getAssociatedExpression(); 8665 // If the first component is a member expression, we have to look into 8666 // 'this', which maps to null in the map of map information. Otherwise 8667 // look directly for the information. 8668 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8669 8670 // We potentially have map information for this declaration already. 8671 // Look for the first set of components that refer to it. 8672 if (It != Info.end()) { 8673 bool Found = false; 8674 for (auto &Data : It->second) { 8675 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) { 8676 return MI.Components.back().getAssociatedDeclaration() == VD; 8677 }); 8678 // If we found a map entry, signal that the pointer has to be 8679 // returned and move on to the next declaration. Exclude cases where 8680 // the base pointer is mapped as array subscript, array section or 8681 // array shaping. The base address is passed as a pointer to base in 8682 // this case and cannot be used as a base for use_device_ptr list 8683 // item. 8684 if (CI != Data.end()) { 8685 auto PrevCI = std::next(CI->Components.rbegin()); 8686 const auto *VarD = dyn_cast<VarDecl>(VD); 8687 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8688 isa<MemberExpr>(IE) || 8689 !VD->getType().getNonReferenceType()->isPointerType() || 8690 PrevCI == CI->Components.rend() || 8691 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD || 8692 VarD->hasLocalStorage()) { 8693 CI->ReturnDevicePointer = true; 8694 Found = true; 8695 break; 8696 } 8697 } 8698 } 8699 if (Found) 8700 continue; 8701 } 8702 8703 // We didn't find any match in our map information - generate a zero 8704 // size array section - if the pointer is a struct member we defer this 8705 // action until the whole struct has been processed. 8706 if (isa<MemberExpr>(IE)) { 8707 // Insert the pointer into Info to be processed by 8708 // generateInfoForComponentList. Because it is a member pointer 8709 // without a pointee, no entry will be generated for it, therefore 8710 // we need to generate one after the whole struct has been processed. 8711 // Nonetheless, generateInfoForComponentList must be called to take 8712 // the pointer into account for the calculation of the range of the 8713 // partial struct. 8714 InfoGen(nullptr, Other, Components, OMPC_MAP_unknown, llvm::None, 8715 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8716 nullptr); 8717 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false); 8718 } else { 8719 llvm::Value *Ptr = 8720 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8721 UseDevicePtrCombinedInfo.Exprs.push_back(VD); 8722 UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD); 8723 UseDevicePtrCombinedInfo.Pointers.push_back(Ptr); 8724 UseDevicePtrCombinedInfo.Sizes.push_back( 8725 llvm::Constant::getNullValue(CGF.Int64Ty)); 8726 UseDevicePtrCombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM); 8727 UseDevicePtrCombinedInfo.Mappers.push_back(nullptr); 8728 } 8729 } 8730 } 8731 8732 // Look at the use_device_addr clause information and mark the existing map 8733 // entries as such. If there is no map information for an entry in the 8734 // use_device_addr list, we create one with map type 'alloc' and zero size 8735 // section. It is the user fault if that was not mapped before. If there is 8736 // no map information and the pointer is a struct member, then we defer the 8737 // emission of that entry until the whole struct has been processed. 8738 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed; 8739 for (const auto *Cl : Clauses) { 8740 const auto *C = dyn_cast<OMPUseDeviceAddrClause>(Cl); 8741 if (!C) 8742 continue; 8743 for (const auto L : C->component_lists()) { 8744 assert(!std::get<1>(L).empty() && 8745 "Not expecting empty list of components!"); 8746 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration(); 8747 if (!Processed.insert(VD).second) 8748 continue; 8749 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8750 const Expr *IE = std::get<1>(L).back().getAssociatedExpression(); 8751 // If the first component is a member expression, we have to look into 8752 // 'this', which maps to null in the map of map information. Otherwise 8753 // look directly for the information. 8754 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8755 8756 // We potentially have map information for this declaration already. 8757 // Look for the first set of components that refer to it. 8758 if (It != Info.end()) { 8759 bool Found = false; 8760 for (auto &Data : It->second) { 8761 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) { 8762 return MI.Components.back().getAssociatedDeclaration() == VD; 8763 }); 8764 // If we found a map entry, signal that the pointer has to be 8765 // returned and move on to the next declaration. 8766 if (CI != Data.end()) { 8767 CI->ReturnDevicePointer = true; 8768 Found = true; 8769 break; 8770 } 8771 } 8772 if (Found) 8773 continue; 8774 } 8775 8776 // We didn't find any match in our map information - generate a zero 8777 // size array section - if the pointer is a struct member we defer this 8778 // action until the whole struct has been processed. 8779 if (isa<MemberExpr>(IE)) { 8780 // Insert the pointer into Info to be processed by 8781 // generateInfoForComponentList. Because it is a member pointer 8782 // without a pointee, no entry will be generated for it, therefore 8783 // we need to generate one after the whole struct has been processed. 8784 // Nonetheless, generateInfoForComponentList must be called to take 8785 // the pointer into account for the calculation of the range of the 8786 // partial struct. 8787 InfoGen(nullptr, Other, std::get<1>(L), OMPC_MAP_unknown, llvm::None, 8788 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8789 nullptr, nullptr, /*ForDeviceAddr=*/true); 8790 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true); 8791 } else { 8792 llvm::Value *Ptr; 8793 if (IE->isGLValue()) 8794 Ptr = CGF.EmitLValue(IE).getPointer(CGF); 8795 else 8796 Ptr = CGF.EmitScalarExpr(IE); 8797 CombinedInfo.Exprs.push_back(VD); 8798 CombinedInfo.BasePointers.emplace_back(Ptr, VD); 8799 CombinedInfo.Pointers.push_back(Ptr); 8800 CombinedInfo.Sizes.push_back( 8801 llvm::Constant::getNullValue(CGF.Int64Ty)); 8802 CombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM); 8803 CombinedInfo.Mappers.push_back(nullptr); 8804 } 8805 } 8806 } 8807 8808 for (const auto &Data : Info) { 8809 StructRangeInfoTy PartialStruct; 8810 // Temporary generated information. 8811 MapCombinedInfoTy CurInfo; 8812 const Decl *D = Data.first; 8813 const ValueDecl *VD = cast_or_null<ValueDecl>(D); 8814 for (const auto &M : Data.second) { 8815 for (const MapInfo &L : M) { 8816 assert(!L.Components.empty() && 8817 "Not expecting declaration with no component lists."); 8818 8819 // Remember the current base pointer index. 8820 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size(); 8821 CurInfo.NonContigInfo.IsNonContiguous = 8822 L.Components.back().isNonContiguous(); 8823 generateInfoForComponentList( 8824 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components, 8825 CurInfo, PartialStruct, /*IsFirstComponentList=*/false, 8826 L.IsImplicit, L.Mapper, L.ForDeviceAddr, VD, L.VarRef); 8827 8828 // If this entry relates with a device pointer, set the relevant 8829 // declaration and add the 'return pointer' flag. 8830 if (L.ReturnDevicePointer) { 8831 assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx && 8832 "Unexpected number of mapped base pointers."); 8833 8834 const ValueDecl *RelevantVD = 8835 L.Components.back().getAssociatedDeclaration(); 8836 assert(RelevantVD && 8837 "No relevant declaration related with device pointer??"); 8838 8839 CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl( 8840 RelevantVD); 8841 CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8842 } 8843 } 8844 } 8845 8846 // Append any pending zero-length pointers which are struct members and 8847 // used with use_device_ptr or use_device_addr. 8848 auto CI = DeferredInfo.find(Data.first); 8849 if (CI != DeferredInfo.end()) { 8850 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8851 llvm::Value *BasePtr; 8852 llvm::Value *Ptr; 8853 if (L.ForDeviceAddr) { 8854 if (L.IE->isGLValue()) 8855 Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8856 else 8857 Ptr = this->CGF.EmitScalarExpr(L.IE); 8858 BasePtr = Ptr; 8859 // Entry is RETURN_PARAM. Also, set the placeholder value 8860 // MEMBER_OF=FFFF so that the entry is later updated with the 8861 // correct value of MEMBER_OF. 8862 CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF); 8863 } else { 8864 BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8865 Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE), 8866 L.IE->getExprLoc()); 8867 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the 8868 // placeholder value MEMBER_OF=FFFF so that the entry is later 8869 // updated with the correct value of MEMBER_OF. 8870 CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8871 OMP_MAP_MEMBER_OF); 8872 } 8873 CurInfo.Exprs.push_back(L.VD); 8874 CurInfo.BasePointers.emplace_back(BasePtr, L.VD); 8875 CurInfo.Pointers.push_back(Ptr); 8876 CurInfo.Sizes.push_back( 8877 llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8878 CurInfo.Mappers.push_back(nullptr); 8879 } 8880 } 8881 // If there is an entry in PartialStruct it means we have a struct with 8882 // individual members mapped. Emit an extra combined entry. 8883 if (PartialStruct.Base.isValid()) { 8884 CurInfo.NonContigInfo.Dims.push_back(0); 8885 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD); 8886 } 8887 8888 // We need to append the results of this capture to what we already 8889 // have. 8890 CombinedInfo.append(CurInfo); 8891 } 8892 // Append data for use_device_ptr clauses. 8893 CombinedInfo.append(UseDevicePtrCombinedInfo); 8894 } 8895 8896 public: 8897 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 8898 : CurDir(&Dir), CGF(CGF) { 8899 // Extract firstprivate clause information. 8900 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 8901 for (const auto *D : C->varlists()) 8902 FirstPrivateDecls.try_emplace( 8903 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 8904 // Extract implicit firstprivates from uses_allocators clauses. 8905 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) { 8906 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 8907 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 8908 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits)) 8909 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()), 8910 /*Implicit=*/true); 8911 else if (const auto *VD = dyn_cast<VarDecl>( 8912 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts()) 8913 ->getDecl())) 8914 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true); 8915 } 8916 } 8917 // Extract device pointer clause information. 8918 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 8919 for (auto L : C->component_lists()) 8920 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L)); 8921 // Extract map information. 8922 for (const auto *C : Dir.getClausesOfKind<OMPMapClause>()) { 8923 if (C->getMapType() != OMPC_MAP_to) 8924 continue; 8925 for (auto L : C->component_lists()) { 8926 const ValueDecl *VD = std::get<0>(L); 8927 const auto *RD = VD ? VD->getType() 8928 .getCanonicalType() 8929 .getNonReferenceType() 8930 ->getAsCXXRecordDecl() 8931 : nullptr; 8932 if (RD && RD->isLambda()) 8933 LambdasMap.try_emplace(std::get<0>(L), C); 8934 } 8935 } 8936 } 8937 8938 /// Constructor for the declare mapper directive. 8939 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 8940 : CurDir(&Dir), CGF(CGF) {} 8941 8942 /// Generate code for the combined entry if we have a partially mapped struct 8943 /// and take care of the mapping flags of the arguments corresponding to 8944 /// individual struct members. 8945 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo, 8946 MapFlagsArrayTy &CurTypes, 8947 const StructRangeInfoTy &PartialStruct, 8948 const ValueDecl *VD = nullptr, 8949 bool NotTargetParams = true) const { 8950 if (CurTypes.size() == 1 && 8951 ((CurTypes.back() & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF) && 8952 !PartialStruct.IsArraySection) 8953 return; 8954 Address LBAddr = PartialStruct.LowestElem.second; 8955 Address HBAddr = PartialStruct.HighestElem.second; 8956 if (PartialStruct.HasCompleteRecord) { 8957 LBAddr = PartialStruct.LB; 8958 HBAddr = PartialStruct.LB; 8959 } 8960 CombinedInfo.Exprs.push_back(VD); 8961 // Base is the base of the struct 8962 CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); 8963 // Pointer is the address of the lowest element 8964 llvm::Value *LB = LBAddr.getPointer(); 8965 CombinedInfo.Pointers.push_back(LB); 8966 // There should not be a mapper for a combined entry. 8967 CombinedInfo.Mappers.push_back(nullptr); 8968 // Size is (addr of {highest+1} element) - (addr of lowest element) 8969 llvm::Value *HB = HBAddr.getPointer(); 8970 llvm::Value *HAddr = 8971 CGF.Builder.CreateConstGEP1_32(HBAddr.getElementType(), HB, /*Idx0=*/1); 8972 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 8973 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 8974 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 8975 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 8976 /*isSigned=*/false); 8977 CombinedInfo.Sizes.push_back(Size); 8978 // Map type is always TARGET_PARAM, if generate info for captures. 8979 CombinedInfo.Types.push_back(NotTargetParams ? OMP_MAP_NONE 8980 : OMP_MAP_TARGET_PARAM); 8981 // If any element has the present modifier, then make sure the runtime 8982 // doesn't attempt to allocate the struct. 8983 if (CurTypes.end() != 8984 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) { 8985 return Type & OMP_MAP_PRESENT; 8986 })) 8987 CombinedInfo.Types.back() |= OMP_MAP_PRESENT; 8988 // Remove TARGET_PARAM flag from the first element 8989 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 8990 // If any element has the ompx_hold modifier, then make sure the runtime 8991 // uses the hold reference count for the struct as a whole so that it won't 8992 // be unmapped by an extra dynamic reference count decrement. Add it to all 8993 // elements as well so the runtime knows which reference count to check 8994 // when determining whether it's time for device-to-host transfers of 8995 // individual elements. 8996 if (CurTypes.end() != 8997 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) { 8998 return Type & OMP_MAP_OMPX_HOLD; 8999 })) { 9000 CombinedInfo.Types.back() |= OMP_MAP_OMPX_HOLD; 9001 for (auto &M : CurTypes) 9002 M |= OMP_MAP_OMPX_HOLD; 9003 } 9004 9005 // All other current entries will be MEMBER_OF the combined entry 9006 // (except for PTR_AND_OBJ entries which do not have a placeholder value 9007 // 0xFFFF in the MEMBER_OF field). 9008 OpenMPOffloadMappingFlags MemberOfFlag = 9009 getMemberOfFlag(CombinedInfo.BasePointers.size() - 1); 9010 for (auto &M : CurTypes) 9011 setCorrectMemberOfFlag(M, MemberOfFlag); 9012 } 9013 9014 /// Generate all the base pointers, section pointers, sizes, map types, and 9015 /// mappers for the extracted mappable expressions (all included in \a 9016 /// CombinedInfo). Also, for each item that relates with a device pointer, a 9017 /// pair of the relevant declaration and index where it occurs is appended to 9018 /// the device pointers info array. 9019 void generateAllInfo( 9020 MapCombinedInfoTy &CombinedInfo, 9021 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 9022 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 9023 assert(CurDir.is<const OMPExecutableDirective *>() && 9024 "Expect a executable directive"); 9025 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 9026 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, SkipVarSet); 9027 } 9028 9029 /// Generate all the base pointers, section pointers, sizes, map types, and 9030 /// mappers for the extracted map clauses of user-defined mapper (all included 9031 /// in \a CombinedInfo). 9032 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const { 9033 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 9034 "Expect a declare mapper directive"); 9035 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 9036 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo); 9037 } 9038 9039 /// Emit capture info for lambdas for variables captured by reference. 9040 void generateInfoForLambdaCaptures( 9041 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 9042 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 9043 const auto *RD = VD->getType() 9044 .getCanonicalType() 9045 .getNonReferenceType() 9046 ->getAsCXXRecordDecl(); 9047 if (!RD || !RD->isLambda()) 9048 return; 9049 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 9050 LValue VDLVal = CGF.MakeAddrLValue( 9051 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 9052 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 9053 FieldDecl *ThisCapture = nullptr; 9054 RD->getCaptureFields(Captures, ThisCapture); 9055 if (ThisCapture) { 9056 LValue ThisLVal = 9057 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 9058 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 9059 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 9060 VDLVal.getPointer(CGF)); 9061 CombinedInfo.Exprs.push_back(VD); 9062 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF)); 9063 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF)); 9064 CombinedInfo.Sizes.push_back( 9065 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 9066 CGF.Int64Ty, /*isSigned=*/true)); 9067 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9068 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 9069 CombinedInfo.Mappers.push_back(nullptr); 9070 } 9071 for (const LambdaCapture &LC : RD->captures()) { 9072 if (!LC.capturesVariable()) 9073 continue; 9074 const VarDecl *VD = LC.getCapturedVar(); 9075 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 9076 continue; 9077 auto It = Captures.find(VD); 9078 assert(It != Captures.end() && "Found lambda capture without field."); 9079 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 9080 if (LC.getCaptureKind() == LCK_ByRef) { 9081 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 9082 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 9083 VDLVal.getPointer(CGF)); 9084 CombinedInfo.Exprs.push_back(VD); 9085 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 9086 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF)); 9087 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9088 CGF.getTypeSize( 9089 VD->getType().getCanonicalType().getNonReferenceType()), 9090 CGF.Int64Ty, /*isSigned=*/true)); 9091 } else { 9092 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 9093 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 9094 VDLVal.getPointer(CGF)); 9095 CombinedInfo.Exprs.push_back(VD); 9096 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 9097 CombinedInfo.Pointers.push_back(VarRVal.getScalarVal()); 9098 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 9099 } 9100 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9101 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 9102 CombinedInfo.Mappers.push_back(nullptr); 9103 } 9104 } 9105 9106 /// Set correct indices for lambdas captures. 9107 void adjustMemberOfForLambdaCaptures( 9108 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 9109 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 9110 MapFlagsArrayTy &Types) const { 9111 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 9112 // Set correct member_of idx for all implicit lambda captures. 9113 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9114 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 9115 continue; 9116 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 9117 assert(BasePtr && "Unable to find base lambda address."); 9118 int TgtIdx = -1; 9119 for (unsigned J = I; J > 0; --J) { 9120 unsigned Idx = J - 1; 9121 if (Pointers[Idx] != BasePtr) 9122 continue; 9123 TgtIdx = Idx; 9124 break; 9125 } 9126 assert(TgtIdx != -1 && "Unable to find parent lambda."); 9127 // All other current entries will be MEMBER_OF the combined entry 9128 // (except for PTR_AND_OBJ entries which do not have a placeholder value 9129 // 0xFFFF in the MEMBER_OF field). 9130 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 9131 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 9132 } 9133 } 9134 9135 /// Generate the base pointers, section pointers, sizes, map types, and 9136 /// mappers associated to a given capture (all included in \a CombinedInfo). 9137 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 9138 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 9139 StructRangeInfoTy &PartialStruct) const { 9140 assert(!Cap->capturesVariableArrayType() && 9141 "Not expecting to generate map info for a variable array type!"); 9142 9143 // We need to know when we generating information for the first component 9144 const ValueDecl *VD = Cap->capturesThis() 9145 ? nullptr 9146 : Cap->getCapturedVar()->getCanonicalDecl(); 9147 9148 // for map(to: lambda): skip here, processing it in 9149 // generateDefaultMapInfo 9150 if (LambdasMap.count(VD)) 9151 return; 9152 9153 // If this declaration appears in a is_device_ptr clause we just have to 9154 // pass the pointer by value. If it is a reference to a declaration, we just 9155 // pass its value. 9156 if (DevPointersMap.count(VD)) { 9157 CombinedInfo.Exprs.push_back(VD); 9158 CombinedInfo.BasePointers.emplace_back(Arg, VD); 9159 CombinedInfo.Pointers.push_back(Arg); 9160 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9161 CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty, 9162 /*isSigned=*/true)); 9163 CombinedInfo.Types.push_back( 9164 (Cap->capturesVariable() ? OMP_MAP_TO : OMP_MAP_LITERAL) | 9165 OMP_MAP_TARGET_PARAM); 9166 CombinedInfo.Mappers.push_back(nullptr); 9167 return; 9168 } 9169 9170 using MapData = 9171 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 9172 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool, 9173 const ValueDecl *, const Expr *>; 9174 SmallVector<MapData, 4> DeclComponentLists; 9175 assert(CurDir.is<const OMPExecutableDirective *>() && 9176 "Expect a executable directive"); 9177 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 9178 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 9179 const auto *EI = C->getVarRefs().begin(); 9180 for (const auto L : C->decl_component_lists(VD)) { 9181 const ValueDecl *VDecl, *Mapper; 9182 // The Expression is not correct if the mapping is implicit 9183 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 9184 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9185 std::tie(VDecl, Components, Mapper) = L; 9186 assert(VDecl == VD && "We got information for the wrong declaration??"); 9187 assert(!Components.empty() && 9188 "Not expecting declaration with no component lists."); 9189 DeclComponentLists.emplace_back(Components, C->getMapType(), 9190 C->getMapTypeModifiers(), 9191 C->isImplicit(), Mapper, E); 9192 ++EI; 9193 } 9194 } 9195 llvm::stable_sort(DeclComponentLists, [](const MapData &LHS, 9196 const MapData &RHS) { 9197 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS); 9198 OpenMPMapClauseKind MapType = std::get<1>(RHS); 9199 bool HasPresent = !MapModifiers.empty() && 9200 llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) { 9201 return K == clang::OMPC_MAP_MODIFIER_present; 9202 }); 9203 bool HasAllocs = MapType == OMPC_MAP_alloc; 9204 MapModifiers = std::get<2>(RHS); 9205 MapType = std::get<1>(LHS); 9206 bool HasPresentR = 9207 !MapModifiers.empty() && 9208 llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) { 9209 return K == clang::OMPC_MAP_MODIFIER_present; 9210 }); 9211 bool HasAllocsR = MapType == OMPC_MAP_alloc; 9212 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR); 9213 }); 9214 9215 // Find overlapping elements (including the offset from the base element). 9216 llvm::SmallDenseMap< 9217 const MapData *, 9218 llvm::SmallVector< 9219 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 9220 4> 9221 OverlappedData; 9222 size_t Count = 0; 9223 for (const MapData &L : DeclComponentLists) { 9224 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9225 OpenMPMapClauseKind MapType; 9226 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9227 bool IsImplicit; 9228 const ValueDecl *Mapper; 9229 const Expr *VarRef; 9230 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9231 L; 9232 ++Count; 9233 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 9234 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 9235 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper, 9236 VarRef) = L1; 9237 auto CI = Components.rbegin(); 9238 auto CE = Components.rend(); 9239 auto SI = Components1.rbegin(); 9240 auto SE = Components1.rend(); 9241 for (; CI != CE && SI != SE; ++CI, ++SI) { 9242 if (CI->getAssociatedExpression()->getStmtClass() != 9243 SI->getAssociatedExpression()->getStmtClass()) 9244 break; 9245 // Are we dealing with different variables/fields? 9246 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 9247 break; 9248 } 9249 // Found overlapping if, at least for one component, reached the head 9250 // of the components list. 9251 if (CI == CE || SI == SE) { 9252 // Ignore it if it is the same component. 9253 if (CI == CE && SI == SE) 9254 continue; 9255 const auto It = (SI == SE) ? CI : SI; 9256 // If one component is a pointer and another one is a kind of 9257 // dereference of this pointer (array subscript, section, dereference, 9258 // etc.), it is not an overlapping. 9259 // Same, if one component is a base and another component is a 9260 // dereferenced pointer memberexpr with the same base. 9261 if (!isa<MemberExpr>(It->getAssociatedExpression()) || 9262 (std::prev(It)->getAssociatedDeclaration() && 9263 std::prev(It) 9264 ->getAssociatedDeclaration() 9265 ->getType() 9266 ->isPointerType()) || 9267 (It->getAssociatedDeclaration() && 9268 It->getAssociatedDeclaration()->getType()->isPointerType() && 9269 std::next(It) != CE && std::next(It) != SE)) 9270 continue; 9271 const MapData &BaseData = CI == CE ? L : L1; 9272 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 9273 SI == SE ? Components : Components1; 9274 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 9275 OverlappedElements.getSecond().push_back(SubData); 9276 } 9277 } 9278 } 9279 // Sort the overlapped elements for each item. 9280 llvm::SmallVector<const FieldDecl *, 4> Layout; 9281 if (!OverlappedData.empty()) { 9282 const Type *BaseType = VD->getType().getCanonicalType().getTypePtr(); 9283 const Type *OrigType = BaseType->getPointeeOrArrayElementType(); 9284 while (BaseType != OrigType) { 9285 BaseType = OrigType->getCanonicalTypeInternal().getTypePtr(); 9286 OrigType = BaseType->getPointeeOrArrayElementType(); 9287 } 9288 9289 if (const auto *CRD = BaseType->getAsCXXRecordDecl()) 9290 getPlainLayout(CRD, Layout, /*AsBase=*/false); 9291 else { 9292 const auto *RD = BaseType->getAsRecordDecl(); 9293 Layout.append(RD->field_begin(), RD->field_end()); 9294 } 9295 } 9296 for (auto &Pair : OverlappedData) { 9297 llvm::stable_sort( 9298 Pair.getSecond(), 9299 [&Layout]( 9300 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 9301 OMPClauseMappableExprCommon::MappableExprComponentListRef 9302 Second) { 9303 auto CI = First.rbegin(); 9304 auto CE = First.rend(); 9305 auto SI = Second.rbegin(); 9306 auto SE = Second.rend(); 9307 for (; CI != CE && SI != SE; ++CI, ++SI) { 9308 if (CI->getAssociatedExpression()->getStmtClass() != 9309 SI->getAssociatedExpression()->getStmtClass()) 9310 break; 9311 // Are we dealing with different variables/fields? 9312 if (CI->getAssociatedDeclaration() != 9313 SI->getAssociatedDeclaration()) 9314 break; 9315 } 9316 9317 // Lists contain the same elements. 9318 if (CI == CE && SI == SE) 9319 return false; 9320 9321 // List with less elements is less than list with more elements. 9322 if (CI == CE || SI == SE) 9323 return CI == CE; 9324 9325 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 9326 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 9327 if (FD1->getParent() == FD2->getParent()) 9328 return FD1->getFieldIndex() < FD2->getFieldIndex(); 9329 const auto *It = 9330 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 9331 return FD == FD1 || FD == FD2; 9332 }); 9333 return *It == FD1; 9334 }); 9335 } 9336 9337 // Associated with a capture, because the mapping flags depend on it. 9338 // Go through all of the elements with the overlapped elements. 9339 bool IsFirstComponentList = true; 9340 for (const auto &Pair : OverlappedData) { 9341 const MapData &L = *Pair.getFirst(); 9342 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9343 OpenMPMapClauseKind MapType; 9344 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9345 bool IsImplicit; 9346 const ValueDecl *Mapper; 9347 const Expr *VarRef; 9348 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9349 L; 9350 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 9351 OverlappedComponents = Pair.getSecond(); 9352 generateInfoForComponentList( 9353 MapType, MapModifiers, llvm::None, Components, CombinedInfo, 9354 PartialStruct, IsFirstComponentList, IsImplicit, Mapper, 9355 /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents); 9356 IsFirstComponentList = false; 9357 } 9358 // Go through other elements without overlapped elements. 9359 for (const MapData &L : DeclComponentLists) { 9360 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9361 OpenMPMapClauseKind MapType; 9362 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9363 bool IsImplicit; 9364 const ValueDecl *Mapper; 9365 const Expr *VarRef; 9366 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9367 L; 9368 auto It = OverlappedData.find(&L); 9369 if (It == OverlappedData.end()) 9370 generateInfoForComponentList(MapType, MapModifiers, llvm::None, 9371 Components, CombinedInfo, PartialStruct, 9372 IsFirstComponentList, IsImplicit, Mapper, 9373 /*ForDeviceAddr=*/false, VD, VarRef); 9374 IsFirstComponentList = false; 9375 } 9376 } 9377 9378 /// Generate the default map information for a given capture \a CI, 9379 /// record field declaration \a RI and captured value \a CV. 9380 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 9381 const FieldDecl &RI, llvm::Value *CV, 9382 MapCombinedInfoTy &CombinedInfo) const { 9383 bool IsImplicit = true; 9384 // Do the default mapping. 9385 if (CI.capturesThis()) { 9386 CombinedInfo.Exprs.push_back(nullptr); 9387 CombinedInfo.BasePointers.push_back(CV); 9388 CombinedInfo.Pointers.push_back(CV); 9389 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 9390 CombinedInfo.Sizes.push_back( 9391 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 9392 CGF.Int64Ty, /*isSigned=*/true)); 9393 // Default map type. 9394 CombinedInfo.Types.push_back(OMP_MAP_TO | OMP_MAP_FROM); 9395 } else if (CI.capturesVariableByCopy()) { 9396 const VarDecl *VD = CI.getCapturedVar(); 9397 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9398 CombinedInfo.BasePointers.push_back(CV); 9399 CombinedInfo.Pointers.push_back(CV); 9400 if (!RI.getType()->isAnyPointerType()) { 9401 // We have to signal to the runtime captures passed by value that are 9402 // not pointers. 9403 CombinedInfo.Types.push_back(OMP_MAP_LITERAL); 9404 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9405 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 9406 } else { 9407 // Pointers are implicitly mapped with a zero size and no flags 9408 // (other than first map that is added for all implicit maps). 9409 CombinedInfo.Types.push_back(OMP_MAP_NONE); 9410 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 9411 } 9412 auto I = FirstPrivateDecls.find(VD); 9413 if (I != FirstPrivateDecls.end()) 9414 IsImplicit = I->getSecond(); 9415 } else { 9416 assert(CI.capturesVariable() && "Expected captured reference."); 9417 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 9418 QualType ElementType = PtrTy->getPointeeType(); 9419 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9420 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 9421 // The default map type for a scalar/complex type is 'to' because by 9422 // default the value doesn't have to be retrieved. For an aggregate 9423 // type, the default is 'tofrom'. 9424 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI)); 9425 const VarDecl *VD = CI.getCapturedVar(); 9426 auto I = FirstPrivateDecls.find(VD); 9427 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9428 CombinedInfo.BasePointers.push_back(CV); 9429 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 9430 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 9431 CV, ElementType, CGF.getContext().getDeclAlign(VD), 9432 AlignmentSource::Decl)); 9433 CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); 9434 } else { 9435 CombinedInfo.Pointers.push_back(CV); 9436 } 9437 if (I != FirstPrivateDecls.end()) 9438 IsImplicit = I->getSecond(); 9439 } 9440 // Every default map produces a single argument which is a target parameter. 9441 CombinedInfo.Types.back() |= OMP_MAP_TARGET_PARAM; 9442 9443 // Add flag stating this is an implicit map. 9444 if (IsImplicit) 9445 CombinedInfo.Types.back() |= OMP_MAP_IMPLICIT; 9446 9447 // No user-defined mapper for default mapping. 9448 CombinedInfo.Mappers.push_back(nullptr); 9449 } 9450 }; 9451 } // anonymous namespace 9452 9453 static void emitNonContiguousDescriptor( 9454 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9455 CGOpenMPRuntime::TargetDataInfo &Info) { 9456 CodeGenModule &CGM = CGF.CGM; 9457 MappableExprsHandler::MapCombinedInfoTy::StructNonContiguousInfo 9458 &NonContigInfo = CombinedInfo.NonContigInfo; 9459 9460 // Build an array of struct descriptor_dim and then assign it to 9461 // offload_args. 9462 // 9463 // struct descriptor_dim { 9464 // uint64_t offset; 9465 // uint64_t count; 9466 // uint64_t stride 9467 // }; 9468 ASTContext &C = CGF.getContext(); 9469 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 9470 RecordDecl *RD; 9471 RD = C.buildImplicitRecord("descriptor_dim"); 9472 RD->startDefinition(); 9473 addFieldToRecordDecl(C, RD, Int64Ty); 9474 addFieldToRecordDecl(C, RD, Int64Ty); 9475 addFieldToRecordDecl(C, RD, Int64Ty); 9476 RD->completeDefinition(); 9477 QualType DimTy = C.getRecordType(RD); 9478 9479 enum { OffsetFD = 0, CountFD, StrideFD }; 9480 // We need two index variable here since the size of "Dims" is the same as the 9481 // size of Components, however, the size of offset, count, and stride is equal 9482 // to the size of base declaration that is non-contiguous. 9483 for (unsigned I = 0, L = 0, E = NonContigInfo.Dims.size(); I < E; ++I) { 9484 // Skip emitting ir if dimension size is 1 since it cannot be 9485 // non-contiguous. 9486 if (NonContigInfo.Dims[I] == 1) 9487 continue; 9488 llvm::APInt Size(/*numBits=*/32, NonContigInfo.Dims[I]); 9489 QualType ArrayTy = 9490 C.getConstantArrayType(DimTy, Size, nullptr, ArrayType::Normal, 0); 9491 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 9492 for (unsigned II = 0, EE = NonContigInfo.Dims[I]; II < EE; ++II) { 9493 unsigned RevIdx = EE - II - 1; 9494 LValue DimsLVal = CGF.MakeAddrLValue( 9495 CGF.Builder.CreateConstArrayGEP(DimsAddr, II), DimTy); 9496 // Offset 9497 LValue OffsetLVal = CGF.EmitLValueForField( 9498 DimsLVal, *std::next(RD->field_begin(), OffsetFD)); 9499 CGF.EmitStoreOfScalar(NonContigInfo.Offsets[L][RevIdx], OffsetLVal); 9500 // Count 9501 LValue CountLVal = CGF.EmitLValueForField( 9502 DimsLVal, *std::next(RD->field_begin(), CountFD)); 9503 CGF.EmitStoreOfScalar(NonContigInfo.Counts[L][RevIdx], CountLVal); 9504 // Stride 9505 LValue StrideLVal = CGF.EmitLValueForField( 9506 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 9507 CGF.EmitStoreOfScalar(NonContigInfo.Strides[L][RevIdx], StrideLVal); 9508 } 9509 // args[I] = &dims 9510 Address DAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9511 DimsAddr, CGM.Int8PtrTy); 9512 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9513 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9514 Info.PointersArray, 0, I); 9515 Address PAddr(P, CGF.getPointerAlign()); 9516 CGF.Builder.CreateStore(DAddr.getPointer(), PAddr); 9517 ++L; 9518 } 9519 } 9520 9521 // Try to extract the base declaration from a `this->x` expression if possible. 9522 static ValueDecl *getDeclFromThisExpr(const Expr *E) { 9523 if (!E) 9524 return nullptr; 9525 9526 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenCasts())) 9527 if (const MemberExpr *ME = 9528 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts())) 9529 return ME->getMemberDecl(); 9530 return nullptr; 9531 } 9532 9533 /// Emit a string constant containing the names of the values mapped to the 9534 /// offloading runtime library. 9535 llvm::Constant * 9536 emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, 9537 MappableExprsHandler::MappingExprInfo &MapExprs) { 9538 9539 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr()) 9540 return OMPBuilder.getOrCreateDefaultSrcLocStr(); 9541 9542 SourceLocation Loc; 9543 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) { 9544 if (const ValueDecl *VD = getDeclFromThisExpr(MapExprs.getMapExpr())) 9545 Loc = VD->getLocation(); 9546 else 9547 Loc = MapExprs.getMapExpr()->getExprLoc(); 9548 } else { 9549 Loc = MapExprs.getMapDecl()->getLocation(); 9550 } 9551 9552 std::string ExprName = ""; 9553 if (MapExprs.getMapExpr()) { 9554 PrintingPolicy P(CGF.getContext().getLangOpts()); 9555 llvm::raw_string_ostream OS(ExprName); 9556 MapExprs.getMapExpr()->printPretty(OS, nullptr, P); 9557 OS.flush(); 9558 } else { 9559 ExprName = MapExprs.getMapDecl()->getNameAsString(); 9560 } 9561 9562 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 9563 return OMPBuilder.getOrCreateSrcLocStr(PLoc.getFilename(), ExprName.c_str(), 9564 PLoc.getLine(), PLoc.getColumn()); 9565 } 9566 9567 /// Emit the arrays used to pass the captures and map information to the 9568 /// offloading runtime library. If there is no map or capture information, 9569 /// return nullptr by reference. 9570 static void emitOffloadingArrays( 9571 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9572 CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, 9573 bool IsNonContiguous = false) { 9574 CodeGenModule &CGM = CGF.CGM; 9575 ASTContext &Ctx = CGF.getContext(); 9576 9577 // Reset the array information. 9578 Info.clearArrayInfo(); 9579 Info.NumberOfPtrs = CombinedInfo.BasePointers.size(); 9580 9581 if (Info.NumberOfPtrs) { 9582 // Detect if we have any capture size requiring runtime evaluation of the 9583 // size so that a constant array could be eventually used. 9584 bool hasRuntimeEvaluationCaptureSize = false; 9585 for (llvm::Value *S : CombinedInfo.Sizes) 9586 if (!isa<llvm::Constant>(S)) { 9587 hasRuntimeEvaluationCaptureSize = true; 9588 break; 9589 } 9590 9591 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 9592 QualType PointerArrayType = Ctx.getConstantArrayType( 9593 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 9594 /*IndexTypeQuals=*/0); 9595 9596 Info.BasePointersArray = 9597 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 9598 Info.PointersArray = 9599 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 9600 Address MappersArray = 9601 CGF.CreateMemTemp(PointerArrayType, ".offload_mappers"); 9602 Info.MappersArray = MappersArray.getPointer(); 9603 9604 // If we don't have any VLA types or other types that require runtime 9605 // evaluation, we can use a constant array for the map sizes, otherwise we 9606 // need to fill up the arrays as we do for the pointers. 9607 QualType Int64Ty = 9608 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 9609 if (hasRuntimeEvaluationCaptureSize) { 9610 QualType SizeArrayType = Ctx.getConstantArrayType( 9611 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 9612 /*IndexTypeQuals=*/0); 9613 Info.SizesArray = 9614 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 9615 } else { 9616 // We expect all the sizes to be constant, so we collect them to create 9617 // a constant array. 9618 SmallVector<llvm::Constant *, 16> ConstSizes; 9619 for (unsigned I = 0, E = CombinedInfo.Sizes.size(); I < E; ++I) { 9620 if (IsNonContiguous && 9621 (CombinedInfo.Types[I] & MappableExprsHandler::OMP_MAP_NON_CONTIG)) { 9622 ConstSizes.push_back(llvm::ConstantInt::get( 9623 CGF.Int64Ty, CombinedInfo.NonContigInfo.Dims[I])); 9624 } else { 9625 ConstSizes.push_back(cast<llvm::Constant>(CombinedInfo.Sizes[I])); 9626 } 9627 } 9628 9629 auto *SizesArrayInit = llvm::ConstantArray::get( 9630 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 9631 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 9632 auto *SizesArrayGbl = new llvm::GlobalVariable( 9633 CGM.getModule(), SizesArrayInit->getType(), 9634 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 9635 SizesArrayInit, Name); 9636 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 9637 Info.SizesArray = SizesArrayGbl; 9638 } 9639 9640 // The map types are always constant so we don't need to generate code to 9641 // fill arrays. Instead, we create an array constant. 9642 SmallVector<uint64_t, 4> Mapping(CombinedInfo.Types.size(), 0); 9643 llvm::copy(CombinedInfo.Types, Mapping.begin()); 9644 std::string MaptypesName = 9645 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 9646 auto *MapTypesArrayGbl = 9647 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName); 9648 Info.MapTypesArray = MapTypesArrayGbl; 9649 9650 // The information types are only built if there is debug information 9651 // requested. 9652 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) { 9653 Info.MapNamesArray = llvm::Constant::getNullValue( 9654 llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo()); 9655 } else { 9656 auto fillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) { 9657 return emitMappingInformation(CGF, OMPBuilder, MapExpr); 9658 }; 9659 SmallVector<llvm::Constant *, 4> InfoMap(CombinedInfo.Exprs.size()); 9660 llvm::transform(CombinedInfo.Exprs, InfoMap.begin(), fillInfoMap); 9661 std::string MapnamesName = 9662 CGM.getOpenMPRuntime().getName({"offload_mapnames"}); 9663 auto *MapNamesArrayGbl = 9664 OMPBuilder.createOffloadMapnames(InfoMap, MapnamesName); 9665 Info.MapNamesArray = MapNamesArrayGbl; 9666 } 9667 9668 // If there's a present map type modifier, it must not be applied to the end 9669 // of a region, so generate a separate map type array in that case. 9670 if (Info.separateBeginEndCalls()) { 9671 bool EndMapTypesDiffer = false; 9672 for (uint64_t &Type : Mapping) { 9673 if (Type & MappableExprsHandler::OMP_MAP_PRESENT) { 9674 Type &= ~MappableExprsHandler::OMP_MAP_PRESENT; 9675 EndMapTypesDiffer = true; 9676 } 9677 } 9678 if (EndMapTypesDiffer) { 9679 MapTypesArrayGbl = 9680 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName); 9681 Info.MapTypesArrayEnd = MapTypesArrayGbl; 9682 } 9683 } 9684 9685 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 9686 llvm::Value *BPVal = *CombinedInfo.BasePointers[I]; 9687 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 9688 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9689 Info.BasePointersArray, 0, I); 9690 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9691 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9692 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9693 CGF.Builder.CreateStore(BPVal, BPAddr); 9694 9695 if (Info.requiresDevicePointerInfo()) 9696 if (const ValueDecl *DevVD = 9697 CombinedInfo.BasePointers[I].getDevicePtrDecl()) 9698 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 9699 9700 llvm::Value *PVal = CombinedInfo.Pointers[I]; 9701 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9702 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9703 Info.PointersArray, 0, I); 9704 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9705 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9706 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9707 CGF.Builder.CreateStore(PVal, PAddr); 9708 9709 if (hasRuntimeEvaluationCaptureSize) { 9710 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 9711 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9712 Info.SizesArray, 9713 /*Idx0=*/0, 9714 /*Idx1=*/I); 9715 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 9716 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(CombinedInfo.Sizes[I], 9717 CGM.Int64Ty, 9718 /*isSigned=*/true), 9719 SAddr); 9720 } 9721 9722 // Fill up the mapper array. 9723 llvm::Value *MFunc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 9724 if (CombinedInfo.Mappers[I]) { 9725 MFunc = CGM.getOpenMPRuntime().getOrCreateUserDefinedMapperFunc( 9726 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I])); 9727 MFunc = CGF.Builder.CreatePointerCast(MFunc, CGM.VoidPtrTy); 9728 Info.HasMapper = true; 9729 } 9730 Address MAddr = CGF.Builder.CreateConstArrayGEP(MappersArray, I); 9731 CGF.Builder.CreateStore(MFunc, MAddr); 9732 } 9733 } 9734 9735 if (!IsNonContiguous || CombinedInfo.NonContigInfo.Offsets.empty() || 9736 Info.NumberOfPtrs == 0) 9737 return; 9738 9739 emitNonContiguousDescriptor(CGF, CombinedInfo, Info); 9740 } 9741 9742 namespace { 9743 /// Additional arguments for emitOffloadingArraysArgument function. 9744 struct ArgumentsOptions { 9745 bool ForEndCall = false; 9746 ArgumentsOptions() = default; 9747 ArgumentsOptions(bool ForEndCall) : ForEndCall(ForEndCall) {} 9748 }; 9749 } // namespace 9750 9751 /// Emit the arguments to be passed to the runtime library based on the 9752 /// arrays of base pointers, pointers, sizes, map types, and mappers. If 9753 /// ForEndCall, emit map types to be passed for the end of the region instead of 9754 /// the beginning. 9755 static void emitOffloadingArraysArgument( 9756 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 9757 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 9758 llvm::Value *&MapTypesArrayArg, llvm::Value *&MapNamesArrayArg, 9759 llvm::Value *&MappersArrayArg, CGOpenMPRuntime::TargetDataInfo &Info, 9760 const ArgumentsOptions &Options = ArgumentsOptions()) { 9761 assert((!Options.ForEndCall || Info.separateBeginEndCalls()) && 9762 "expected region end call to runtime only when end call is separate"); 9763 CodeGenModule &CGM = CGF.CGM; 9764 if (Info.NumberOfPtrs) { 9765 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9766 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9767 Info.BasePointersArray, 9768 /*Idx0=*/0, /*Idx1=*/0); 9769 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9770 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9771 Info.PointersArray, 9772 /*Idx0=*/0, 9773 /*Idx1=*/0); 9774 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9775 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 9776 /*Idx0=*/0, /*Idx1=*/0); 9777 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9778 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9779 Options.ForEndCall && Info.MapTypesArrayEnd ? Info.MapTypesArrayEnd 9780 : Info.MapTypesArray, 9781 /*Idx0=*/0, 9782 /*Idx1=*/0); 9783 9784 // Only emit the mapper information arrays if debug information is 9785 // requested. 9786 if (CGF.CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 9787 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9788 else 9789 MapNamesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9790 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9791 Info.MapNamesArray, 9792 /*Idx0=*/0, 9793 /*Idx1=*/0); 9794 // If there is no user-defined mapper, set the mapper array to nullptr to 9795 // avoid an unnecessary data privatization 9796 if (!Info.HasMapper) 9797 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9798 else 9799 MappersArrayArg = 9800 CGF.Builder.CreatePointerCast(Info.MappersArray, CGM.VoidPtrPtrTy); 9801 } else { 9802 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9803 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9804 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9805 MapTypesArrayArg = 9806 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9807 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9808 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9809 } 9810 } 9811 9812 /// Check for inner distribute directive. 9813 static const OMPExecutableDirective * 9814 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 9815 const auto *CS = D.getInnermostCapturedStmt(); 9816 const auto *Body = 9817 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 9818 const Stmt *ChildStmt = 9819 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9820 9821 if (const auto *NestedDir = 9822 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9823 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 9824 switch (D.getDirectiveKind()) { 9825 case OMPD_target: 9826 if (isOpenMPDistributeDirective(DKind)) 9827 return NestedDir; 9828 if (DKind == OMPD_teams) { 9829 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 9830 /*IgnoreCaptured=*/true); 9831 if (!Body) 9832 return nullptr; 9833 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9834 if (const auto *NND = 9835 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9836 DKind = NND->getDirectiveKind(); 9837 if (isOpenMPDistributeDirective(DKind)) 9838 return NND; 9839 } 9840 } 9841 return nullptr; 9842 case OMPD_target_teams: 9843 if (isOpenMPDistributeDirective(DKind)) 9844 return NestedDir; 9845 return nullptr; 9846 case OMPD_target_parallel: 9847 case OMPD_target_simd: 9848 case OMPD_target_parallel_for: 9849 case OMPD_target_parallel_for_simd: 9850 return nullptr; 9851 case OMPD_target_teams_distribute: 9852 case OMPD_target_teams_distribute_simd: 9853 case OMPD_target_teams_distribute_parallel_for: 9854 case OMPD_target_teams_distribute_parallel_for_simd: 9855 case OMPD_parallel: 9856 case OMPD_for: 9857 case OMPD_parallel_for: 9858 case OMPD_parallel_master: 9859 case OMPD_parallel_sections: 9860 case OMPD_for_simd: 9861 case OMPD_parallel_for_simd: 9862 case OMPD_cancel: 9863 case OMPD_cancellation_point: 9864 case OMPD_ordered: 9865 case OMPD_threadprivate: 9866 case OMPD_allocate: 9867 case OMPD_task: 9868 case OMPD_simd: 9869 case OMPD_tile: 9870 case OMPD_unroll: 9871 case OMPD_sections: 9872 case OMPD_section: 9873 case OMPD_single: 9874 case OMPD_master: 9875 case OMPD_critical: 9876 case OMPD_taskyield: 9877 case OMPD_barrier: 9878 case OMPD_taskwait: 9879 case OMPD_taskgroup: 9880 case OMPD_atomic: 9881 case OMPD_flush: 9882 case OMPD_depobj: 9883 case OMPD_scan: 9884 case OMPD_teams: 9885 case OMPD_target_data: 9886 case OMPD_target_exit_data: 9887 case OMPD_target_enter_data: 9888 case OMPD_distribute: 9889 case OMPD_distribute_simd: 9890 case OMPD_distribute_parallel_for: 9891 case OMPD_distribute_parallel_for_simd: 9892 case OMPD_teams_distribute: 9893 case OMPD_teams_distribute_simd: 9894 case OMPD_teams_distribute_parallel_for: 9895 case OMPD_teams_distribute_parallel_for_simd: 9896 case OMPD_target_update: 9897 case OMPD_declare_simd: 9898 case OMPD_declare_variant: 9899 case OMPD_begin_declare_variant: 9900 case OMPD_end_declare_variant: 9901 case OMPD_declare_target: 9902 case OMPD_end_declare_target: 9903 case OMPD_declare_reduction: 9904 case OMPD_declare_mapper: 9905 case OMPD_taskloop: 9906 case OMPD_taskloop_simd: 9907 case OMPD_master_taskloop: 9908 case OMPD_master_taskloop_simd: 9909 case OMPD_parallel_master_taskloop: 9910 case OMPD_parallel_master_taskloop_simd: 9911 case OMPD_requires: 9912 case OMPD_metadirective: 9913 case OMPD_unknown: 9914 default: 9915 llvm_unreachable("Unexpected directive."); 9916 } 9917 } 9918 9919 return nullptr; 9920 } 9921 9922 /// Emit the user-defined mapper function. The code generation follows the 9923 /// pattern in the example below. 9924 /// \code 9925 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 9926 /// void *base, void *begin, 9927 /// int64_t size, int64_t type, 9928 /// void *name = nullptr) { 9929 /// // Allocate space for an array section first or add a base/begin for 9930 /// // pointer dereference. 9931 /// if ((size > 1 || (base != begin && maptype.IsPtrAndObj)) && 9932 /// !maptype.IsDelete) 9933 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9934 /// size*sizeof(Ty), clearToFromMember(type)); 9935 /// // Map members. 9936 /// for (unsigned i = 0; i < size; i++) { 9937 /// // For each component specified by this mapper: 9938 /// for (auto c : begin[i]->all_components) { 9939 /// if (c.hasMapper()) 9940 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 9941 /// c.arg_type, c.arg_name); 9942 /// else 9943 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 9944 /// c.arg_begin, c.arg_size, c.arg_type, 9945 /// c.arg_name); 9946 /// } 9947 /// } 9948 /// // Delete the array section. 9949 /// if (size > 1 && maptype.IsDelete) 9950 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9951 /// size*sizeof(Ty), clearToFromMember(type)); 9952 /// } 9953 /// \endcode 9954 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 9955 CodeGenFunction *CGF) { 9956 if (UDMMap.count(D) > 0) 9957 return; 9958 ASTContext &C = CGM.getContext(); 9959 QualType Ty = D->getType(); 9960 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 9961 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 9962 auto *MapperVarDecl = 9963 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 9964 SourceLocation Loc = D->getLocation(); 9965 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 9966 9967 // Prepare mapper function arguments and attributes. 9968 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9969 C.VoidPtrTy, ImplicitParamDecl::Other); 9970 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9971 ImplicitParamDecl::Other); 9972 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9973 C.VoidPtrTy, ImplicitParamDecl::Other); 9974 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9975 ImplicitParamDecl::Other); 9976 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9977 ImplicitParamDecl::Other); 9978 ImplicitParamDecl NameArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9979 ImplicitParamDecl::Other); 9980 FunctionArgList Args; 9981 Args.push_back(&HandleArg); 9982 Args.push_back(&BaseArg); 9983 Args.push_back(&BeginArg); 9984 Args.push_back(&SizeArg); 9985 Args.push_back(&TypeArg); 9986 Args.push_back(&NameArg); 9987 const CGFunctionInfo &FnInfo = 9988 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 9989 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 9990 SmallString<64> TyStr; 9991 llvm::raw_svector_ostream Out(TyStr); 9992 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 9993 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 9994 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 9995 Name, &CGM.getModule()); 9996 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 9997 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 9998 // Start the mapper function code generation. 9999 CodeGenFunction MapperCGF(CGM); 10000 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 10001 // Compute the starting and end addresses of array elements. 10002 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 10003 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 10004 C.getPointerType(Int64Ty), Loc); 10005 // Prepare common arguments for array initiation and deletion. 10006 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 10007 MapperCGF.GetAddrOfLocalVar(&HandleArg), 10008 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 10009 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 10010 MapperCGF.GetAddrOfLocalVar(&BaseArg), 10011 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 10012 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 10013 MapperCGF.GetAddrOfLocalVar(&BeginArg), 10014 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 10015 // Convert the size in bytes into the number of array elements. 10016 Size = MapperCGF.Builder.CreateExactUDiv( 10017 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 10018 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 10019 BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy)); 10020 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP( 10021 PtrBegin->getType()->getPointerElementType(), PtrBegin, Size); 10022 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 10023 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 10024 C.getPointerType(Int64Ty), Loc); 10025 llvm::Value *MapName = MapperCGF.EmitLoadOfScalar( 10026 MapperCGF.GetAddrOfLocalVar(&NameArg), 10027 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 10028 10029 // Emit array initiation if this is an array section and \p MapType indicates 10030 // that memory allocation is required. 10031 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 10032 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 10033 MapName, ElementSize, HeadBB, /*IsInit=*/true); 10034 10035 // Emit a for loop to iterate through SizeArg of elements and map all of them. 10036 10037 // Emit the loop header block. 10038 MapperCGF.EmitBlock(HeadBB); 10039 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 10040 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 10041 // Evaluate whether the initial condition is satisfied. 10042 llvm::Value *IsEmpty = 10043 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 10044 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 10045 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 10046 10047 // Emit the loop body block. 10048 MapperCGF.EmitBlock(BodyBB); 10049 llvm::BasicBlock *LastBB = BodyBB; 10050 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 10051 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 10052 PtrPHI->addIncoming(PtrBegin, EntryBB); 10053 Address PtrCurrent = 10054 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 10055 .getAlignment() 10056 .alignmentOfArrayElement(ElementSize)); 10057 // Privatize the declared variable of mapper to be the current array element. 10058 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 10059 Scope.addPrivate(MapperVarDecl, [PtrCurrent]() { return PtrCurrent; }); 10060 (void)Scope.Privatize(); 10061 10062 // Get map clause information. Fill up the arrays with all mapped variables. 10063 MappableExprsHandler::MapCombinedInfoTy Info; 10064 MappableExprsHandler MEHandler(*D, MapperCGF); 10065 MEHandler.generateAllInfoForMapper(Info); 10066 10067 // Call the runtime API __tgt_mapper_num_components to get the number of 10068 // pre-existing components. 10069 llvm::Value *OffloadingArgs[] = {Handle}; 10070 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 10071 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 10072 OMPRTL___tgt_mapper_num_components), 10073 OffloadingArgs); 10074 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 10075 PreviousSize, 10076 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 10077 10078 // Fill up the runtime mapper handle for all components. 10079 for (unsigned I = 0; I < Info.BasePointers.size(); ++I) { 10080 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 10081 *Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 10082 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 10083 Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 10084 llvm::Value *CurSizeArg = Info.Sizes[I]; 10085 llvm::Value *CurNameArg = 10086 (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 10087 ? llvm::ConstantPointerNull::get(CGM.VoidPtrTy) 10088 : emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]); 10089 10090 // Extract the MEMBER_OF field from the map type. 10091 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(Info.Types[I]); 10092 llvm::Value *MemberMapType = 10093 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 10094 10095 // Combine the map type inherited from user-defined mapper with that 10096 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 10097 // bits of the \a MapType, which is the input argument of the mapper 10098 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 10099 // bits of MemberMapType. 10100 // [OpenMP 5.0], 1.2.6. map-type decay. 10101 // | alloc | to | from | tofrom | release | delete 10102 // ---------------------------------------------------------- 10103 // alloc | alloc | alloc | alloc | alloc | release | delete 10104 // to | alloc | to | alloc | to | release | delete 10105 // from | alloc | alloc | from | from | release | delete 10106 // tofrom | alloc | to | from | tofrom | release | delete 10107 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 10108 MapType, 10109 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 10110 MappableExprsHandler::OMP_MAP_FROM)); 10111 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 10112 llvm::BasicBlock *AllocElseBB = 10113 MapperCGF.createBasicBlock("omp.type.alloc.else"); 10114 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 10115 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 10116 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 10117 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 10118 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 10119 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 10120 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 10121 MapperCGF.EmitBlock(AllocBB); 10122 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 10123 MemberMapType, 10124 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 10125 MappableExprsHandler::OMP_MAP_FROM))); 10126 MapperCGF.Builder.CreateBr(EndBB); 10127 MapperCGF.EmitBlock(AllocElseBB); 10128 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 10129 LeftToFrom, 10130 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 10131 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 10132 // In case of to, clear OMP_MAP_FROM. 10133 MapperCGF.EmitBlock(ToBB); 10134 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 10135 MemberMapType, 10136 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 10137 MapperCGF.Builder.CreateBr(EndBB); 10138 MapperCGF.EmitBlock(ToElseBB); 10139 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 10140 LeftToFrom, 10141 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 10142 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 10143 // In case of from, clear OMP_MAP_TO. 10144 MapperCGF.EmitBlock(FromBB); 10145 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 10146 MemberMapType, 10147 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 10148 // In case of tofrom, do nothing. 10149 MapperCGF.EmitBlock(EndBB); 10150 LastBB = EndBB; 10151 llvm::PHINode *CurMapType = 10152 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 10153 CurMapType->addIncoming(AllocMapType, AllocBB); 10154 CurMapType->addIncoming(ToMapType, ToBB); 10155 CurMapType->addIncoming(FromMapType, FromBB); 10156 CurMapType->addIncoming(MemberMapType, ToElseBB); 10157 10158 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 10159 CurSizeArg, CurMapType, CurNameArg}; 10160 if (Info.Mappers[I]) { 10161 // Call the corresponding mapper function. 10162 llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc( 10163 cast<OMPDeclareMapperDecl>(Info.Mappers[I])); 10164 assert(MapperFunc && "Expect a valid mapper function is available."); 10165 MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs); 10166 } else { 10167 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 10168 // data structure. 10169 MapperCGF.EmitRuntimeCall( 10170 OMPBuilder.getOrCreateRuntimeFunction( 10171 CGM.getModule(), OMPRTL___tgt_push_mapper_component), 10172 OffloadingArgs); 10173 } 10174 } 10175 10176 // Update the pointer to point to the next element that needs to be mapped, 10177 // and check whether we have mapped all elements. 10178 llvm::Type *ElemTy = PtrPHI->getType()->getPointerElementType(); 10179 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 10180 ElemTy, PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 10181 PtrPHI->addIncoming(PtrNext, LastBB); 10182 llvm::Value *IsDone = 10183 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 10184 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 10185 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 10186 10187 MapperCGF.EmitBlock(ExitBB); 10188 // Emit array deletion if this is an array section and \p MapType indicates 10189 // that deletion is required. 10190 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 10191 MapName, ElementSize, DoneBB, /*IsInit=*/false); 10192 10193 // Emit the function exit block. 10194 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 10195 MapperCGF.FinishFunction(); 10196 UDMMap.try_emplace(D, Fn); 10197 if (CGF) { 10198 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 10199 Decls.second.push_back(D); 10200 } 10201 } 10202 10203 /// Emit the array initialization or deletion portion for user-defined mapper 10204 /// code generation. First, it evaluates whether an array section is mapped and 10205 /// whether the \a MapType instructs to delete this section. If \a IsInit is 10206 /// true, and \a MapType indicates to not delete this array, array 10207 /// initialization code is generated. If \a IsInit is false, and \a MapType 10208 /// indicates to not this array, array deletion code is generated. 10209 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 10210 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 10211 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 10212 llvm::Value *MapName, CharUnits ElementSize, llvm::BasicBlock *ExitBB, 10213 bool IsInit) { 10214 StringRef Prefix = IsInit ? ".init" : ".del"; 10215 10216 // Evaluate if this is an array section. 10217 llvm::BasicBlock *BodyBB = 10218 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 10219 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGT( 10220 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 10221 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 10222 MapType, 10223 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 10224 llvm::Value *DeleteCond; 10225 llvm::Value *Cond; 10226 if (IsInit) { 10227 // base != begin? 10228 llvm::Value *BaseIsBegin = MapperCGF.Builder.CreateIsNotNull( 10229 MapperCGF.Builder.CreatePtrDiff(Base, Begin)); 10230 // IsPtrAndObj? 10231 llvm::Value *PtrAndObjBit = MapperCGF.Builder.CreateAnd( 10232 MapType, 10233 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_PTR_AND_OBJ)); 10234 PtrAndObjBit = MapperCGF.Builder.CreateIsNotNull(PtrAndObjBit); 10235 BaseIsBegin = MapperCGF.Builder.CreateAnd(BaseIsBegin, PtrAndObjBit); 10236 Cond = MapperCGF.Builder.CreateOr(IsArray, BaseIsBegin); 10237 DeleteCond = MapperCGF.Builder.CreateIsNull( 10238 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 10239 } else { 10240 Cond = IsArray; 10241 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 10242 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 10243 } 10244 Cond = MapperCGF.Builder.CreateAnd(Cond, DeleteCond); 10245 MapperCGF.Builder.CreateCondBr(Cond, BodyBB, ExitBB); 10246 10247 MapperCGF.EmitBlock(BodyBB); 10248 // Get the array size by multiplying element size and element number (i.e., \p 10249 // Size). 10250 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 10251 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 10252 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 10253 // memory allocation/deletion purpose only. 10254 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 10255 MapType, 10256 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 10257 MappableExprsHandler::OMP_MAP_FROM))); 10258 MapTypeArg = MapperCGF.Builder.CreateOr( 10259 MapTypeArg, 10260 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_IMPLICIT)); 10261 10262 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 10263 // data structure. 10264 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, 10265 ArraySize, MapTypeArg, MapName}; 10266 MapperCGF.EmitRuntimeCall( 10267 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 10268 OMPRTL___tgt_push_mapper_component), 10269 OffloadingArgs); 10270 } 10271 10272 llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc( 10273 const OMPDeclareMapperDecl *D) { 10274 auto I = UDMMap.find(D); 10275 if (I != UDMMap.end()) 10276 return I->second; 10277 emitUserDefinedMapper(D); 10278 return UDMMap.lookup(D); 10279 } 10280 10281 void CGOpenMPRuntime::emitTargetNumIterationsCall( 10282 CodeGenFunction &CGF, const OMPExecutableDirective &D, 10283 llvm::Value *DeviceID, 10284 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 10285 const OMPLoopDirective &D)> 10286 SizeEmitter) { 10287 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 10288 const OMPExecutableDirective *TD = &D; 10289 // Get nested teams distribute kind directive, if any. 10290 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 10291 TD = getNestedDistributeDirective(CGM.getContext(), D); 10292 if (!TD) 10293 return; 10294 const auto *LD = cast<OMPLoopDirective>(TD); 10295 auto &&CodeGen = [LD, DeviceID, SizeEmitter, &D, this](CodeGenFunction &CGF, 10296 PrePostActionTy &) { 10297 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 10298 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10299 llvm::Value *Args[] = {RTLoc, DeviceID, NumIterations}; 10300 CGF.EmitRuntimeCall( 10301 OMPBuilder.getOrCreateRuntimeFunction( 10302 CGM.getModule(), OMPRTL___kmpc_push_target_tripcount_mapper), 10303 Args); 10304 } 10305 }; 10306 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 10307 } 10308 10309 void CGOpenMPRuntime::emitTargetCall( 10310 CodeGenFunction &CGF, const OMPExecutableDirective &D, 10311 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 10312 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 10313 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 10314 const OMPLoopDirective &D)> 10315 SizeEmitter) { 10316 if (!CGF.HaveInsertPoint()) 10317 return; 10318 10319 assert(OutlinedFn && "Invalid outlined function!"); 10320 10321 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 10322 D.hasClausesOfKind<OMPNowaitClause>(); 10323 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 10324 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 10325 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 10326 PrePostActionTy &) { 10327 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10328 }; 10329 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 10330 10331 CodeGenFunction::OMPTargetDataInfo InputInfo; 10332 llvm::Value *MapTypesArray = nullptr; 10333 llvm::Value *MapNamesArray = nullptr; 10334 // Fill up the pointer arrays and transfer execution to the device. 10335 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 10336 &MapTypesArray, &MapNamesArray, &CS, RequiresOuterTask, 10337 &CapturedVars, 10338 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 10339 if (Device.getInt() == OMPC_DEVICE_ancestor) { 10340 // Reverse offloading is not supported, so just execute on the host. 10341 if (RequiresOuterTask) { 10342 CapturedVars.clear(); 10343 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10344 } 10345 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10346 return; 10347 } 10348 10349 // On top of the arrays that were filled up, the target offloading call 10350 // takes as arguments the device id as well as the host pointer. The host 10351 // pointer is used by the runtime library to identify the current target 10352 // region, so it only has to be unique and not necessarily point to 10353 // anything. It could be the pointer to the outlined function that 10354 // implements the target region, but we aren't using that so that the 10355 // compiler doesn't need to keep that, and could therefore inline the host 10356 // function if proven worthwhile during optimization. 10357 10358 // From this point on, we need to have an ID of the target region defined. 10359 assert(OutlinedFnID && "Invalid outlined function ID!"); 10360 10361 // Emit device ID if any. 10362 llvm::Value *DeviceID; 10363 if (Device.getPointer()) { 10364 assert((Device.getInt() == OMPC_DEVICE_unknown || 10365 Device.getInt() == OMPC_DEVICE_device_num) && 10366 "Expected device_num modifier."); 10367 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer()); 10368 DeviceID = 10369 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true); 10370 } else { 10371 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10372 } 10373 10374 // Emit the number of elements in the offloading arrays. 10375 llvm::Value *PointerNum = 10376 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10377 10378 // Return value of the runtime offloading call. 10379 llvm::Value *Return; 10380 10381 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 10382 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 10383 10384 // Source location for the ident struct 10385 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10386 10387 // Emit tripcount for the target loop-based directive. 10388 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 10389 10390 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10391 // The target region is an outlined function launched by the runtime 10392 // via calls __tgt_target() or __tgt_target_teams(). 10393 // 10394 // __tgt_target() launches a target region with one team and one thread, 10395 // executing a serial region. This master thread may in turn launch 10396 // more threads within its team upon encountering a parallel region, 10397 // however, no additional teams can be launched on the device. 10398 // 10399 // __tgt_target_teams() launches a target region with one or more teams, 10400 // each with one or more threads. This call is required for target 10401 // constructs such as: 10402 // 'target teams' 10403 // 'target' / 'teams' 10404 // 'target teams distribute parallel for' 10405 // 'target parallel' 10406 // and so on. 10407 // 10408 // Note that on the host and CPU targets, the runtime implementation of 10409 // these calls simply call the outlined function without forking threads. 10410 // The outlined functions themselves have runtime calls to 10411 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 10412 // the compiler in emitTeamsCall() and emitParallelCall(). 10413 // 10414 // In contrast, on the NVPTX target, the implementation of 10415 // __tgt_target_teams() launches a GPU kernel with the requested number 10416 // of teams and threads so no additional calls to the runtime are required. 10417 if (NumTeams) { 10418 // If we have NumTeams defined this means that we have an enclosed teams 10419 // region. Therefore we also expect to have NumThreads defined. These two 10420 // values should be defined in the presence of a teams directive, 10421 // regardless of having any clauses associated. If the user is using teams 10422 // but no clauses, these two values will be the default that should be 10423 // passed to the runtime library - a 32-bit integer with the value zero. 10424 assert(NumThreads && "Thread limit expression should be available along " 10425 "with number of teams."); 10426 SmallVector<llvm::Value *> OffloadingArgs = { 10427 RTLoc, 10428 DeviceID, 10429 OutlinedFnID, 10430 PointerNum, 10431 InputInfo.BasePointersArray.getPointer(), 10432 InputInfo.PointersArray.getPointer(), 10433 InputInfo.SizesArray.getPointer(), 10434 MapTypesArray, 10435 MapNamesArray, 10436 InputInfo.MappersArray.getPointer(), 10437 NumTeams, 10438 NumThreads}; 10439 if (HasNowait) { 10440 // Add int32_t depNum = 0, void *depList = nullptr, int32_t 10441 // noAliasDepNum = 0, void *noAliasDepList = nullptr. 10442 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10443 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10444 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10445 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10446 } 10447 Return = CGF.EmitRuntimeCall( 10448 OMPBuilder.getOrCreateRuntimeFunction( 10449 CGM.getModule(), HasNowait 10450 ? OMPRTL___tgt_target_teams_nowait_mapper 10451 : OMPRTL___tgt_target_teams_mapper), 10452 OffloadingArgs); 10453 } else { 10454 SmallVector<llvm::Value *> OffloadingArgs = { 10455 RTLoc, 10456 DeviceID, 10457 OutlinedFnID, 10458 PointerNum, 10459 InputInfo.BasePointersArray.getPointer(), 10460 InputInfo.PointersArray.getPointer(), 10461 InputInfo.SizesArray.getPointer(), 10462 MapTypesArray, 10463 MapNamesArray, 10464 InputInfo.MappersArray.getPointer()}; 10465 if (HasNowait) { 10466 // Add int32_t depNum = 0, void *depList = nullptr, int32_t 10467 // noAliasDepNum = 0, void *noAliasDepList = nullptr. 10468 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10469 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10470 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10471 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10472 } 10473 Return = CGF.EmitRuntimeCall( 10474 OMPBuilder.getOrCreateRuntimeFunction( 10475 CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper 10476 : OMPRTL___tgt_target_mapper), 10477 OffloadingArgs); 10478 } 10479 10480 // Check the error code and execute the host version if required. 10481 llvm::BasicBlock *OffloadFailedBlock = 10482 CGF.createBasicBlock("omp_offload.failed"); 10483 llvm::BasicBlock *OffloadContBlock = 10484 CGF.createBasicBlock("omp_offload.cont"); 10485 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 10486 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 10487 10488 CGF.EmitBlock(OffloadFailedBlock); 10489 if (RequiresOuterTask) { 10490 CapturedVars.clear(); 10491 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10492 } 10493 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10494 CGF.EmitBranch(OffloadContBlock); 10495 10496 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 10497 }; 10498 10499 // Notify that the host version must be executed. 10500 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 10501 RequiresOuterTask](CodeGenFunction &CGF, 10502 PrePostActionTy &) { 10503 if (RequiresOuterTask) { 10504 CapturedVars.clear(); 10505 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10506 } 10507 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10508 }; 10509 10510 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 10511 &MapNamesArray, &CapturedVars, RequiresOuterTask, 10512 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 10513 // Fill up the arrays with all the captured variables. 10514 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 10515 10516 // Get mappable expression information. 10517 MappableExprsHandler MEHandler(D, CGF); 10518 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 10519 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet; 10520 10521 auto RI = CS.getCapturedRecordDecl()->field_begin(); 10522 auto *CV = CapturedVars.begin(); 10523 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 10524 CE = CS.capture_end(); 10525 CI != CE; ++CI, ++RI, ++CV) { 10526 MappableExprsHandler::MapCombinedInfoTy CurInfo; 10527 MappableExprsHandler::StructRangeInfoTy PartialStruct; 10528 10529 // VLA sizes are passed to the outlined region by copy and do not have map 10530 // information associated. 10531 if (CI->capturesVariableArrayType()) { 10532 CurInfo.Exprs.push_back(nullptr); 10533 CurInfo.BasePointers.push_back(*CV); 10534 CurInfo.Pointers.push_back(*CV); 10535 CurInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 10536 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 10537 // Copy to the device as an argument. No need to retrieve it. 10538 CurInfo.Types.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 10539 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 10540 MappableExprsHandler::OMP_MAP_IMPLICIT); 10541 CurInfo.Mappers.push_back(nullptr); 10542 } else { 10543 // If we have any information in the map clause, we use it, otherwise we 10544 // just do a default mapping. 10545 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct); 10546 if (!CI->capturesThis()) 10547 MappedVarSet.insert(CI->getCapturedVar()); 10548 else 10549 MappedVarSet.insert(nullptr); 10550 if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid()) 10551 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo); 10552 // Generate correct mapping for variables captured by reference in 10553 // lambdas. 10554 if (CI->capturesVariable()) 10555 MEHandler.generateInfoForLambdaCaptures(CI->getCapturedVar(), *CV, 10556 CurInfo, LambdaPointers); 10557 } 10558 // We expect to have at least an element of information for this capture. 10559 assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) && 10560 "Non-existing map pointer for capture!"); 10561 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() && 10562 CurInfo.BasePointers.size() == CurInfo.Sizes.size() && 10563 CurInfo.BasePointers.size() == CurInfo.Types.size() && 10564 CurInfo.BasePointers.size() == CurInfo.Mappers.size() && 10565 "Inconsistent map information sizes!"); 10566 10567 // If there is an entry in PartialStruct it means we have a struct with 10568 // individual members mapped. Emit an extra combined entry. 10569 if (PartialStruct.Base.isValid()) { 10570 CombinedInfo.append(PartialStruct.PreliminaryMapData); 10571 MEHandler.emitCombinedEntry( 10572 CombinedInfo, CurInfo.Types, PartialStruct, nullptr, 10573 !PartialStruct.PreliminaryMapData.BasePointers.empty()); 10574 } 10575 10576 // We need to append the results of this capture to what we already have. 10577 CombinedInfo.append(CurInfo); 10578 } 10579 // Adjust MEMBER_OF flags for the lambdas captures. 10580 MEHandler.adjustMemberOfForLambdaCaptures( 10581 LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers, 10582 CombinedInfo.Types); 10583 // Map any list items in a map clause that were not captures because they 10584 // weren't referenced within the construct. 10585 MEHandler.generateAllInfo(CombinedInfo, MappedVarSet); 10586 10587 TargetDataInfo Info; 10588 // Fill up the arrays and create the arguments. 10589 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder); 10590 emitOffloadingArraysArgument( 10591 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 10592 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 10593 {/*ForEndTask=*/false}); 10594 10595 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10596 InputInfo.BasePointersArray = 10597 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10598 InputInfo.PointersArray = 10599 Address(Info.PointersArray, CGM.getPointerAlign()); 10600 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 10601 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 10602 MapTypesArray = Info.MapTypesArray; 10603 MapNamesArray = Info.MapNamesArray; 10604 if (RequiresOuterTask) 10605 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10606 else 10607 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10608 }; 10609 10610 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 10611 CodeGenFunction &CGF, PrePostActionTy &) { 10612 if (RequiresOuterTask) { 10613 CodeGenFunction::OMPTargetDataInfo InputInfo; 10614 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 10615 } else { 10616 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 10617 } 10618 }; 10619 10620 // If we have a target function ID it means that we need to support 10621 // offloading, otherwise, just execute on the host. We need to execute on host 10622 // regardless of the conditional in the if clause if, e.g., the user do not 10623 // specify target triples. 10624 if (OutlinedFnID) { 10625 if (IfCond) { 10626 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 10627 } else { 10628 RegionCodeGenTy ThenRCG(TargetThenGen); 10629 ThenRCG(CGF); 10630 } 10631 } else { 10632 RegionCodeGenTy ElseRCG(TargetElseGen); 10633 ElseRCG(CGF); 10634 } 10635 } 10636 10637 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 10638 StringRef ParentName) { 10639 if (!S) 10640 return; 10641 10642 // Codegen OMP target directives that offload compute to the device. 10643 bool RequiresDeviceCodegen = 10644 isa<OMPExecutableDirective>(S) && 10645 isOpenMPTargetExecutionDirective( 10646 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 10647 10648 if (RequiresDeviceCodegen) { 10649 const auto &E = *cast<OMPExecutableDirective>(S); 10650 unsigned DeviceID; 10651 unsigned FileID; 10652 unsigned Line; 10653 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 10654 FileID, Line); 10655 10656 // Is this a target region that should not be emitted as an entry point? If 10657 // so just signal we are done with this target region. 10658 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 10659 ParentName, Line)) 10660 return; 10661 10662 switch (E.getDirectiveKind()) { 10663 case OMPD_target: 10664 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 10665 cast<OMPTargetDirective>(E)); 10666 break; 10667 case OMPD_target_parallel: 10668 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 10669 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 10670 break; 10671 case OMPD_target_teams: 10672 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 10673 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 10674 break; 10675 case OMPD_target_teams_distribute: 10676 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 10677 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 10678 break; 10679 case OMPD_target_teams_distribute_simd: 10680 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 10681 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 10682 break; 10683 case OMPD_target_parallel_for: 10684 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 10685 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 10686 break; 10687 case OMPD_target_parallel_for_simd: 10688 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 10689 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 10690 break; 10691 case OMPD_target_simd: 10692 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 10693 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 10694 break; 10695 case OMPD_target_teams_distribute_parallel_for: 10696 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 10697 CGM, ParentName, 10698 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 10699 break; 10700 case OMPD_target_teams_distribute_parallel_for_simd: 10701 CodeGenFunction:: 10702 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 10703 CGM, ParentName, 10704 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 10705 break; 10706 case OMPD_parallel: 10707 case OMPD_for: 10708 case OMPD_parallel_for: 10709 case OMPD_parallel_master: 10710 case OMPD_parallel_sections: 10711 case OMPD_for_simd: 10712 case OMPD_parallel_for_simd: 10713 case OMPD_cancel: 10714 case OMPD_cancellation_point: 10715 case OMPD_ordered: 10716 case OMPD_threadprivate: 10717 case OMPD_allocate: 10718 case OMPD_task: 10719 case OMPD_simd: 10720 case OMPD_tile: 10721 case OMPD_unroll: 10722 case OMPD_sections: 10723 case OMPD_section: 10724 case OMPD_single: 10725 case OMPD_master: 10726 case OMPD_critical: 10727 case OMPD_taskyield: 10728 case OMPD_barrier: 10729 case OMPD_taskwait: 10730 case OMPD_taskgroup: 10731 case OMPD_atomic: 10732 case OMPD_flush: 10733 case OMPD_depobj: 10734 case OMPD_scan: 10735 case OMPD_teams: 10736 case OMPD_target_data: 10737 case OMPD_target_exit_data: 10738 case OMPD_target_enter_data: 10739 case OMPD_distribute: 10740 case OMPD_distribute_simd: 10741 case OMPD_distribute_parallel_for: 10742 case OMPD_distribute_parallel_for_simd: 10743 case OMPD_teams_distribute: 10744 case OMPD_teams_distribute_simd: 10745 case OMPD_teams_distribute_parallel_for: 10746 case OMPD_teams_distribute_parallel_for_simd: 10747 case OMPD_target_update: 10748 case OMPD_declare_simd: 10749 case OMPD_declare_variant: 10750 case OMPD_begin_declare_variant: 10751 case OMPD_end_declare_variant: 10752 case OMPD_declare_target: 10753 case OMPD_end_declare_target: 10754 case OMPD_declare_reduction: 10755 case OMPD_declare_mapper: 10756 case OMPD_taskloop: 10757 case OMPD_taskloop_simd: 10758 case OMPD_master_taskloop: 10759 case OMPD_master_taskloop_simd: 10760 case OMPD_parallel_master_taskloop: 10761 case OMPD_parallel_master_taskloop_simd: 10762 case OMPD_requires: 10763 case OMPD_metadirective: 10764 case OMPD_unknown: 10765 default: 10766 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 10767 } 10768 return; 10769 } 10770 10771 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 10772 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 10773 return; 10774 10775 scanForTargetRegionsFunctions(E->getRawStmt(), ParentName); 10776 return; 10777 } 10778 10779 // If this is a lambda function, look into its body. 10780 if (const auto *L = dyn_cast<LambdaExpr>(S)) 10781 S = L->getBody(); 10782 10783 // Keep looking for target regions recursively. 10784 for (const Stmt *II : S->children()) 10785 scanForTargetRegionsFunctions(II, ParentName); 10786 } 10787 10788 static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice) { 10789 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10790 OMPDeclareTargetDeclAttr::getDeviceType(VD); 10791 if (!DevTy) 10792 return false; 10793 // Do not emit device_type(nohost) functions for the host. 10794 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 10795 return true; 10796 // Do not emit device_type(host) functions for the device. 10797 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host) 10798 return true; 10799 return false; 10800 } 10801 10802 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 10803 // If emitting code for the host, we do not process FD here. Instead we do 10804 // the normal code generation. 10805 if (!CGM.getLangOpts().OpenMPIsDevice) { 10806 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) 10807 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD), 10808 CGM.getLangOpts().OpenMPIsDevice)) 10809 return true; 10810 return false; 10811 } 10812 10813 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 10814 // Try to detect target regions in the function. 10815 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 10816 StringRef Name = CGM.getMangledName(GD); 10817 scanForTargetRegionsFunctions(FD->getBody(), Name); 10818 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD), 10819 CGM.getLangOpts().OpenMPIsDevice)) 10820 return true; 10821 } 10822 10823 // Do not to emit function if it is not marked as declare target. 10824 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 10825 AlreadyEmittedTargetDecls.count(VD) == 0; 10826 } 10827 10828 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 10829 if (isAssumedToBeNotEmitted(cast<ValueDecl>(GD.getDecl()), 10830 CGM.getLangOpts().OpenMPIsDevice)) 10831 return true; 10832 10833 if (!CGM.getLangOpts().OpenMPIsDevice) 10834 return false; 10835 10836 // Check if there are Ctors/Dtors in this declaration and look for target 10837 // regions in it. We use the complete variant to produce the kernel name 10838 // mangling. 10839 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 10840 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 10841 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 10842 StringRef ParentName = 10843 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 10844 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 10845 } 10846 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 10847 StringRef ParentName = 10848 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 10849 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 10850 } 10851 } 10852 10853 // Do not to emit variable if it is not marked as declare target. 10854 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10855 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 10856 cast<VarDecl>(GD.getDecl())); 10857 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 10858 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10859 HasRequiresUnifiedSharedMemory)) { 10860 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 10861 return true; 10862 } 10863 return false; 10864 } 10865 10866 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 10867 llvm::Constant *Addr) { 10868 if (CGM.getLangOpts().OMPTargetTriples.empty() && 10869 !CGM.getLangOpts().OpenMPIsDevice) 10870 return; 10871 10872 // If we have host/nohost variables, they do not need to be registered. 10873 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10874 OMPDeclareTargetDeclAttr::getDeviceType(VD); 10875 if (DevTy && DevTy.getValue() != OMPDeclareTargetDeclAttr::DT_Any) 10876 return; 10877 10878 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10879 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10880 if (!Res) { 10881 if (CGM.getLangOpts().OpenMPIsDevice) { 10882 // Register non-target variables being emitted in device code (debug info 10883 // may cause this). 10884 StringRef VarName = CGM.getMangledName(VD); 10885 EmittedNonTargetVariables.try_emplace(VarName, Addr); 10886 } 10887 return; 10888 } 10889 // Register declare target variables. 10890 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 10891 StringRef VarName; 10892 CharUnits VarSize; 10893 llvm::GlobalValue::LinkageTypes Linkage; 10894 10895 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10896 !HasRequiresUnifiedSharedMemory) { 10897 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10898 VarName = CGM.getMangledName(VD); 10899 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 10900 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 10901 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 10902 } else { 10903 VarSize = CharUnits::Zero(); 10904 } 10905 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 10906 // Temp solution to prevent optimizations of the internal variables. 10907 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 10908 // Do not create a "ref-variable" if the original is not also available 10909 // on the host. 10910 if (!OffloadEntriesInfoManager.hasDeviceGlobalVarEntryInfo(VarName)) 10911 return; 10912 std::string RefName = getName({VarName, "ref"}); 10913 if (!CGM.GetGlobalValue(RefName)) { 10914 llvm::Constant *AddrRef = 10915 getOrCreateInternalVariable(Addr->getType(), RefName); 10916 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 10917 GVAddrRef->setConstant(/*Val=*/true); 10918 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 10919 GVAddrRef->setInitializer(Addr); 10920 CGM.addCompilerUsedGlobal(GVAddrRef); 10921 } 10922 } 10923 } else { 10924 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 10925 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10926 HasRequiresUnifiedSharedMemory)) && 10927 "Declare target attribute must link or to with unified memory."); 10928 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 10929 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 10930 else 10931 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10932 10933 if (CGM.getLangOpts().OpenMPIsDevice) { 10934 VarName = Addr->getName(); 10935 Addr = nullptr; 10936 } else { 10937 VarName = getAddrOfDeclareTargetVar(VD).getName(); 10938 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 10939 } 10940 VarSize = CGM.getPointerSize(); 10941 Linkage = llvm::GlobalValue::WeakAnyLinkage; 10942 } 10943 10944 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10945 VarName, Addr, VarSize, Flags, Linkage); 10946 } 10947 10948 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 10949 if (isa<FunctionDecl>(GD.getDecl()) || 10950 isa<OMPDeclareReductionDecl>(GD.getDecl())) 10951 return emitTargetFunctions(GD); 10952 10953 return emitTargetGlobalVariable(GD); 10954 } 10955 10956 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 10957 for (const VarDecl *VD : DeferredGlobalVariables) { 10958 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10959 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10960 if (!Res) 10961 continue; 10962 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10963 !HasRequiresUnifiedSharedMemory) { 10964 CGM.EmitGlobal(VD); 10965 } else { 10966 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 10967 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10968 HasRequiresUnifiedSharedMemory)) && 10969 "Expected link clause or to clause with unified memory."); 10970 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 10971 } 10972 } 10973 } 10974 10975 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 10976 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 10977 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 10978 " Expected target-based directive."); 10979 } 10980 10981 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 10982 for (const OMPClause *Clause : D->clauselists()) { 10983 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 10984 HasRequiresUnifiedSharedMemory = true; 10985 } else if (const auto *AC = 10986 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 10987 switch (AC->getAtomicDefaultMemOrderKind()) { 10988 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 10989 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 10990 break; 10991 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 10992 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 10993 break; 10994 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 10995 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 10996 break; 10997 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 10998 break; 10999 } 11000 } 11001 } 11002 } 11003 11004 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 11005 return RequiresAtomicOrdering; 11006 } 11007 11008 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 11009 LangAS &AS) { 11010 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 11011 return false; 11012 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 11013 switch(A->getAllocatorType()) { 11014 case OMPAllocateDeclAttr::OMPNullMemAlloc: 11015 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 11016 // Not supported, fallback to the default mem space. 11017 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 11018 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 11019 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 11020 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 11021 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 11022 case OMPAllocateDeclAttr::OMPConstMemAlloc: 11023 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 11024 AS = LangAS::Default; 11025 return true; 11026 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 11027 llvm_unreachable("Expected predefined allocator for the variables with the " 11028 "static storage."); 11029 } 11030 return false; 11031 } 11032 11033 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 11034 return HasRequiresUnifiedSharedMemory; 11035 } 11036 11037 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 11038 CodeGenModule &CGM) 11039 : CGM(CGM) { 11040 if (CGM.getLangOpts().OpenMPIsDevice) { 11041 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 11042 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 11043 } 11044 } 11045 11046 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 11047 if (CGM.getLangOpts().OpenMPIsDevice) 11048 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 11049 } 11050 11051 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 11052 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 11053 return true; 11054 11055 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11056 // Do not to emit function if it is marked as declare target as it was already 11057 // emitted. 11058 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 11059 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 11060 if (auto *F = dyn_cast_or_null<llvm::Function>( 11061 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 11062 return !F->isDeclaration(); 11063 return false; 11064 } 11065 return true; 11066 } 11067 11068 return !AlreadyEmittedTargetDecls.insert(D).second; 11069 } 11070 11071 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 11072 // If we don't have entries or if we are emitting code for the device, we 11073 // don't need to do anything. 11074 if (CGM.getLangOpts().OMPTargetTriples.empty() || 11075 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 11076 (OffloadEntriesInfoManager.empty() && 11077 !HasEmittedDeclareTargetRegion && 11078 !HasEmittedTargetRegion)) 11079 return nullptr; 11080 11081 // Create and register the function that handles the requires directives. 11082 ASTContext &C = CGM.getContext(); 11083 11084 llvm::Function *RequiresRegFn; 11085 { 11086 CodeGenFunction CGF(CGM); 11087 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 11088 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 11089 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 11090 RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI); 11091 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 11092 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 11093 // TODO: check for other requires clauses. 11094 // The requires directive takes effect only when a target region is 11095 // present in the compilation unit. Otherwise it is ignored and not 11096 // passed to the runtime. This avoids the runtime from throwing an error 11097 // for mismatching requires clauses across compilation units that don't 11098 // contain at least 1 target region. 11099 assert((HasEmittedTargetRegion || 11100 HasEmittedDeclareTargetRegion || 11101 !OffloadEntriesInfoManager.empty()) && 11102 "Target or declare target region expected."); 11103 if (HasRequiresUnifiedSharedMemory) 11104 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 11105 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 11106 CGM.getModule(), OMPRTL___tgt_register_requires), 11107 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 11108 CGF.FinishFunction(); 11109 } 11110 return RequiresRegFn; 11111 } 11112 11113 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 11114 const OMPExecutableDirective &D, 11115 SourceLocation Loc, 11116 llvm::Function *OutlinedFn, 11117 ArrayRef<llvm::Value *> CapturedVars) { 11118 if (!CGF.HaveInsertPoint()) 11119 return; 11120 11121 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 11122 CodeGenFunction::RunCleanupsScope Scope(CGF); 11123 11124 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 11125 llvm::Value *Args[] = { 11126 RTLoc, 11127 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 11128 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 11129 llvm::SmallVector<llvm::Value *, 16> RealArgs; 11130 RealArgs.append(std::begin(Args), std::end(Args)); 11131 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 11132 11133 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11134 CGM.getModule(), OMPRTL___kmpc_fork_teams); 11135 CGF.EmitRuntimeCall(RTLFn, RealArgs); 11136 } 11137 11138 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11139 const Expr *NumTeams, 11140 const Expr *ThreadLimit, 11141 SourceLocation Loc) { 11142 if (!CGF.HaveInsertPoint()) 11143 return; 11144 11145 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 11146 11147 llvm::Value *NumTeamsVal = 11148 NumTeams 11149 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 11150 CGF.CGM.Int32Ty, /* isSigned = */ true) 11151 : CGF.Builder.getInt32(0); 11152 11153 llvm::Value *ThreadLimitVal = 11154 ThreadLimit 11155 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 11156 CGF.CGM.Int32Ty, /* isSigned = */ true) 11157 : CGF.Builder.getInt32(0); 11158 11159 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 11160 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 11161 ThreadLimitVal}; 11162 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 11163 CGM.getModule(), OMPRTL___kmpc_push_num_teams), 11164 PushNumTeamsArgs); 11165 } 11166 11167 void CGOpenMPRuntime::emitTargetDataCalls( 11168 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11169 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11170 if (!CGF.HaveInsertPoint()) 11171 return; 11172 11173 // Action used to replace the default codegen action and turn privatization 11174 // off. 11175 PrePostActionTy NoPrivAction; 11176 11177 // Generate the code for the opening of the data environment. Capture all the 11178 // arguments of the runtime call by reference because they are used in the 11179 // closing of the region. 11180 auto &&BeginThenGen = [this, &D, Device, &Info, 11181 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 11182 // Fill up the arrays with all the mapped variables. 11183 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 11184 11185 // Get map clause information. 11186 MappableExprsHandler MEHandler(D, CGF); 11187 MEHandler.generateAllInfo(CombinedInfo); 11188 11189 // Fill up the arrays and create the arguments. 11190 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 11191 /*IsNonContiguous=*/true); 11192 11193 llvm::Value *BasePointersArrayArg = nullptr; 11194 llvm::Value *PointersArrayArg = nullptr; 11195 llvm::Value *SizesArrayArg = nullptr; 11196 llvm::Value *MapTypesArrayArg = nullptr; 11197 llvm::Value *MapNamesArrayArg = nullptr; 11198 llvm::Value *MappersArrayArg = nullptr; 11199 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 11200 SizesArrayArg, MapTypesArrayArg, 11201 MapNamesArrayArg, MappersArrayArg, Info); 11202 11203 // Emit device ID if any. 11204 llvm::Value *DeviceID = nullptr; 11205 if (Device) { 11206 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11207 CGF.Int64Ty, /*isSigned=*/true); 11208 } else { 11209 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11210 } 11211 11212 // Emit the number of elements in the offloading arrays. 11213 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 11214 // 11215 // Source location for the ident struct 11216 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11217 11218 llvm::Value *OffloadingArgs[] = {RTLoc, 11219 DeviceID, 11220 PointerNum, 11221 BasePointersArrayArg, 11222 PointersArrayArg, 11223 SizesArrayArg, 11224 MapTypesArrayArg, 11225 MapNamesArrayArg, 11226 MappersArrayArg}; 11227 CGF.EmitRuntimeCall( 11228 OMPBuilder.getOrCreateRuntimeFunction( 11229 CGM.getModule(), OMPRTL___tgt_target_data_begin_mapper), 11230 OffloadingArgs); 11231 11232 // If device pointer privatization is required, emit the body of the region 11233 // here. It will have to be duplicated: with and without privatization. 11234 if (!Info.CaptureDeviceAddrMap.empty()) 11235 CodeGen(CGF); 11236 }; 11237 11238 // Generate code for the closing of the data region. 11239 auto &&EndThenGen = [this, Device, &Info, &D](CodeGenFunction &CGF, 11240 PrePostActionTy &) { 11241 assert(Info.isValid() && "Invalid data environment closing arguments."); 11242 11243 llvm::Value *BasePointersArrayArg = nullptr; 11244 llvm::Value *PointersArrayArg = nullptr; 11245 llvm::Value *SizesArrayArg = nullptr; 11246 llvm::Value *MapTypesArrayArg = nullptr; 11247 llvm::Value *MapNamesArrayArg = nullptr; 11248 llvm::Value *MappersArrayArg = nullptr; 11249 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 11250 SizesArrayArg, MapTypesArrayArg, 11251 MapNamesArrayArg, MappersArrayArg, Info, 11252 {/*ForEndCall=*/true}); 11253 11254 // Emit device ID if any. 11255 llvm::Value *DeviceID = nullptr; 11256 if (Device) { 11257 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11258 CGF.Int64Ty, /*isSigned=*/true); 11259 } else { 11260 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11261 } 11262 11263 // Emit the number of elements in the offloading arrays. 11264 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 11265 11266 // Source location for the ident struct 11267 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11268 11269 llvm::Value *OffloadingArgs[] = {RTLoc, 11270 DeviceID, 11271 PointerNum, 11272 BasePointersArrayArg, 11273 PointersArrayArg, 11274 SizesArrayArg, 11275 MapTypesArrayArg, 11276 MapNamesArrayArg, 11277 MappersArrayArg}; 11278 CGF.EmitRuntimeCall( 11279 OMPBuilder.getOrCreateRuntimeFunction( 11280 CGM.getModule(), OMPRTL___tgt_target_data_end_mapper), 11281 OffloadingArgs); 11282 }; 11283 11284 // If we need device pointer privatization, we need to emit the body of the 11285 // region with no privatization in the 'else' branch of the conditional. 11286 // Otherwise, we don't have to do anything. 11287 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 11288 PrePostActionTy &) { 11289 if (!Info.CaptureDeviceAddrMap.empty()) { 11290 CodeGen.setAction(NoPrivAction); 11291 CodeGen(CGF); 11292 } 11293 }; 11294 11295 // We don't have to do anything to close the region if the if clause evaluates 11296 // to false. 11297 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 11298 11299 if (IfCond) { 11300 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 11301 } else { 11302 RegionCodeGenTy RCG(BeginThenGen); 11303 RCG(CGF); 11304 } 11305 11306 // If we don't require privatization of device pointers, we emit the body in 11307 // between the runtime calls. This avoids duplicating the body code. 11308 if (Info.CaptureDeviceAddrMap.empty()) { 11309 CodeGen.setAction(NoPrivAction); 11310 CodeGen(CGF); 11311 } 11312 11313 if (IfCond) { 11314 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 11315 } else { 11316 RegionCodeGenTy RCG(EndThenGen); 11317 RCG(CGF); 11318 } 11319 } 11320 11321 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 11322 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11323 const Expr *Device) { 11324 if (!CGF.HaveInsertPoint()) 11325 return; 11326 11327 assert((isa<OMPTargetEnterDataDirective>(D) || 11328 isa<OMPTargetExitDataDirective>(D) || 11329 isa<OMPTargetUpdateDirective>(D)) && 11330 "Expecting either target enter, exit data, or update directives."); 11331 11332 CodeGenFunction::OMPTargetDataInfo InputInfo; 11333 llvm::Value *MapTypesArray = nullptr; 11334 llvm::Value *MapNamesArray = nullptr; 11335 // Generate the code for the opening of the data environment. 11336 auto &&ThenGen = [this, &D, Device, &InputInfo, &MapTypesArray, 11337 &MapNamesArray](CodeGenFunction &CGF, PrePostActionTy &) { 11338 // Emit device ID if any. 11339 llvm::Value *DeviceID = nullptr; 11340 if (Device) { 11341 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11342 CGF.Int64Ty, /*isSigned=*/true); 11343 } else { 11344 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11345 } 11346 11347 // Emit the number of elements in the offloading arrays. 11348 llvm::Constant *PointerNum = 11349 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 11350 11351 // Source location for the ident struct 11352 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11353 11354 llvm::Value *OffloadingArgs[] = {RTLoc, 11355 DeviceID, 11356 PointerNum, 11357 InputInfo.BasePointersArray.getPointer(), 11358 InputInfo.PointersArray.getPointer(), 11359 InputInfo.SizesArray.getPointer(), 11360 MapTypesArray, 11361 MapNamesArray, 11362 InputInfo.MappersArray.getPointer()}; 11363 11364 // Select the right runtime function call for each standalone 11365 // directive. 11366 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 11367 RuntimeFunction RTLFn; 11368 switch (D.getDirectiveKind()) { 11369 case OMPD_target_enter_data: 11370 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper 11371 : OMPRTL___tgt_target_data_begin_mapper; 11372 break; 11373 case OMPD_target_exit_data: 11374 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper 11375 : OMPRTL___tgt_target_data_end_mapper; 11376 break; 11377 case OMPD_target_update: 11378 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper 11379 : OMPRTL___tgt_target_data_update_mapper; 11380 break; 11381 case OMPD_parallel: 11382 case OMPD_for: 11383 case OMPD_parallel_for: 11384 case OMPD_parallel_master: 11385 case OMPD_parallel_sections: 11386 case OMPD_for_simd: 11387 case OMPD_parallel_for_simd: 11388 case OMPD_cancel: 11389 case OMPD_cancellation_point: 11390 case OMPD_ordered: 11391 case OMPD_threadprivate: 11392 case OMPD_allocate: 11393 case OMPD_task: 11394 case OMPD_simd: 11395 case OMPD_tile: 11396 case OMPD_unroll: 11397 case OMPD_sections: 11398 case OMPD_section: 11399 case OMPD_single: 11400 case OMPD_master: 11401 case OMPD_critical: 11402 case OMPD_taskyield: 11403 case OMPD_barrier: 11404 case OMPD_taskwait: 11405 case OMPD_taskgroup: 11406 case OMPD_atomic: 11407 case OMPD_flush: 11408 case OMPD_depobj: 11409 case OMPD_scan: 11410 case OMPD_teams: 11411 case OMPD_target_data: 11412 case OMPD_distribute: 11413 case OMPD_distribute_simd: 11414 case OMPD_distribute_parallel_for: 11415 case OMPD_distribute_parallel_for_simd: 11416 case OMPD_teams_distribute: 11417 case OMPD_teams_distribute_simd: 11418 case OMPD_teams_distribute_parallel_for: 11419 case OMPD_teams_distribute_parallel_for_simd: 11420 case OMPD_declare_simd: 11421 case OMPD_declare_variant: 11422 case OMPD_begin_declare_variant: 11423 case OMPD_end_declare_variant: 11424 case OMPD_declare_target: 11425 case OMPD_end_declare_target: 11426 case OMPD_declare_reduction: 11427 case OMPD_declare_mapper: 11428 case OMPD_taskloop: 11429 case OMPD_taskloop_simd: 11430 case OMPD_master_taskloop: 11431 case OMPD_master_taskloop_simd: 11432 case OMPD_parallel_master_taskloop: 11433 case OMPD_parallel_master_taskloop_simd: 11434 case OMPD_target: 11435 case OMPD_target_simd: 11436 case OMPD_target_teams_distribute: 11437 case OMPD_target_teams_distribute_simd: 11438 case OMPD_target_teams_distribute_parallel_for: 11439 case OMPD_target_teams_distribute_parallel_for_simd: 11440 case OMPD_target_teams: 11441 case OMPD_target_parallel: 11442 case OMPD_target_parallel_for: 11443 case OMPD_target_parallel_for_simd: 11444 case OMPD_requires: 11445 case OMPD_metadirective: 11446 case OMPD_unknown: 11447 default: 11448 llvm_unreachable("Unexpected standalone target data directive."); 11449 break; 11450 } 11451 CGF.EmitRuntimeCall( 11452 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), RTLFn), 11453 OffloadingArgs); 11454 }; 11455 11456 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 11457 &MapNamesArray](CodeGenFunction &CGF, 11458 PrePostActionTy &) { 11459 // Fill up the arrays with all the mapped variables. 11460 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 11461 11462 // Get map clause information. 11463 MappableExprsHandler MEHandler(D, CGF); 11464 MEHandler.generateAllInfo(CombinedInfo); 11465 11466 TargetDataInfo Info; 11467 // Fill up the arrays and create the arguments. 11468 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 11469 /*IsNonContiguous=*/true); 11470 bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 11471 D.hasClausesOfKind<OMPNowaitClause>(); 11472 emitOffloadingArraysArgument( 11473 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 11474 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 11475 {/*ForEndTask=*/false}); 11476 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 11477 InputInfo.BasePointersArray = 11478 Address(Info.BasePointersArray, CGM.getPointerAlign()); 11479 InputInfo.PointersArray = 11480 Address(Info.PointersArray, CGM.getPointerAlign()); 11481 InputInfo.SizesArray = 11482 Address(Info.SizesArray, CGM.getPointerAlign()); 11483 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 11484 MapTypesArray = Info.MapTypesArray; 11485 MapNamesArray = Info.MapNamesArray; 11486 if (RequiresOuterTask) 11487 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 11488 else 11489 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 11490 }; 11491 11492 if (IfCond) { 11493 emitIfClause(CGF, IfCond, TargetThenGen, 11494 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 11495 } else { 11496 RegionCodeGenTy ThenRCG(TargetThenGen); 11497 ThenRCG(CGF); 11498 } 11499 } 11500 11501 namespace { 11502 /// Kind of parameter in a function with 'declare simd' directive. 11503 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 11504 /// Attribute set of the parameter. 11505 struct ParamAttrTy { 11506 ParamKindTy Kind = Vector; 11507 llvm::APSInt StrideOrArg; 11508 llvm::APSInt Alignment; 11509 }; 11510 } // namespace 11511 11512 static unsigned evaluateCDTSize(const FunctionDecl *FD, 11513 ArrayRef<ParamAttrTy> ParamAttrs) { 11514 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 11515 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 11516 // of that clause. The VLEN value must be power of 2. 11517 // In other case the notion of the function`s "characteristic data type" (CDT) 11518 // is used to compute the vector length. 11519 // CDT is defined in the following order: 11520 // a) For non-void function, the CDT is the return type. 11521 // b) If the function has any non-uniform, non-linear parameters, then the 11522 // CDT is the type of the first such parameter. 11523 // c) If the CDT determined by a) or b) above is struct, union, or class 11524 // type which is pass-by-value (except for the type that maps to the 11525 // built-in complex data type), the characteristic data type is int. 11526 // d) If none of the above three cases is applicable, the CDT is int. 11527 // The VLEN is then determined based on the CDT and the size of vector 11528 // register of that ISA for which current vector version is generated. The 11529 // VLEN is computed using the formula below: 11530 // VLEN = sizeof(vector_register) / sizeof(CDT), 11531 // where vector register size specified in section 3.2.1 Registers and the 11532 // Stack Frame of original AMD64 ABI document. 11533 QualType RetType = FD->getReturnType(); 11534 if (RetType.isNull()) 11535 return 0; 11536 ASTContext &C = FD->getASTContext(); 11537 QualType CDT; 11538 if (!RetType.isNull() && !RetType->isVoidType()) { 11539 CDT = RetType; 11540 } else { 11541 unsigned Offset = 0; 11542 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 11543 if (ParamAttrs[Offset].Kind == Vector) 11544 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 11545 ++Offset; 11546 } 11547 if (CDT.isNull()) { 11548 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11549 if (ParamAttrs[I + Offset].Kind == Vector) { 11550 CDT = FD->getParamDecl(I)->getType(); 11551 break; 11552 } 11553 } 11554 } 11555 } 11556 if (CDT.isNull()) 11557 CDT = C.IntTy; 11558 CDT = CDT->getCanonicalTypeUnqualified(); 11559 if (CDT->isRecordType() || CDT->isUnionType()) 11560 CDT = C.IntTy; 11561 return C.getTypeSize(CDT); 11562 } 11563 11564 static void 11565 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 11566 const llvm::APSInt &VLENVal, 11567 ArrayRef<ParamAttrTy> ParamAttrs, 11568 OMPDeclareSimdDeclAttr::BranchStateTy State) { 11569 struct ISADataTy { 11570 char ISA; 11571 unsigned VecRegSize; 11572 }; 11573 ISADataTy ISAData[] = { 11574 { 11575 'b', 128 11576 }, // SSE 11577 { 11578 'c', 256 11579 }, // AVX 11580 { 11581 'd', 256 11582 }, // AVX2 11583 { 11584 'e', 512 11585 }, // AVX512 11586 }; 11587 llvm::SmallVector<char, 2> Masked; 11588 switch (State) { 11589 case OMPDeclareSimdDeclAttr::BS_Undefined: 11590 Masked.push_back('N'); 11591 Masked.push_back('M'); 11592 break; 11593 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11594 Masked.push_back('N'); 11595 break; 11596 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11597 Masked.push_back('M'); 11598 break; 11599 } 11600 for (char Mask : Masked) { 11601 for (const ISADataTy &Data : ISAData) { 11602 SmallString<256> Buffer; 11603 llvm::raw_svector_ostream Out(Buffer); 11604 Out << "_ZGV" << Data.ISA << Mask; 11605 if (!VLENVal) { 11606 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 11607 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 11608 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 11609 } else { 11610 Out << VLENVal; 11611 } 11612 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 11613 switch (ParamAttr.Kind){ 11614 case LinearWithVarStride: 11615 Out << 's' << ParamAttr.StrideOrArg; 11616 break; 11617 case Linear: 11618 Out << 'l'; 11619 if (ParamAttr.StrideOrArg != 1) 11620 Out << ParamAttr.StrideOrArg; 11621 break; 11622 case Uniform: 11623 Out << 'u'; 11624 break; 11625 case Vector: 11626 Out << 'v'; 11627 break; 11628 } 11629 if (!!ParamAttr.Alignment) 11630 Out << 'a' << ParamAttr.Alignment; 11631 } 11632 Out << '_' << Fn->getName(); 11633 Fn->addFnAttr(Out.str()); 11634 } 11635 } 11636 } 11637 11638 // This are the Functions that are needed to mangle the name of the 11639 // vector functions generated by the compiler, according to the rules 11640 // defined in the "Vector Function ABI specifications for AArch64", 11641 // available at 11642 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 11643 11644 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 11645 /// 11646 /// TODO: Need to implement the behavior for reference marked with a 11647 /// var or no linear modifiers (1.b in the section). For this, we 11648 /// need to extend ParamKindTy to support the linear modifiers. 11649 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 11650 QT = QT.getCanonicalType(); 11651 11652 if (QT->isVoidType()) 11653 return false; 11654 11655 if (Kind == ParamKindTy::Uniform) 11656 return false; 11657 11658 if (Kind == ParamKindTy::Linear) 11659 return false; 11660 11661 // TODO: Handle linear references with modifiers 11662 11663 if (Kind == ParamKindTy::LinearWithVarStride) 11664 return false; 11665 11666 return true; 11667 } 11668 11669 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 11670 static bool getAArch64PBV(QualType QT, ASTContext &C) { 11671 QT = QT.getCanonicalType(); 11672 unsigned Size = C.getTypeSize(QT); 11673 11674 // Only scalars and complex within 16 bytes wide set PVB to true. 11675 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 11676 return false; 11677 11678 if (QT->isFloatingType()) 11679 return true; 11680 11681 if (QT->isIntegerType()) 11682 return true; 11683 11684 if (QT->isPointerType()) 11685 return true; 11686 11687 // TODO: Add support for complex types (section 3.1.2, item 2). 11688 11689 return false; 11690 } 11691 11692 /// Computes the lane size (LS) of a return type or of an input parameter, 11693 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 11694 /// TODO: Add support for references, section 3.2.1, item 1. 11695 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 11696 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 11697 QualType PTy = QT.getCanonicalType()->getPointeeType(); 11698 if (getAArch64PBV(PTy, C)) 11699 return C.getTypeSize(PTy); 11700 } 11701 if (getAArch64PBV(QT, C)) 11702 return C.getTypeSize(QT); 11703 11704 return C.getTypeSize(C.getUIntPtrType()); 11705 } 11706 11707 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 11708 // signature of the scalar function, as defined in 3.2.2 of the 11709 // AAVFABI. 11710 static std::tuple<unsigned, unsigned, bool> 11711 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 11712 QualType RetType = FD->getReturnType().getCanonicalType(); 11713 11714 ASTContext &C = FD->getASTContext(); 11715 11716 bool OutputBecomesInput = false; 11717 11718 llvm::SmallVector<unsigned, 8> Sizes; 11719 if (!RetType->isVoidType()) { 11720 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 11721 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 11722 OutputBecomesInput = true; 11723 } 11724 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11725 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 11726 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 11727 } 11728 11729 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 11730 // The LS of a function parameter / return value can only be a power 11731 // of 2, starting from 8 bits, up to 128. 11732 assert(std::all_of(Sizes.begin(), Sizes.end(), 11733 [](unsigned Size) { 11734 return Size == 8 || Size == 16 || Size == 32 || 11735 Size == 64 || Size == 128; 11736 }) && 11737 "Invalid size"); 11738 11739 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 11740 *std::max_element(std::begin(Sizes), std::end(Sizes)), 11741 OutputBecomesInput); 11742 } 11743 11744 /// Mangle the parameter part of the vector function name according to 11745 /// their OpenMP classification. The mangling function is defined in 11746 /// section 3.5 of the AAVFABI. 11747 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 11748 SmallString<256> Buffer; 11749 llvm::raw_svector_ostream Out(Buffer); 11750 for (const auto &ParamAttr : ParamAttrs) { 11751 switch (ParamAttr.Kind) { 11752 case LinearWithVarStride: 11753 Out << "ls" << ParamAttr.StrideOrArg; 11754 break; 11755 case Linear: 11756 Out << 'l'; 11757 // Don't print the step value if it is not present or if it is 11758 // equal to 1. 11759 if (ParamAttr.StrideOrArg != 1) 11760 Out << ParamAttr.StrideOrArg; 11761 break; 11762 case Uniform: 11763 Out << 'u'; 11764 break; 11765 case Vector: 11766 Out << 'v'; 11767 break; 11768 } 11769 11770 if (!!ParamAttr.Alignment) 11771 Out << 'a' << ParamAttr.Alignment; 11772 } 11773 11774 return std::string(Out.str()); 11775 } 11776 11777 // Function used to add the attribute. The parameter `VLEN` is 11778 // templated to allow the use of "x" when targeting scalable functions 11779 // for SVE. 11780 template <typename T> 11781 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 11782 char ISA, StringRef ParSeq, 11783 StringRef MangledName, bool OutputBecomesInput, 11784 llvm::Function *Fn) { 11785 SmallString<256> Buffer; 11786 llvm::raw_svector_ostream Out(Buffer); 11787 Out << Prefix << ISA << LMask << VLEN; 11788 if (OutputBecomesInput) 11789 Out << "v"; 11790 Out << ParSeq << "_" << MangledName; 11791 Fn->addFnAttr(Out.str()); 11792 } 11793 11794 // Helper function to generate the Advanced SIMD names depending on 11795 // the value of the NDS when simdlen is not present. 11796 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 11797 StringRef Prefix, char ISA, 11798 StringRef ParSeq, StringRef MangledName, 11799 bool OutputBecomesInput, 11800 llvm::Function *Fn) { 11801 switch (NDS) { 11802 case 8: 11803 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11804 OutputBecomesInput, Fn); 11805 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 11806 OutputBecomesInput, Fn); 11807 break; 11808 case 16: 11809 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11810 OutputBecomesInput, Fn); 11811 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11812 OutputBecomesInput, Fn); 11813 break; 11814 case 32: 11815 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11816 OutputBecomesInput, Fn); 11817 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11818 OutputBecomesInput, Fn); 11819 break; 11820 case 64: 11821 case 128: 11822 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11823 OutputBecomesInput, Fn); 11824 break; 11825 default: 11826 llvm_unreachable("Scalar type is too wide."); 11827 } 11828 } 11829 11830 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 11831 static void emitAArch64DeclareSimdFunction( 11832 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 11833 ArrayRef<ParamAttrTy> ParamAttrs, 11834 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 11835 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 11836 11837 // Get basic data for building the vector signature. 11838 const auto Data = getNDSWDS(FD, ParamAttrs); 11839 const unsigned NDS = std::get<0>(Data); 11840 const unsigned WDS = std::get<1>(Data); 11841 const bool OutputBecomesInput = std::get<2>(Data); 11842 11843 // Check the values provided via `simdlen` by the user. 11844 // 1. A `simdlen(1)` doesn't produce vector signatures, 11845 if (UserVLEN == 1) { 11846 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11847 DiagnosticsEngine::Warning, 11848 "The clause simdlen(1) has no effect when targeting aarch64."); 11849 CGM.getDiags().Report(SLoc, DiagID); 11850 return; 11851 } 11852 11853 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 11854 // Advanced SIMD output. 11855 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 11856 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11857 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 11858 "power of 2 when targeting Advanced SIMD."); 11859 CGM.getDiags().Report(SLoc, DiagID); 11860 return; 11861 } 11862 11863 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 11864 // limits. 11865 if (ISA == 's' && UserVLEN != 0) { 11866 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 11867 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11868 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 11869 "lanes in the architectural constraints " 11870 "for SVE (min is 128-bit, max is " 11871 "2048-bit, by steps of 128-bit)"); 11872 CGM.getDiags().Report(SLoc, DiagID) << WDS; 11873 return; 11874 } 11875 } 11876 11877 // Sort out parameter sequence. 11878 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 11879 StringRef Prefix = "_ZGV"; 11880 // Generate simdlen from user input (if any). 11881 if (UserVLEN) { 11882 if (ISA == 's') { 11883 // SVE generates only a masked function. 11884 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11885 OutputBecomesInput, Fn); 11886 } else { 11887 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11888 // Advanced SIMD generates one or two functions, depending on 11889 // the `[not]inbranch` clause. 11890 switch (State) { 11891 case OMPDeclareSimdDeclAttr::BS_Undefined: 11892 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11893 OutputBecomesInput, Fn); 11894 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11895 OutputBecomesInput, Fn); 11896 break; 11897 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11898 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11899 OutputBecomesInput, Fn); 11900 break; 11901 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11902 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11903 OutputBecomesInput, Fn); 11904 break; 11905 } 11906 } 11907 } else { 11908 // If no user simdlen is provided, follow the AAVFABI rules for 11909 // generating the vector length. 11910 if (ISA == 's') { 11911 // SVE, section 3.4.1, item 1. 11912 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 11913 OutputBecomesInput, Fn); 11914 } else { 11915 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11916 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 11917 // two vector names depending on the use of the clause 11918 // `[not]inbranch`. 11919 switch (State) { 11920 case OMPDeclareSimdDeclAttr::BS_Undefined: 11921 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11922 OutputBecomesInput, Fn); 11923 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11924 OutputBecomesInput, Fn); 11925 break; 11926 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11927 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11928 OutputBecomesInput, Fn); 11929 break; 11930 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11931 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11932 OutputBecomesInput, Fn); 11933 break; 11934 } 11935 } 11936 } 11937 } 11938 11939 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 11940 llvm::Function *Fn) { 11941 ASTContext &C = CGM.getContext(); 11942 FD = FD->getMostRecentDecl(); 11943 // Map params to their positions in function decl. 11944 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 11945 if (isa<CXXMethodDecl>(FD)) 11946 ParamPositions.try_emplace(FD, 0); 11947 unsigned ParamPos = ParamPositions.size(); 11948 for (const ParmVarDecl *P : FD->parameters()) { 11949 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 11950 ++ParamPos; 11951 } 11952 while (FD) { 11953 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 11954 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 11955 // Mark uniform parameters. 11956 for (const Expr *E : Attr->uniforms()) { 11957 E = E->IgnoreParenImpCasts(); 11958 unsigned Pos; 11959 if (isa<CXXThisExpr>(E)) { 11960 Pos = ParamPositions[FD]; 11961 } else { 11962 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11963 ->getCanonicalDecl(); 11964 Pos = ParamPositions[PVD]; 11965 } 11966 ParamAttrs[Pos].Kind = Uniform; 11967 } 11968 // Get alignment info. 11969 auto NI = Attr->alignments_begin(); 11970 for (const Expr *E : Attr->aligneds()) { 11971 E = E->IgnoreParenImpCasts(); 11972 unsigned Pos; 11973 QualType ParmTy; 11974 if (isa<CXXThisExpr>(E)) { 11975 Pos = ParamPositions[FD]; 11976 ParmTy = E->getType(); 11977 } else { 11978 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11979 ->getCanonicalDecl(); 11980 Pos = ParamPositions[PVD]; 11981 ParmTy = PVD->getType(); 11982 } 11983 ParamAttrs[Pos].Alignment = 11984 (*NI) 11985 ? (*NI)->EvaluateKnownConstInt(C) 11986 : llvm::APSInt::getUnsigned( 11987 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 11988 .getQuantity()); 11989 ++NI; 11990 } 11991 // Mark linear parameters. 11992 auto SI = Attr->steps_begin(); 11993 auto MI = Attr->modifiers_begin(); 11994 for (const Expr *E : Attr->linears()) { 11995 E = E->IgnoreParenImpCasts(); 11996 unsigned Pos; 11997 // Rescaling factor needed to compute the linear parameter 11998 // value in the mangled name. 11999 unsigned PtrRescalingFactor = 1; 12000 if (isa<CXXThisExpr>(E)) { 12001 Pos = ParamPositions[FD]; 12002 } else { 12003 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 12004 ->getCanonicalDecl(); 12005 Pos = ParamPositions[PVD]; 12006 if (auto *P = dyn_cast<PointerType>(PVD->getType())) 12007 PtrRescalingFactor = CGM.getContext() 12008 .getTypeSizeInChars(P->getPointeeType()) 12009 .getQuantity(); 12010 } 12011 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 12012 ParamAttr.Kind = Linear; 12013 // Assuming a stride of 1, for `linear` without modifiers. 12014 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1); 12015 if (*SI) { 12016 Expr::EvalResult Result; 12017 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 12018 if (const auto *DRE = 12019 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 12020 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 12021 ParamAttr.Kind = LinearWithVarStride; 12022 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 12023 ParamPositions[StridePVD->getCanonicalDecl()]); 12024 } 12025 } 12026 } else { 12027 ParamAttr.StrideOrArg = Result.Val.getInt(); 12028 } 12029 } 12030 // If we are using a linear clause on a pointer, we need to 12031 // rescale the value of linear_step with the byte size of the 12032 // pointee type. 12033 if (Linear == ParamAttr.Kind) 12034 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor; 12035 ++SI; 12036 ++MI; 12037 } 12038 llvm::APSInt VLENVal; 12039 SourceLocation ExprLoc; 12040 const Expr *VLENExpr = Attr->getSimdlen(); 12041 if (VLENExpr) { 12042 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 12043 ExprLoc = VLENExpr->getExprLoc(); 12044 } 12045 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 12046 if (CGM.getTriple().isX86()) { 12047 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 12048 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 12049 unsigned VLEN = VLENVal.getExtValue(); 12050 StringRef MangledName = Fn->getName(); 12051 if (CGM.getTarget().hasFeature("sve")) 12052 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 12053 MangledName, 's', 128, Fn, ExprLoc); 12054 if (CGM.getTarget().hasFeature("neon")) 12055 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 12056 MangledName, 'n', 128, Fn, ExprLoc); 12057 } 12058 } 12059 FD = FD->getPreviousDecl(); 12060 } 12061 } 12062 12063 namespace { 12064 /// Cleanup action for doacross support. 12065 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 12066 public: 12067 static const int DoacrossFinArgs = 2; 12068 12069 private: 12070 llvm::FunctionCallee RTLFn; 12071 llvm::Value *Args[DoacrossFinArgs]; 12072 12073 public: 12074 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 12075 ArrayRef<llvm::Value *> CallArgs) 12076 : RTLFn(RTLFn) { 12077 assert(CallArgs.size() == DoacrossFinArgs); 12078 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 12079 } 12080 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 12081 if (!CGF.HaveInsertPoint()) 12082 return; 12083 CGF.EmitRuntimeCall(RTLFn, Args); 12084 } 12085 }; 12086 } // namespace 12087 12088 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12089 const OMPLoopDirective &D, 12090 ArrayRef<Expr *> NumIterations) { 12091 if (!CGF.HaveInsertPoint()) 12092 return; 12093 12094 ASTContext &C = CGM.getContext(); 12095 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 12096 RecordDecl *RD; 12097 if (KmpDimTy.isNull()) { 12098 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 12099 // kmp_int64 lo; // lower 12100 // kmp_int64 up; // upper 12101 // kmp_int64 st; // stride 12102 // }; 12103 RD = C.buildImplicitRecord("kmp_dim"); 12104 RD->startDefinition(); 12105 addFieldToRecordDecl(C, RD, Int64Ty); 12106 addFieldToRecordDecl(C, RD, Int64Ty); 12107 addFieldToRecordDecl(C, RD, Int64Ty); 12108 RD->completeDefinition(); 12109 KmpDimTy = C.getRecordType(RD); 12110 } else { 12111 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 12112 } 12113 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 12114 QualType ArrayTy = 12115 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 12116 12117 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 12118 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 12119 enum { LowerFD = 0, UpperFD, StrideFD }; 12120 // Fill dims with data. 12121 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 12122 LValue DimsLVal = CGF.MakeAddrLValue( 12123 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 12124 // dims.upper = num_iterations; 12125 LValue UpperLVal = CGF.EmitLValueForField( 12126 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 12127 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 12128 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(), 12129 Int64Ty, NumIterations[I]->getExprLoc()); 12130 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 12131 // dims.stride = 1; 12132 LValue StrideLVal = CGF.EmitLValueForField( 12133 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 12134 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 12135 StrideLVal); 12136 } 12137 12138 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 12139 // kmp_int32 num_dims, struct kmp_dim * dims); 12140 llvm::Value *Args[] = { 12141 emitUpdateLocation(CGF, D.getBeginLoc()), 12142 getThreadID(CGF, D.getBeginLoc()), 12143 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 12144 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12145 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 12146 CGM.VoidPtrTy)}; 12147 12148 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12149 CGM.getModule(), OMPRTL___kmpc_doacross_init); 12150 CGF.EmitRuntimeCall(RTLFn, Args); 12151 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 12152 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 12153 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12154 CGM.getModule(), OMPRTL___kmpc_doacross_fini); 12155 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 12156 llvm::makeArrayRef(FiniArgs)); 12157 } 12158 12159 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12160 const OMPDependClause *C) { 12161 QualType Int64Ty = 12162 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 12163 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 12164 QualType ArrayTy = CGM.getContext().getConstantArrayType( 12165 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 12166 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 12167 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 12168 const Expr *CounterVal = C->getLoopData(I); 12169 assert(CounterVal); 12170 llvm::Value *CntVal = CGF.EmitScalarConversion( 12171 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 12172 CounterVal->getExprLoc()); 12173 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 12174 /*Volatile=*/false, Int64Ty); 12175 } 12176 llvm::Value *Args[] = { 12177 emitUpdateLocation(CGF, C->getBeginLoc()), 12178 getThreadID(CGF, C->getBeginLoc()), 12179 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 12180 llvm::FunctionCallee RTLFn; 12181 if (C->getDependencyKind() == OMPC_DEPEND_source) { 12182 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 12183 OMPRTL___kmpc_doacross_post); 12184 } else { 12185 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 12186 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 12187 OMPRTL___kmpc_doacross_wait); 12188 } 12189 CGF.EmitRuntimeCall(RTLFn, Args); 12190 } 12191 12192 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 12193 llvm::FunctionCallee Callee, 12194 ArrayRef<llvm::Value *> Args) const { 12195 assert(Loc.isValid() && "Outlined function call location must be valid."); 12196 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 12197 12198 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 12199 if (Fn->doesNotThrow()) { 12200 CGF.EmitNounwindRuntimeCall(Fn, Args); 12201 return; 12202 } 12203 } 12204 CGF.EmitRuntimeCall(Callee, Args); 12205 } 12206 12207 void CGOpenMPRuntime::emitOutlinedFunctionCall( 12208 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 12209 ArrayRef<llvm::Value *> Args) const { 12210 emitCall(CGF, Loc, OutlinedFn, Args); 12211 } 12212 12213 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 12214 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 12215 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 12216 HasEmittedDeclareTargetRegion = true; 12217 } 12218 12219 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 12220 const VarDecl *NativeParam, 12221 const VarDecl *TargetParam) const { 12222 return CGF.GetAddrOfLocalVar(NativeParam); 12223 } 12224 12225 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 12226 const VarDecl *VD) { 12227 if (!VD) 12228 return Address::invalid(); 12229 Address UntiedAddr = Address::invalid(); 12230 Address UntiedRealAddr = Address::invalid(); 12231 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 12232 if (It != FunctionToUntiedTaskStackMap.end()) { 12233 const UntiedLocalVarsAddressesMap &UntiedData = 12234 UntiedLocalVarsStack[It->second]; 12235 auto I = UntiedData.find(VD); 12236 if (I != UntiedData.end()) { 12237 UntiedAddr = I->second.first; 12238 UntiedRealAddr = I->second.second; 12239 } 12240 } 12241 const VarDecl *CVD = VD->getCanonicalDecl(); 12242 if (CVD->hasAttr<OMPAllocateDeclAttr>()) { 12243 // Use the default allocation. 12244 if (!isAllocatableDecl(VD)) 12245 return UntiedAddr; 12246 llvm::Value *Size; 12247 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 12248 if (CVD->getType()->isVariablyModifiedType()) { 12249 Size = CGF.getTypeSize(CVD->getType()); 12250 // Align the size: ((size + align - 1) / align) * align 12251 Size = CGF.Builder.CreateNUWAdd( 12252 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 12253 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 12254 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 12255 } else { 12256 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 12257 Size = CGM.getSize(Sz.alignTo(Align)); 12258 } 12259 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 12260 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 12261 assert(AA->getAllocator() && 12262 "Expected allocator expression for non-default allocator."); 12263 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 12264 // According to the standard, the original allocator type is a enum 12265 // (integer). Convert to pointer type, if required. 12266 Allocator = CGF.EmitScalarConversion( 12267 Allocator, AA->getAllocator()->getType(), CGF.getContext().VoidPtrTy, 12268 AA->getAllocator()->getExprLoc()); 12269 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 12270 12271 llvm::Value *Addr = 12272 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 12273 CGM.getModule(), OMPRTL___kmpc_alloc), 12274 Args, getName({CVD->getName(), ".void.addr"})); 12275 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12276 CGM.getModule(), OMPRTL___kmpc_free); 12277 QualType Ty = CGM.getContext().getPointerType(CVD->getType()); 12278 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12279 Addr, CGF.ConvertTypeForMem(Ty), getName({CVD->getName(), ".addr"})); 12280 if (UntiedAddr.isValid()) 12281 CGF.EmitStoreOfScalar(Addr, UntiedAddr, /*Volatile=*/false, Ty); 12282 12283 // Cleanup action for allocate support. 12284 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 12285 llvm::FunctionCallee RTLFn; 12286 SourceLocation::UIntTy LocEncoding; 12287 Address Addr; 12288 const Expr *Allocator; 12289 12290 public: 12291 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 12292 SourceLocation::UIntTy LocEncoding, Address Addr, 12293 const Expr *Allocator) 12294 : RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr), 12295 Allocator(Allocator) {} 12296 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 12297 if (!CGF.HaveInsertPoint()) 12298 return; 12299 llvm::Value *Args[3]; 12300 Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( 12301 CGF, SourceLocation::getFromRawEncoding(LocEncoding)); 12302 Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12303 Addr.getPointer(), CGF.VoidPtrTy); 12304 llvm::Value *AllocVal = CGF.EmitScalarExpr(Allocator); 12305 // According to the standard, the original allocator type is a enum 12306 // (integer). Convert to pointer type, if required. 12307 AllocVal = CGF.EmitScalarConversion(AllocVal, Allocator->getType(), 12308 CGF.getContext().VoidPtrTy, 12309 Allocator->getExprLoc()); 12310 Args[2] = AllocVal; 12311 12312 CGF.EmitRuntimeCall(RTLFn, Args); 12313 } 12314 }; 12315 Address VDAddr = 12316 UntiedRealAddr.isValid() ? UntiedRealAddr : Address(Addr, Align); 12317 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>( 12318 NormalAndEHCleanup, FiniRTLFn, CVD->getLocation().getRawEncoding(), 12319 VDAddr, AA->getAllocator()); 12320 if (UntiedRealAddr.isValid()) 12321 if (auto *Region = 12322 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 12323 Region->emitUntiedSwitch(CGF); 12324 return VDAddr; 12325 } 12326 return UntiedAddr; 12327 } 12328 12329 bool CGOpenMPRuntime::isLocalVarInUntiedTask(CodeGenFunction &CGF, 12330 const VarDecl *VD) const { 12331 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 12332 if (It == FunctionToUntiedTaskStackMap.end()) 12333 return false; 12334 return UntiedLocalVarsStack[It->second].count(VD) > 0; 12335 } 12336 12337 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 12338 CodeGenModule &CGM, const OMPLoopDirective &S) 12339 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 12340 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12341 if (!NeedToPush) 12342 return; 12343 NontemporalDeclsSet &DS = 12344 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 12345 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 12346 for (const Stmt *Ref : C->private_refs()) { 12347 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 12348 const ValueDecl *VD; 12349 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 12350 VD = DRE->getDecl(); 12351 } else { 12352 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 12353 assert((ME->isImplicitCXXThis() || 12354 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 12355 "Expected member of current class."); 12356 VD = ME->getMemberDecl(); 12357 } 12358 DS.insert(VD); 12359 } 12360 } 12361 } 12362 12363 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 12364 if (!NeedToPush) 12365 return; 12366 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 12367 } 12368 12369 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII( 12370 CodeGenFunction &CGF, 12371 const llvm::MapVector<CanonicalDeclPtr<const VarDecl>, 12372 std::pair<Address, Address>> &LocalVars) 12373 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) { 12374 if (!NeedToPush) 12375 return; 12376 CGM.getOpenMPRuntime().FunctionToUntiedTaskStackMap.try_emplace( 12377 CGF.CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size()); 12378 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars); 12379 } 12380 12381 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::~UntiedTaskLocalDeclsRAII() { 12382 if (!NeedToPush) 12383 return; 12384 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back(); 12385 } 12386 12387 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 12388 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12389 12390 return llvm::any_of( 12391 CGM.getOpenMPRuntime().NontemporalDeclsStack, 12392 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 12393 } 12394 12395 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 12396 const OMPExecutableDirective &S, 12397 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 12398 const { 12399 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 12400 // Vars in target/task regions must be excluded completely. 12401 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 12402 isOpenMPTaskingDirective(S.getDirectiveKind())) { 12403 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12404 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 12405 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 12406 for (const CapturedStmt::Capture &Cap : CS->captures()) { 12407 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 12408 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 12409 } 12410 } 12411 // Exclude vars in private clauses. 12412 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 12413 for (const Expr *Ref : C->varlists()) { 12414 if (!Ref->getType()->isScalarType()) 12415 continue; 12416 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12417 if (!DRE) 12418 continue; 12419 NeedToCheckForLPCs.insert(DRE->getDecl()); 12420 } 12421 } 12422 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 12423 for (const Expr *Ref : C->varlists()) { 12424 if (!Ref->getType()->isScalarType()) 12425 continue; 12426 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12427 if (!DRE) 12428 continue; 12429 NeedToCheckForLPCs.insert(DRE->getDecl()); 12430 } 12431 } 12432 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12433 for (const Expr *Ref : C->varlists()) { 12434 if (!Ref->getType()->isScalarType()) 12435 continue; 12436 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12437 if (!DRE) 12438 continue; 12439 NeedToCheckForLPCs.insert(DRE->getDecl()); 12440 } 12441 } 12442 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 12443 for (const Expr *Ref : C->varlists()) { 12444 if (!Ref->getType()->isScalarType()) 12445 continue; 12446 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12447 if (!DRE) 12448 continue; 12449 NeedToCheckForLPCs.insert(DRE->getDecl()); 12450 } 12451 } 12452 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 12453 for (const Expr *Ref : C->varlists()) { 12454 if (!Ref->getType()->isScalarType()) 12455 continue; 12456 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12457 if (!DRE) 12458 continue; 12459 NeedToCheckForLPCs.insert(DRE->getDecl()); 12460 } 12461 } 12462 for (const Decl *VD : NeedToCheckForLPCs) { 12463 for (const LastprivateConditionalData &Data : 12464 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 12465 if (Data.DeclToUniqueName.count(VD) > 0) { 12466 if (!Data.Disabled) 12467 NeedToAddForLPCsAsDisabled.insert(VD); 12468 break; 12469 } 12470 } 12471 } 12472 } 12473 12474 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12475 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 12476 : CGM(CGF.CGM), 12477 Action((CGM.getLangOpts().OpenMP >= 50 && 12478 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 12479 [](const OMPLastprivateClause *C) { 12480 return C->getKind() == 12481 OMPC_LASTPRIVATE_conditional; 12482 })) 12483 ? ActionToDo::PushAsLastprivateConditional 12484 : ActionToDo::DoNotPush) { 12485 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12486 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 12487 return; 12488 assert(Action == ActionToDo::PushAsLastprivateConditional && 12489 "Expected a push action."); 12490 LastprivateConditionalData &Data = 12491 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12492 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12493 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 12494 continue; 12495 12496 for (const Expr *Ref : C->varlists()) { 12497 Data.DeclToUniqueName.insert(std::make_pair( 12498 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 12499 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 12500 } 12501 } 12502 Data.IVLVal = IVLVal; 12503 Data.Fn = CGF.CurFn; 12504 } 12505 12506 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12507 CodeGenFunction &CGF, const OMPExecutableDirective &S) 12508 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 12509 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12510 if (CGM.getLangOpts().OpenMP < 50) 12511 return; 12512 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 12513 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 12514 if (!NeedToAddForLPCsAsDisabled.empty()) { 12515 Action = ActionToDo::DisableLastprivateConditional; 12516 LastprivateConditionalData &Data = 12517 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12518 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 12519 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 12520 Data.Fn = CGF.CurFn; 12521 Data.Disabled = true; 12522 } 12523 } 12524 12525 CGOpenMPRuntime::LastprivateConditionalRAII 12526 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 12527 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 12528 return LastprivateConditionalRAII(CGF, S); 12529 } 12530 12531 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 12532 if (CGM.getLangOpts().OpenMP < 50) 12533 return; 12534 if (Action == ActionToDo::DisableLastprivateConditional) { 12535 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12536 "Expected list of disabled private vars."); 12537 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12538 } 12539 if (Action == ActionToDo::PushAsLastprivateConditional) { 12540 assert( 12541 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12542 "Expected list of lastprivate conditional vars."); 12543 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12544 } 12545 } 12546 12547 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 12548 const VarDecl *VD) { 12549 ASTContext &C = CGM.getContext(); 12550 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 12551 if (I == LastprivateConditionalToTypes.end()) 12552 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 12553 QualType NewType; 12554 const FieldDecl *VDField; 12555 const FieldDecl *FiredField; 12556 LValue BaseLVal; 12557 auto VI = I->getSecond().find(VD); 12558 if (VI == I->getSecond().end()) { 12559 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 12560 RD->startDefinition(); 12561 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 12562 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 12563 RD->completeDefinition(); 12564 NewType = C.getRecordType(RD); 12565 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 12566 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 12567 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 12568 } else { 12569 NewType = std::get<0>(VI->getSecond()); 12570 VDField = std::get<1>(VI->getSecond()); 12571 FiredField = std::get<2>(VI->getSecond()); 12572 BaseLVal = std::get<3>(VI->getSecond()); 12573 } 12574 LValue FiredLVal = 12575 CGF.EmitLValueForField(BaseLVal, FiredField); 12576 CGF.EmitStoreOfScalar( 12577 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 12578 FiredLVal); 12579 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 12580 } 12581 12582 namespace { 12583 /// Checks if the lastprivate conditional variable is referenced in LHS. 12584 class LastprivateConditionalRefChecker final 12585 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 12586 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 12587 const Expr *FoundE = nullptr; 12588 const Decl *FoundD = nullptr; 12589 StringRef UniqueDeclName; 12590 LValue IVLVal; 12591 llvm::Function *FoundFn = nullptr; 12592 SourceLocation Loc; 12593 12594 public: 12595 bool VisitDeclRefExpr(const DeclRefExpr *E) { 12596 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12597 llvm::reverse(LPM)) { 12598 auto It = D.DeclToUniqueName.find(E->getDecl()); 12599 if (It == D.DeclToUniqueName.end()) 12600 continue; 12601 if (D.Disabled) 12602 return false; 12603 FoundE = E; 12604 FoundD = E->getDecl()->getCanonicalDecl(); 12605 UniqueDeclName = It->second; 12606 IVLVal = D.IVLVal; 12607 FoundFn = D.Fn; 12608 break; 12609 } 12610 return FoundE == E; 12611 } 12612 bool VisitMemberExpr(const MemberExpr *E) { 12613 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 12614 return false; 12615 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12616 llvm::reverse(LPM)) { 12617 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 12618 if (It == D.DeclToUniqueName.end()) 12619 continue; 12620 if (D.Disabled) 12621 return false; 12622 FoundE = E; 12623 FoundD = E->getMemberDecl()->getCanonicalDecl(); 12624 UniqueDeclName = It->second; 12625 IVLVal = D.IVLVal; 12626 FoundFn = D.Fn; 12627 break; 12628 } 12629 return FoundE == E; 12630 } 12631 bool VisitStmt(const Stmt *S) { 12632 for (const Stmt *Child : S->children()) { 12633 if (!Child) 12634 continue; 12635 if (const auto *E = dyn_cast<Expr>(Child)) 12636 if (!E->isGLValue()) 12637 continue; 12638 if (Visit(Child)) 12639 return true; 12640 } 12641 return false; 12642 } 12643 explicit LastprivateConditionalRefChecker( 12644 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 12645 : LPM(LPM) {} 12646 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 12647 getFoundData() const { 12648 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 12649 } 12650 }; 12651 } // namespace 12652 12653 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 12654 LValue IVLVal, 12655 StringRef UniqueDeclName, 12656 LValue LVal, 12657 SourceLocation Loc) { 12658 // Last updated loop counter for the lastprivate conditional var. 12659 // int<xx> last_iv = 0; 12660 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 12661 llvm::Constant *LastIV = 12662 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 12663 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 12664 IVLVal.getAlignment().getAsAlign()); 12665 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 12666 12667 // Last value of the lastprivate conditional. 12668 // decltype(priv_a) last_a; 12669 llvm::Constant *Last = getOrCreateInternalVariable( 12670 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 12671 cast<llvm::GlobalVariable>(Last)->setAlignment( 12672 LVal.getAlignment().getAsAlign()); 12673 LValue LastLVal = 12674 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 12675 12676 // Global loop counter. Required to handle inner parallel-for regions. 12677 // iv 12678 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 12679 12680 // #pragma omp critical(a) 12681 // if (last_iv <= iv) { 12682 // last_iv = iv; 12683 // last_a = priv_a; 12684 // } 12685 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 12686 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 12687 Action.Enter(CGF); 12688 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 12689 // (last_iv <= iv) ? Check if the variable is updated and store new 12690 // value in global var. 12691 llvm::Value *CmpRes; 12692 if (IVLVal.getType()->isSignedIntegerType()) { 12693 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 12694 } else { 12695 assert(IVLVal.getType()->isUnsignedIntegerType() && 12696 "Loop iteration variable must be integer."); 12697 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 12698 } 12699 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 12700 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 12701 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 12702 // { 12703 CGF.EmitBlock(ThenBB); 12704 12705 // last_iv = iv; 12706 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 12707 12708 // last_a = priv_a; 12709 switch (CGF.getEvaluationKind(LVal.getType())) { 12710 case TEK_Scalar: { 12711 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 12712 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 12713 break; 12714 } 12715 case TEK_Complex: { 12716 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 12717 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 12718 break; 12719 } 12720 case TEK_Aggregate: 12721 llvm_unreachable( 12722 "Aggregates are not supported in lastprivate conditional."); 12723 } 12724 // } 12725 CGF.EmitBranch(ExitBB); 12726 // There is no need to emit line number for unconditional branch. 12727 (void)ApplyDebugLocation::CreateEmpty(CGF); 12728 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 12729 }; 12730 12731 if (CGM.getLangOpts().OpenMPSimd) { 12732 // Do not emit as a critical region as no parallel region could be emitted. 12733 RegionCodeGenTy ThenRCG(CodeGen); 12734 ThenRCG(CGF); 12735 } else { 12736 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 12737 } 12738 } 12739 12740 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 12741 const Expr *LHS) { 12742 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12743 return; 12744 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 12745 if (!Checker.Visit(LHS)) 12746 return; 12747 const Expr *FoundE; 12748 const Decl *FoundD; 12749 StringRef UniqueDeclName; 12750 LValue IVLVal; 12751 llvm::Function *FoundFn; 12752 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 12753 Checker.getFoundData(); 12754 if (FoundFn != CGF.CurFn) { 12755 // Special codegen for inner parallel regions. 12756 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 12757 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 12758 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 12759 "Lastprivate conditional is not found in outer region."); 12760 QualType StructTy = std::get<0>(It->getSecond()); 12761 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 12762 LValue PrivLVal = CGF.EmitLValue(FoundE); 12763 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12764 PrivLVal.getAddress(CGF), 12765 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 12766 LValue BaseLVal = 12767 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 12768 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 12769 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 12770 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 12771 FiredLVal, llvm::AtomicOrdering::Unordered, 12772 /*IsVolatile=*/true, /*isInit=*/false); 12773 return; 12774 } 12775 12776 // Private address of the lastprivate conditional in the current context. 12777 // priv_a 12778 LValue LVal = CGF.EmitLValue(FoundE); 12779 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 12780 FoundE->getExprLoc()); 12781 } 12782 12783 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 12784 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12785 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 12786 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12787 return; 12788 auto Range = llvm::reverse(LastprivateConditionalStack); 12789 auto It = llvm::find_if( 12790 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 12791 if (It == Range.end() || It->Fn != CGF.CurFn) 12792 return; 12793 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 12794 assert(LPCI != LastprivateConditionalToTypes.end() && 12795 "Lastprivates must be registered already."); 12796 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12797 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 12798 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 12799 for (const auto &Pair : It->DeclToUniqueName) { 12800 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 12801 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 12802 continue; 12803 auto I = LPCI->getSecond().find(Pair.first); 12804 assert(I != LPCI->getSecond().end() && 12805 "Lastprivate must be rehistered already."); 12806 // bool Cmp = priv_a.Fired != 0; 12807 LValue BaseLVal = std::get<3>(I->getSecond()); 12808 LValue FiredLVal = 12809 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 12810 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 12811 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 12812 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 12813 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 12814 // if (Cmp) { 12815 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 12816 CGF.EmitBlock(ThenBB); 12817 Address Addr = CGF.GetAddrOfLocalVar(VD); 12818 LValue LVal; 12819 if (VD->getType()->isReferenceType()) 12820 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 12821 AlignmentSource::Decl); 12822 else 12823 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 12824 AlignmentSource::Decl); 12825 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 12826 D.getBeginLoc()); 12827 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 12828 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 12829 // } 12830 } 12831 } 12832 12833 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 12834 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 12835 SourceLocation Loc) { 12836 if (CGF.getLangOpts().OpenMP < 50) 12837 return; 12838 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 12839 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 12840 "Unknown lastprivate conditional variable."); 12841 StringRef UniqueName = It->second; 12842 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 12843 // The variable was not updated in the region - exit. 12844 if (!GV) 12845 return; 12846 LValue LPLVal = CGF.MakeAddrLValue( 12847 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 12848 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 12849 CGF.EmitStoreOfScalar(Res, PrivLVal); 12850 } 12851 12852 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 12853 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12854 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12855 llvm_unreachable("Not supported in SIMD-only mode"); 12856 } 12857 12858 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 12859 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12860 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12861 llvm_unreachable("Not supported in SIMD-only mode"); 12862 } 12863 12864 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 12865 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12866 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 12867 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 12868 bool Tied, unsigned &NumberOfParts) { 12869 llvm_unreachable("Not supported in SIMD-only mode"); 12870 } 12871 12872 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 12873 SourceLocation Loc, 12874 llvm::Function *OutlinedFn, 12875 ArrayRef<llvm::Value *> CapturedVars, 12876 const Expr *IfCond) { 12877 llvm_unreachable("Not supported in SIMD-only mode"); 12878 } 12879 12880 void CGOpenMPSIMDRuntime::emitCriticalRegion( 12881 CodeGenFunction &CGF, StringRef CriticalName, 12882 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 12883 const Expr *Hint) { 12884 llvm_unreachable("Not supported in SIMD-only mode"); 12885 } 12886 12887 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 12888 const RegionCodeGenTy &MasterOpGen, 12889 SourceLocation Loc) { 12890 llvm_unreachable("Not supported in SIMD-only mode"); 12891 } 12892 12893 void CGOpenMPSIMDRuntime::emitMaskedRegion(CodeGenFunction &CGF, 12894 const RegionCodeGenTy &MasterOpGen, 12895 SourceLocation Loc, 12896 const Expr *Filter) { 12897 llvm_unreachable("Not supported in SIMD-only mode"); 12898 } 12899 12900 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 12901 SourceLocation Loc) { 12902 llvm_unreachable("Not supported in SIMD-only mode"); 12903 } 12904 12905 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 12906 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 12907 SourceLocation Loc) { 12908 llvm_unreachable("Not supported in SIMD-only mode"); 12909 } 12910 12911 void CGOpenMPSIMDRuntime::emitSingleRegion( 12912 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 12913 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 12914 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 12915 ArrayRef<const Expr *> AssignmentOps) { 12916 llvm_unreachable("Not supported in SIMD-only mode"); 12917 } 12918 12919 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 12920 const RegionCodeGenTy &OrderedOpGen, 12921 SourceLocation Loc, 12922 bool IsThreads) { 12923 llvm_unreachable("Not supported in SIMD-only mode"); 12924 } 12925 12926 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 12927 SourceLocation Loc, 12928 OpenMPDirectiveKind Kind, 12929 bool EmitChecks, 12930 bool ForceSimpleCall) { 12931 llvm_unreachable("Not supported in SIMD-only mode"); 12932 } 12933 12934 void CGOpenMPSIMDRuntime::emitForDispatchInit( 12935 CodeGenFunction &CGF, SourceLocation Loc, 12936 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 12937 bool Ordered, const DispatchRTInput &DispatchValues) { 12938 llvm_unreachable("Not supported in SIMD-only mode"); 12939 } 12940 12941 void CGOpenMPSIMDRuntime::emitForStaticInit( 12942 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 12943 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 12944 llvm_unreachable("Not supported in SIMD-only mode"); 12945 } 12946 12947 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 12948 CodeGenFunction &CGF, SourceLocation Loc, 12949 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 12950 llvm_unreachable("Not supported in SIMD-only mode"); 12951 } 12952 12953 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 12954 SourceLocation Loc, 12955 unsigned IVSize, 12956 bool IVSigned) { 12957 llvm_unreachable("Not supported in SIMD-only mode"); 12958 } 12959 12960 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 12961 SourceLocation Loc, 12962 OpenMPDirectiveKind DKind) { 12963 llvm_unreachable("Not supported in SIMD-only mode"); 12964 } 12965 12966 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 12967 SourceLocation Loc, 12968 unsigned IVSize, bool IVSigned, 12969 Address IL, Address LB, 12970 Address UB, Address ST) { 12971 llvm_unreachable("Not supported in SIMD-only mode"); 12972 } 12973 12974 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 12975 llvm::Value *NumThreads, 12976 SourceLocation Loc) { 12977 llvm_unreachable("Not supported in SIMD-only mode"); 12978 } 12979 12980 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 12981 ProcBindKind ProcBind, 12982 SourceLocation Loc) { 12983 llvm_unreachable("Not supported in SIMD-only mode"); 12984 } 12985 12986 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 12987 const VarDecl *VD, 12988 Address VDAddr, 12989 SourceLocation Loc) { 12990 llvm_unreachable("Not supported in SIMD-only mode"); 12991 } 12992 12993 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 12994 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 12995 CodeGenFunction *CGF) { 12996 llvm_unreachable("Not supported in SIMD-only mode"); 12997 } 12998 12999 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 13000 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 13001 llvm_unreachable("Not supported in SIMD-only mode"); 13002 } 13003 13004 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 13005 ArrayRef<const Expr *> Vars, 13006 SourceLocation Loc, 13007 llvm::AtomicOrdering AO) { 13008 llvm_unreachable("Not supported in SIMD-only mode"); 13009 } 13010 13011 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 13012 const OMPExecutableDirective &D, 13013 llvm::Function *TaskFunction, 13014 QualType SharedsTy, Address Shareds, 13015 const Expr *IfCond, 13016 const OMPTaskDataTy &Data) { 13017 llvm_unreachable("Not supported in SIMD-only mode"); 13018 } 13019 13020 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 13021 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 13022 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 13023 const Expr *IfCond, const OMPTaskDataTy &Data) { 13024 llvm_unreachable("Not supported in SIMD-only mode"); 13025 } 13026 13027 void CGOpenMPSIMDRuntime::emitReduction( 13028 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 13029 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 13030 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 13031 assert(Options.SimpleReduction && "Only simple reduction is expected."); 13032 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 13033 ReductionOps, Options); 13034 } 13035 13036 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 13037 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 13038 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 13039 llvm_unreachable("Not supported in SIMD-only mode"); 13040 } 13041 13042 void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 13043 SourceLocation Loc, 13044 bool IsWorksharingReduction) { 13045 llvm_unreachable("Not supported in SIMD-only mode"); 13046 } 13047 13048 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 13049 SourceLocation Loc, 13050 ReductionCodeGen &RCG, 13051 unsigned N) { 13052 llvm_unreachable("Not supported in SIMD-only mode"); 13053 } 13054 13055 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 13056 SourceLocation Loc, 13057 llvm::Value *ReductionsPtr, 13058 LValue SharedLVal) { 13059 llvm_unreachable("Not supported in SIMD-only mode"); 13060 } 13061 13062 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 13063 SourceLocation Loc) { 13064 llvm_unreachable("Not supported in SIMD-only mode"); 13065 } 13066 13067 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 13068 CodeGenFunction &CGF, SourceLocation Loc, 13069 OpenMPDirectiveKind CancelRegion) { 13070 llvm_unreachable("Not supported in SIMD-only mode"); 13071 } 13072 13073 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 13074 SourceLocation Loc, const Expr *IfCond, 13075 OpenMPDirectiveKind CancelRegion) { 13076 llvm_unreachable("Not supported in SIMD-only mode"); 13077 } 13078 13079 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 13080 const OMPExecutableDirective &D, StringRef ParentName, 13081 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 13082 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 13083 llvm_unreachable("Not supported in SIMD-only mode"); 13084 } 13085 13086 void CGOpenMPSIMDRuntime::emitTargetCall( 13087 CodeGenFunction &CGF, const OMPExecutableDirective &D, 13088 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 13089 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 13090 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 13091 const OMPLoopDirective &D)> 13092 SizeEmitter) { 13093 llvm_unreachable("Not supported in SIMD-only mode"); 13094 } 13095 13096 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 13097 llvm_unreachable("Not supported in SIMD-only mode"); 13098 } 13099 13100 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 13101 llvm_unreachable("Not supported in SIMD-only mode"); 13102 } 13103 13104 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 13105 return false; 13106 } 13107 13108 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 13109 const OMPExecutableDirective &D, 13110 SourceLocation Loc, 13111 llvm::Function *OutlinedFn, 13112 ArrayRef<llvm::Value *> CapturedVars) { 13113 llvm_unreachable("Not supported in SIMD-only mode"); 13114 } 13115 13116 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 13117 const Expr *NumTeams, 13118 const Expr *ThreadLimit, 13119 SourceLocation Loc) { 13120 llvm_unreachable("Not supported in SIMD-only mode"); 13121 } 13122 13123 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 13124 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 13125 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 13126 llvm_unreachable("Not supported in SIMD-only mode"); 13127 } 13128 13129 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 13130 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 13131 const Expr *Device) { 13132 llvm_unreachable("Not supported in SIMD-only mode"); 13133 } 13134 13135 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 13136 const OMPLoopDirective &D, 13137 ArrayRef<Expr *> NumIterations) { 13138 llvm_unreachable("Not supported in SIMD-only mode"); 13139 } 13140 13141 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 13142 const OMPDependClause *C) { 13143 llvm_unreachable("Not supported in SIMD-only mode"); 13144 } 13145 13146 const VarDecl * 13147 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 13148 const VarDecl *NativeParam) const { 13149 llvm_unreachable("Not supported in SIMD-only mode"); 13150 } 13151 13152 Address 13153 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 13154 const VarDecl *NativeParam, 13155 const VarDecl *TargetParam) const { 13156 llvm_unreachable("Not supported in SIMD-only mode"); 13157 } 13158