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 llvm::Value *getExprTypeSize(const Expr *E) const { 7485 QualType ExprTy = E->getType().getCanonicalType(); 7486 7487 // Calculate the size for array shaping expression. 7488 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) { 7489 llvm::Value *Size = 7490 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType()); 7491 for (const Expr *SE : OAE->getDimensions()) { 7492 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 7493 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 7494 CGF.getContext().getSizeType(), 7495 SE->getExprLoc()); 7496 Size = CGF.Builder.CreateNUWMul(Size, Sz); 7497 } 7498 return Size; 7499 } 7500 7501 // Reference types are ignored for mapping purposes. 7502 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7503 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7504 7505 // Given that an array section is considered a built-in type, we need to 7506 // do the calculation based on the length of the section instead of relying 7507 // on CGF.getTypeSize(E->getType()). 7508 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7509 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7510 OAE->getBase()->IgnoreParenImpCasts()) 7511 .getCanonicalType(); 7512 7513 // If there is no length associated with the expression and lower bound is 7514 // not specified too, that means we are using the whole length of the 7515 // base. 7516 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7517 !OAE->getLowerBound()) 7518 return CGF.getTypeSize(BaseTy); 7519 7520 llvm::Value *ElemSize; 7521 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7522 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7523 } else { 7524 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7525 assert(ATy && "Expecting array type if not a pointer type."); 7526 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7527 } 7528 7529 // If we don't have a length at this point, that is because we have an 7530 // array section with a single element. 7531 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid()) 7532 return ElemSize; 7533 7534 if (const Expr *LenExpr = OAE->getLength()) { 7535 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7536 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7537 CGF.getContext().getSizeType(), 7538 LenExpr->getExprLoc()); 7539 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7540 } 7541 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7542 OAE->getLowerBound() && "expected array_section[lb:]."); 7543 // Size = sizetype - lb * elemtype; 7544 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7545 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7546 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7547 CGF.getContext().getSizeType(), 7548 OAE->getLowerBound()->getExprLoc()); 7549 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7550 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7551 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7552 LengthVal = CGF.Builder.CreateSelect( 7553 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7554 return LengthVal; 7555 } 7556 return CGF.getTypeSize(ExprTy); 7557 } 7558 7559 /// Return the corresponding bits for a given map clause modifier. Add 7560 /// a flag marking the map as a pointer if requested. Add a flag marking the 7561 /// map as the first one of a series of maps that relate to the same map 7562 /// expression. 7563 OpenMPOffloadMappingFlags getMapTypeBits( 7564 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7565 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit, 7566 bool AddPtrFlag, bool AddIsTargetParamFlag, bool IsNonContiguous) const { 7567 OpenMPOffloadMappingFlags Bits = 7568 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7569 switch (MapType) { 7570 case OMPC_MAP_alloc: 7571 case OMPC_MAP_release: 7572 // alloc and release is the default behavior in the runtime library, i.e. 7573 // if we don't pass any bits alloc/release that is what the runtime is 7574 // going to do. Therefore, we don't need to signal anything for these two 7575 // type modifiers. 7576 break; 7577 case OMPC_MAP_to: 7578 Bits |= OMP_MAP_TO; 7579 break; 7580 case OMPC_MAP_from: 7581 Bits |= OMP_MAP_FROM; 7582 break; 7583 case OMPC_MAP_tofrom: 7584 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7585 break; 7586 case OMPC_MAP_delete: 7587 Bits |= OMP_MAP_DELETE; 7588 break; 7589 case OMPC_MAP_unknown: 7590 llvm_unreachable("Unexpected map type!"); 7591 } 7592 if (AddPtrFlag) 7593 Bits |= OMP_MAP_PTR_AND_OBJ; 7594 if (AddIsTargetParamFlag) 7595 Bits |= OMP_MAP_TARGET_PARAM; 7596 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7597 != MapModifiers.end()) 7598 Bits |= OMP_MAP_ALWAYS; 7599 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7600 != MapModifiers.end()) 7601 Bits |= OMP_MAP_CLOSE; 7602 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_present) != 7603 MapModifiers.end() || 7604 llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present) != 7605 MotionModifiers.end()) 7606 Bits |= OMP_MAP_PRESENT; 7607 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_ompx_hold) != 7608 MapModifiers.end()) 7609 Bits |= OMP_MAP_OMPX_HOLD; 7610 if (IsNonContiguous) 7611 Bits |= OMP_MAP_NON_CONTIG; 7612 return Bits; 7613 } 7614 7615 /// Return true if the provided expression is a final array section. A 7616 /// final array section, is one whose length can't be proved to be one. 7617 bool isFinalArraySectionExpression(const Expr *E) const { 7618 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7619 7620 // It is not an array section and therefore not a unity-size one. 7621 if (!OASE) 7622 return false; 7623 7624 // An array section with no colon always refer to a single element. 7625 if (OASE->getColonLocFirst().isInvalid()) 7626 return false; 7627 7628 const Expr *Length = OASE->getLength(); 7629 7630 // If we don't have a length we have to check if the array has size 1 7631 // for this dimension. Also, we should always expect a length if the 7632 // base type is pointer. 7633 if (!Length) { 7634 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7635 OASE->getBase()->IgnoreParenImpCasts()) 7636 .getCanonicalType(); 7637 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7638 return ATy->getSize().getSExtValue() != 1; 7639 // If we don't have a constant dimension length, we have to consider 7640 // the current section as having any size, so it is not necessarily 7641 // unitary. If it happen to be unity size, that's user fault. 7642 return true; 7643 } 7644 7645 // Check if the length evaluates to 1. 7646 Expr::EvalResult Result; 7647 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7648 return true; // Can have more that size 1. 7649 7650 llvm::APSInt ConstLength = Result.Val.getInt(); 7651 return ConstLength.getSExtValue() != 1; 7652 } 7653 7654 /// Generate the base pointers, section pointers, sizes, map type bits, and 7655 /// user-defined mappers (all included in \a CombinedInfo) for the provided 7656 /// map type, map or motion modifiers, and expression components. 7657 /// \a IsFirstComponent should be set to true if the provided set of 7658 /// components is the first associated with a capture. 7659 void generateInfoForComponentList( 7660 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7661 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7662 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7663 MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct, 7664 bool IsFirstComponentList, bool IsImplicit, 7665 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false, 7666 const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr, 7667 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7668 OverlappedElements = llvm::None) const { 7669 // The following summarizes what has to be generated for each map and the 7670 // types below. The generated information is expressed in this order: 7671 // base pointer, section pointer, size, flags 7672 // (to add to the ones that come from the map type and modifier). 7673 // 7674 // double d; 7675 // int i[100]; 7676 // float *p; 7677 // 7678 // struct S1 { 7679 // int i; 7680 // float f[50]; 7681 // } 7682 // struct S2 { 7683 // int i; 7684 // float f[50]; 7685 // S1 s; 7686 // double *p; 7687 // struct S2 *ps; 7688 // int &ref; 7689 // } 7690 // S2 s; 7691 // S2 *ps; 7692 // 7693 // map(d) 7694 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7695 // 7696 // map(i) 7697 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7698 // 7699 // map(i[1:23]) 7700 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7701 // 7702 // map(p) 7703 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7704 // 7705 // map(p[1:24]) 7706 // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ 7707 // in unified shared memory mode or for local pointers 7708 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7709 // 7710 // map(s) 7711 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7712 // 7713 // map(s.i) 7714 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7715 // 7716 // map(s.s.f) 7717 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7718 // 7719 // map(s.p) 7720 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7721 // 7722 // map(to: s.p[:22]) 7723 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7724 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7725 // &(s.p), &(s.p[0]), 22*sizeof(double), 7726 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7727 // (*) alloc space for struct members, only this is a target parameter 7728 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7729 // optimizes this entry out, same in the examples below) 7730 // (***) map the pointee (map: to) 7731 // 7732 // map(to: s.ref) 7733 // &s, &(s.ref), sizeof(int*), TARGET_PARAM (*) 7734 // &s, &(s.ref), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7735 // (*) alloc space for struct members, only this is a target parameter 7736 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7737 // optimizes this entry out, same in the examples below) 7738 // (***) map the pointee (map: to) 7739 // 7740 // map(s.ps) 7741 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7742 // 7743 // map(from: s.ps->s.i) 7744 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7745 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7746 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7747 // 7748 // map(to: s.ps->ps) 7749 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7750 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7751 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7752 // 7753 // map(s.ps->ps->ps) 7754 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7755 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7756 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7757 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7758 // 7759 // map(to: s.ps->ps->s.f[:22]) 7760 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7761 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7762 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7763 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7764 // 7765 // map(ps) 7766 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7767 // 7768 // map(ps->i) 7769 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7770 // 7771 // map(ps->s.f) 7772 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7773 // 7774 // map(from: ps->p) 7775 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7776 // 7777 // map(to: ps->p[:22]) 7778 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7779 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7780 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7781 // 7782 // map(ps->ps) 7783 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7784 // 7785 // map(from: ps->ps->s.i) 7786 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7787 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7788 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7789 // 7790 // map(from: ps->ps->ps) 7791 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7792 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7793 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7794 // 7795 // map(ps->ps->ps->ps) 7796 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7797 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7798 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7799 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7800 // 7801 // map(to: ps->ps->ps->s.f[:22]) 7802 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7803 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7804 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7805 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7806 // 7807 // map(to: s.f[:22]) map(from: s.p[:33]) 7808 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7809 // sizeof(double*) (**), TARGET_PARAM 7810 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7811 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7812 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7813 // (*) allocate contiguous space needed to fit all mapped members even if 7814 // we allocate space for members not mapped (in this example, 7815 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7816 // them as well because they fall between &s.f[0] and &s.p) 7817 // 7818 // map(from: s.f[:22]) map(to: ps->p[:33]) 7819 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7820 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7821 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7822 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7823 // (*) the struct this entry pertains to is the 2nd element in the list of 7824 // arguments, hence MEMBER_OF(2) 7825 // 7826 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7827 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7828 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7829 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7830 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7831 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7832 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7833 // (*) the struct this entry pertains to is the 4th element in the list 7834 // of arguments, hence MEMBER_OF(4) 7835 7836 // Track if the map information being generated is the first for a capture. 7837 bool IsCaptureFirstInfo = IsFirstComponentList; 7838 // When the variable is on a declare target link or in a to clause with 7839 // unified memory, a reference is needed to hold the host/device address 7840 // of the variable. 7841 bool RequiresReference = false; 7842 7843 // Scan the components from the base to the complete expression. 7844 auto CI = Components.rbegin(); 7845 auto CE = Components.rend(); 7846 auto I = CI; 7847 7848 // Track if the map information being generated is the first for a list of 7849 // components. 7850 bool IsExpressionFirstInfo = true; 7851 bool FirstPointerInComplexData = false; 7852 Address BP = Address::invalid(); 7853 const Expr *AssocExpr = I->getAssociatedExpression(); 7854 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7855 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7856 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr); 7857 7858 if (isa<MemberExpr>(AssocExpr)) { 7859 // The base is the 'this' pointer. The content of the pointer is going 7860 // to be the base of the field being mapped. 7861 BP = CGF.LoadCXXThisAddress(); 7862 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7863 (OASE && 7864 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7865 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7866 } else if (OAShE && 7867 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) { 7868 BP = Address( 7869 CGF.EmitScalarExpr(OAShE->getBase()), 7870 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType())); 7871 } else { 7872 // The base is the reference to the variable. 7873 // BP = &Var. 7874 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7875 if (const auto *VD = 7876 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7877 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7878 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7879 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7880 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7881 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7882 RequiresReference = true; 7883 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7884 } 7885 } 7886 } 7887 7888 // If the variable is a pointer and is being dereferenced (i.e. is not 7889 // the last component), the base has to be the pointer itself, not its 7890 // reference. References are ignored for mapping purposes. 7891 QualType Ty = 7892 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7893 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7894 // No need to generate individual map information for the pointer, it 7895 // can be associated with the combined storage if shared memory mode is 7896 // active or the base declaration is not global variable. 7897 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration()); 7898 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 7899 !VD || VD->hasLocalStorage()) 7900 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7901 else 7902 FirstPointerInComplexData = true; 7903 ++I; 7904 } 7905 } 7906 7907 // Track whether a component of the list should be marked as MEMBER_OF some 7908 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7909 // in a component list should be marked as MEMBER_OF, all subsequent entries 7910 // do not belong to the base struct. E.g. 7911 // struct S2 s; 7912 // s.ps->ps->ps->f[:] 7913 // (1) (2) (3) (4) 7914 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7915 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7916 // is the pointee of ps(2) which is not member of struct s, so it should not 7917 // be marked as such (it is still PTR_AND_OBJ). 7918 // The variable is initialized to false so that PTR_AND_OBJ entries which 7919 // are not struct members are not considered (e.g. array of pointers to 7920 // data). 7921 bool ShouldBeMemberOf = false; 7922 7923 // Variable keeping track of whether or not we have encountered a component 7924 // in the component list which is a member expression. Useful when we have a 7925 // pointer or a final array section, in which case it is the previous 7926 // component in the list which tells us whether we have a member expression. 7927 // E.g. X.f[:] 7928 // While processing the final array section "[:]" it is "f" which tells us 7929 // whether we are dealing with a member of a declared struct. 7930 const MemberExpr *EncounteredME = nullptr; 7931 7932 // Track for the total number of dimension. Start from one for the dummy 7933 // dimension. 7934 uint64_t DimSize = 1; 7935 7936 bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous; 7937 bool IsPrevMemberReference = false; 7938 7939 for (; I != CE; ++I) { 7940 // If the current component is member of a struct (parent struct) mark it. 7941 if (!EncounteredME) { 7942 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7943 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7944 // as MEMBER_OF the parent struct. 7945 if (EncounteredME) { 7946 ShouldBeMemberOf = true; 7947 // Do not emit as complex pointer if this is actually not array-like 7948 // expression. 7949 if (FirstPointerInComplexData) { 7950 QualType Ty = std::prev(I) 7951 ->getAssociatedDeclaration() 7952 ->getType() 7953 .getNonReferenceType(); 7954 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7955 FirstPointerInComplexData = false; 7956 } 7957 } 7958 } 7959 7960 auto Next = std::next(I); 7961 7962 // We need to generate the addresses and sizes if this is the last 7963 // component, if the component is a pointer or if it is an array section 7964 // whose length can't be proved to be one. If this is a pointer, it 7965 // becomes the base address for the following components. 7966 7967 // A final array section, is one whose length can't be proved to be one. 7968 // If the map item is non-contiguous then we don't treat any array section 7969 // as final array section. 7970 bool IsFinalArraySection = 7971 !IsNonContiguous && 7972 isFinalArraySectionExpression(I->getAssociatedExpression()); 7973 7974 // If we have a declaration for the mapping use that, otherwise use 7975 // the base declaration of the map clause. 7976 const ValueDecl *MapDecl = (I->getAssociatedDeclaration()) 7977 ? I->getAssociatedDeclaration() 7978 : BaseDecl; 7979 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression() 7980 : MapExpr; 7981 7982 // Get information on whether the element is a pointer. Have to do a 7983 // special treatment for array sections given that they are built-in 7984 // types. 7985 const auto *OASE = 7986 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7987 const auto *OAShE = 7988 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression()); 7989 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 7990 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 7991 bool IsPointer = 7992 OAShE || 7993 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7994 .getCanonicalType() 7995 ->isAnyPointerType()) || 7996 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7997 bool IsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) && 7998 MapDecl && 7999 MapDecl->getType()->isLValueReferenceType(); 8000 bool IsNonDerefPointer = IsPointer && !UO && !BO && !IsNonContiguous; 8001 8002 if (OASE) 8003 ++DimSize; 8004 8005 if (Next == CE || IsMemberReference || IsNonDerefPointer || 8006 IsFinalArraySection) { 8007 // If this is not the last component, we expect the pointer to be 8008 // associated with an array expression or member expression. 8009 assert((Next == CE || 8010 isa<MemberExpr>(Next->getAssociatedExpression()) || 8011 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 8012 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 8013 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || 8014 isa<UnaryOperator>(Next->getAssociatedExpression()) || 8015 isa<BinaryOperator>(Next->getAssociatedExpression())) && 8016 "Unexpected expression"); 8017 8018 Address LB = Address::invalid(); 8019 Address LowestElem = Address::invalid(); 8020 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF, 8021 const MemberExpr *E) { 8022 const Expr *BaseExpr = E->getBase(); 8023 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a 8024 // scalar. 8025 LValue BaseLV; 8026 if (E->isArrow()) { 8027 LValueBaseInfo BaseInfo; 8028 TBAAAccessInfo TBAAInfo; 8029 Address Addr = 8030 CGF.EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo); 8031 QualType PtrTy = BaseExpr->getType()->getPointeeType(); 8032 BaseLV = CGF.MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); 8033 } else { 8034 BaseLV = CGF.EmitOMPSharedLValue(BaseExpr); 8035 } 8036 return BaseLV; 8037 }; 8038 if (OAShE) { 8039 LowestElem = LB = Address(CGF.EmitScalarExpr(OAShE->getBase()), 8040 CGF.getContext().getTypeAlignInChars( 8041 OAShE->getBase()->getType())); 8042 } else if (IsMemberReference) { 8043 const auto *ME = cast<MemberExpr>(I->getAssociatedExpression()); 8044 LValue BaseLVal = EmitMemberExprBase(CGF, ME); 8045 LowestElem = CGF.EmitLValueForFieldInitialization( 8046 BaseLVal, cast<FieldDecl>(MapDecl)) 8047 .getAddress(CGF); 8048 LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType()) 8049 .getAddress(CGF); 8050 } else { 8051 LowestElem = LB = 8052 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 8053 .getAddress(CGF); 8054 } 8055 8056 // If this component is a pointer inside the base struct then we don't 8057 // need to create any entry for it - it will be combined with the object 8058 // it is pointing to into a single PTR_AND_OBJ entry. 8059 bool IsMemberPointerOrAddr = 8060 EncounteredME && 8061 (((IsPointer || ForDeviceAddr) && 8062 I->getAssociatedExpression() == EncounteredME) || 8063 (IsPrevMemberReference && !IsPointer) || 8064 (IsMemberReference && Next != CE && 8065 !Next->getAssociatedExpression()->getType()->isPointerType())); 8066 if (!OverlappedElements.empty() && Next == CE) { 8067 // Handle base element with the info for overlapped elements. 8068 assert(!PartialStruct.Base.isValid() && "The base element is set."); 8069 assert(!IsPointer && 8070 "Unexpected base element with the pointer type."); 8071 // Mark the whole struct as the struct that requires allocation on the 8072 // device. 8073 PartialStruct.LowestElem = {0, LowestElem}; 8074 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 8075 I->getAssociatedExpression()->getType()); 8076 Address HB = CGF.Builder.CreateConstGEP( 8077 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LowestElem, 8078 CGF.VoidPtrTy), 8079 TypeSize.getQuantity() - 1); 8080 PartialStruct.HighestElem = { 8081 std::numeric_limits<decltype( 8082 PartialStruct.HighestElem.first)>::max(), 8083 HB}; 8084 PartialStruct.Base = BP; 8085 PartialStruct.LB = LB; 8086 assert( 8087 PartialStruct.PreliminaryMapData.BasePointers.empty() && 8088 "Overlapped elements must be used only once for the variable."); 8089 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo); 8090 // Emit data for non-overlapped data. 8091 OpenMPOffloadMappingFlags Flags = 8092 OMP_MAP_MEMBER_OF | 8093 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, 8094 /*AddPtrFlag=*/false, 8095 /*AddIsTargetParamFlag=*/false, IsNonContiguous); 8096 llvm::Value *Size = nullptr; 8097 // Do bitcopy of all non-overlapped structure elements. 8098 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 8099 Component : OverlappedElements) { 8100 Address ComponentLB = Address::invalid(); 8101 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 8102 Component) { 8103 if (const ValueDecl *VD = MC.getAssociatedDeclaration()) { 8104 const auto *FD = dyn_cast<FieldDecl>(VD); 8105 if (FD && FD->getType()->isLValueReferenceType()) { 8106 const auto *ME = 8107 cast<MemberExpr>(MC.getAssociatedExpression()); 8108 LValue BaseLVal = EmitMemberExprBase(CGF, ME); 8109 ComponentLB = 8110 CGF.EmitLValueForFieldInitialization(BaseLVal, FD) 8111 .getAddress(CGF); 8112 } else { 8113 ComponentLB = 8114 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 8115 .getAddress(CGF); 8116 } 8117 Size = CGF.Builder.CreatePtrDiff( 8118 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 8119 CGF.EmitCastToVoidPtr(LB.getPointer())); 8120 break; 8121 } 8122 } 8123 assert(Size && "Failed to determine structure size"); 8124 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8125 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8126 CombinedInfo.Pointers.push_back(LB.getPointer()); 8127 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8128 Size, CGF.Int64Ty, /*isSigned=*/true)); 8129 CombinedInfo.Types.push_back(Flags); 8130 CombinedInfo.Mappers.push_back(nullptr); 8131 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8132 : 1); 8133 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 8134 } 8135 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8136 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8137 CombinedInfo.Pointers.push_back(LB.getPointer()); 8138 Size = CGF.Builder.CreatePtrDiff( 8139 CGF.Builder.CreateConstGEP(HB, 1).getPointer(), 8140 CGF.EmitCastToVoidPtr(LB.getPointer())); 8141 CombinedInfo.Sizes.push_back( 8142 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8143 CombinedInfo.Types.push_back(Flags); 8144 CombinedInfo.Mappers.push_back(nullptr); 8145 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8146 : 1); 8147 break; 8148 } 8149 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 8150 if (!IsMemberPointerOrAddr || 8151 (Next == CE && MapType != OMPC_MAP_unknown)) { 8152 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8153 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8154 CombinedInfo.Pointers.push_back(LB.getPointer()); 8155 CombinedInfo.Sizes.push_back( 8156 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8157 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8158 : 1); 8159 8160 // If Mapper is valid, the last component inherits the mapper. 8161 bool HasMapper = Mapper && Next == CE; 8162 CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr); 8163 8164 // We need to add a pointer flag for each map that comes from the 8165 // same expression except for the first one. We also need to signal 8166 // this map is the first one that relates with the current capture 8167 // (there is a set of entries for each capture). 8168 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 8169 MapType, MapModifiers, MotionModifiers, IsImplicit, 8170 !IsExpressionFirstInfo || RequiresReference || 8171 FirstPointerInComplexData || IsMemberReference, 8172 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous); 8173 8174 if (!IsExpressionFirstInfo || IsMemberReference) { 8175 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 8176 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 8177 if (IsPointer || (IsMemberReference && Next != CE)) 8178 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 8179 OMP_MAP_DELETE | OMP_MAP_CLOSE); 8180 8181 if (ShouldBeMemberOf) { 8182 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 8183 // should be later updated with the correct value of MEMBER_OF. 8184 Flags |= OMP_MAP_MEMBER_OF; 8185 // From now on, all subsequent PTR_AND_OBJ entries should not be 8186 // marked as MEMBER_OF. 8187 ShouldBeMemberOf = false; 8188 } 8189 } 8190 8191 CombinedInfo.Types.push_back(Flags); 8192 } 8193 8194 // If we have encountered a member expression so far, keep track of the 8195 // mapped member. If the parent is "*this", then the value declaration 8196 // is nullptr. 8197 if (EncounteredME) { 8198 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 8199 unsigned FieldIndex = FD->getFieldIndex(); 8200 8201 // Update info about the lowest and highest elements for this struct 8202 if (!PartialStruct.Base.isValid()) { 8203 PartialStruct.LowestElem = {FieldIndex, LowestElem}; 8204 if (IsFinalArraySection) { 8205 Address HB = 8206 CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false) 8207 .getAddress(CGF); 8208 PartialStruct.HighestElem = {FieldIndex, HB}; 8209 } else { 8210 PartialStruct.HighestElem = {FieldIndex, LowestElem}; 8211 } 8212 PartialStruct.Base = BP; 8213 PartialStruct.LB = BP; 8214 } else if (FieldIndex < PartialStruct.LowestElem.first) { 8215 PartialStruct.LowestElem = {FieldIndex, LowestElem}; 8216 } else if (FieldIndex > PartialStruct.HighestElem.first) { 8217 PartialStruct.HighestElem = {FieldIndex, LowestElem}; 8218 } 8219 } 8220 8221 // Need to emit combined struct for array sections. 8222 if (IsFinalArraySection || IsNonContiguous) 8223 PartialStruct.IsArraySection = true; 8224 8225 // If we have a final array section, we are done with this expression. 8226 if (IsFinalArraySection) 8227 break; 8228 8229 // The pointer becomes the base for the next element. 8230 if (Next != CE) 8231 BP = IsMemberReference ? LowestElem : LB; 8232 8233 IsExpressionFirstInfo = false; 8234 IsCaptureFirstInfo = false; 8235 FirstPointerInComplexData = false; 8236 IsPrevMemberReference = IsMemberReference; 8237 } else if (FirstPointerInComplexData) { 8238 QualType Ty = Components.rbegin() 8239 ->getAssociatedDeclaration() 8240 ->getType() 8241 .getNonReferenceType(); 8242 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 8243 FirstPointerInComplexData = false; 8244 } 8245 } 8246 // If ran into the whole component - allocate the space for the whole 8247 // record. 8248 if (!EncounteredME) 8249 PartialStruct.HasCompleteRecord = true; 8250 8251 if (!IsNonContiguous) 8252 return; 8253 8254 const ASTContext &Context = CGF.getContext(); 8255 8256 // For supporting stride in array section, we need to initialize the first 8257 // dimension size as 1, first offset as 0, and first count as 1 8258 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 0)}; 8259 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 8260 MapValuesArrayTy CurStrides; 8261 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 8262 uint64_t ElementTypeSize; 8263 8264 // Collect Size information for each dimension and get the element size as 8265 // the first Stride. For example, for `int arr[10][10]`, the DimSizes 8266 // should be [10, 10] and the first stride is 4 btyes. 8267 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 8268 Components) { 8269 const Expr *AssocExpr = Component.getAssociatedExpression(); 8270 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8271 8272 if (!OASE) 8273 continue; 8274 8275 QualType Ty = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase()); 8276 auto *CAT = Context.getAsConstantArrayType(Ty); 8277 auto *VAT = Context.getAsVariableArrayType(Ty); 8278 8279 // We need all the dimension size except for the last dimension. 8280 assert((VAT || CAT || &Component == &*Components.begin()) && 8281 "Should be either ConstantArray or VariableArray if not the " 8282 "first Component"); 8283 8284 // Get element size if CurStrides is empty. 8285 if (CurStrides.empty()) { 8286 const Type *ElementType = nullptr; 8287 if (CAT) 8288 ElementType = CAT->getElementType().getTypePtr(); 8289 else if (VAT) 8290 ElementType = VAT->getElementType().getTypePtr(); 8291 else 8292 assert(&Component == &*Components.begin() && 8293 "Only expect pointer (non CAT or VAT) when this is the " 8294 "first Component"); 8295 // If ElementType is null, then it means the base is a pointer 8296 // (neither CAT nor VAT) and we'll attempt to get ElementType again 8297 // for next iteration. 8298 if (ElementType) { 8299 // For the case that having pointer as base, we need to remove one 8300 // level of indirection. 8301 if (&Component != &*Components.begin()) 8302 ElementType = ElementType->getPointeeOrArrayElementType(); 8303 ElementTypeSize = 8304 Context.getTypeSizeInChars(ElementType).getQuantity(); 8305 CurStrides.push_back( 8306 llvm::ConstantInt::get(CGF.Int64Ty, ElementTypeSize)); 8307 } 8308 } 8309 // Get dimension value except for the last dimension since we don't need 8310 // it. 8311 if (DimSizes.size() < Components.size() - 1) { 8312 if (CAT) 8313 DimSizes.push_back(llvm::ConstantInt::get( 8314 CGF.Int64Ty, CAT->getSize().getZExtValue())); 8315 else if (VAT) 8316 DimSizes.push_back(CGF.Builder.CreateIntCast( 8317 CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty, 8318 /*IsSigned=*/false)); 8319 } 8320 } 8321 8322 // Skip the dummy dimension since we have already have its information. 8323 auto DI = DimSizes.begin() + 1; 8324 // Product of dimension. 8325 llvm::Value *DimProd = 8326 llvm::ConstantInt::get(CGF.CGM.Int64Ty, ElementTypeSize); 8327 8328 // Collect info for non-contiguous. Notice that offset, count, and stride 8329 // are only meaningful for array-section, so we insert a null for anything 8330 // other than array-section. 8331 // Also, the size of offset, count, and stride are not the same as 8332 // pointers, base_pointers, sizes, or dims. Instead, the size of offset, 8333 // count, and stride are the same as the number of non-contiguous 8334 // declaration in target update to/from clause. 8335 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 8336 Components) { 8337 const Expr *AssocExpr = Component.getAssociatedExpression(); 8338 8339 if (const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) { 8340 llvm::Value *Offset = CGF.Builder.CreateIntCast( 8341 CGF.EmitScalarExpr(AE->getIdx()), CGF.Int64Ty, 8342 /*isSigned=*/false); 8343 CurOffsets.push_back(Offset); 8344 CurCounts.push_back(llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/1)); 8345 CurStrides.push_back(CurStrides.back()); 8346 continue; 8347 } 8348 8349 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8350 8351 if (!OASE) 8352 continue; 8353 8354 // Offset 8355 const Expr *OffsetExpr = OASE->getLowerBound(); 8356 llvm::Value *Offset = nullptr; 8357 if (!OffsetExpr) { 8358 // If offset is absent, then we just set it to zero. 8359 Offset = llvm::ConstantInt::get(CGF.Int64Ty, 0); 8360 } else { 8361 Offset = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(OffsetExpr), 8362 CGF.Int64Ty, 8363 /*isSigned=*/false); 8364 } 8365 CurOffsets.push_back(Offset); 8366 8367 // Count 8368 const Expr *CountExpr = OASE->getLength(); 8369 llvm::Value *Count = nullptr; 8370 if (!CountExpr) { 8371 // In Clang, once a high dimension is an array section, we construct all 8372 // the lower dimension as array section, however, for case like 8373 // arr[0:2][2], Clang construct the inner dimension as an array section 8374 // but it actually is not in an array section form according to spec. 8375 if (!OASE->getColonLocFirst().isValid() && 8376 !OASE->getColonLocSecond().isValid()) { 8377 Count = llvm::ConstantInt::get(CGF.Int64Ty, 1); 8378 } else { 8379 // OpenMP 5.0, 2.1.5 Array Sections, Description. 8380 // When the length is absent it defaults to ⌈(size − 8381 // lower-bound)/stride⌉, where size is the size of the array 8382 // dimension. 8383 const Expr *StrideExpr = OASE->getStride(); 8384 llvm::Value *Stride = 8385 StrideExpr 8386 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8387 CGF.Int64Ty, /*isSigned=*/false) 8388 : nullptr; 8389 if (Stride) 8390 Count = CGF.Builder.CreateUDiv( 8391 CGF.Builder.CreateNUWSub(*DI, Offset), Stride); 8392 else 8393 Count = CGF.Builder.CreateNUWSub(*DI, Offset); 8394 } 8395 } else { 8396 Count = CGF.EmitScalarExpr(CountExpr); 8397 } 8398 Count = CGF.Builder.CreateIntCast(Count, CGF.Int64Ty, /*isSigned=*/false); 8399 CurCounts.push_back(Count); 8400 8401 // Stride_n' = Stride_n * (D_0 * D_1 ... * D_n-1) * Unit size 8402 // Take `int arr[5][5][5]` and `arr[0:2:2][1:2:1][0:2:2]` as an example: 8403 // Offset Count Stride 8404 // D0 0 1 4 (int) <- dummy dimension 8405 // D1 0 2 8 (2 * (1) * 4) 8406 // D2 1 2 20 (1 * (1 * 5) * 4) 8407 // D3 0 2 200 (2 * (1 * 5 * 4) * 4) 8408 const Expr *StrideExpr = OASE->getStride(); 8409 llvm::Value *Stride = 8410 StrideExpr 8411 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8412 CGF.Int64Ty, /*isSigned=*/false) 8413 : nullptr; 8414 DimProd = CGF.Builder.CreateNUWMul(DimProd, *(DI - 1)); 8415 if (Stride) 8416 CurStrides.push_back(CGF.Builder.CreateNUWMul(DimProd, Stride)); 8417 else 8418 CurStrides.push_back(DimProd); 8419 if (DI != DimSizes.end()) 8420 ++DI; 8421 } 8422 8423 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets); 8424 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts); 8425 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides); 8426 } 8427 8428 /// Return the adjusted map modifiers if the declaration a capture refers to 8429 /// appears in a first-private clause. This is expected to be used only with 8430 /// directives that start with 'target'. 8431 MappableExprsHandler::OpenMPOffloadMappingFlags 8432 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 8433 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 8434 8435 // A first private variable captured by reference will use only the 8436 // 'private ptr' and 'map to' flag. Return the right flags if the captured 8437 // declaration is known as first-private in this handler. 8438 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 8439 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 8440 return MappableExprsHandler::OMP_MAP_TO | 8441 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 8442 return MappableExprsHandler::OMP_MAP_PRIVATE | 8443 MappableExprsHandler::OMP_MAP_TO; 8444 } 8445 return MappableExprsHandler::OMP_MAP_TO | 8446 MappableExprsHandler::OMP_MAP_FROM; 8447 } 8448 8449 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 8450 // Rotate by getFlagMemberOffset() bits. 8451 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 8452 << getFlagMemberOffset()); 8453 } 8454 8455 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 8456 OpenMPOffloadMappingFlags MemberOfFlag) { 8457 // If the entry is PTR_AND_OBJ but has not been marked with the special 8458 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 8459 // marked as MEMBER_OF. 8460 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 8461 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 8462 return; 8463 8464 // Reset the placeholder value to prepare the flag for the assignment of the 8465 // proper MEMBER_OF value. 8466 Flags &= ~OMP_MAP_MEMBER_OF; 8467 Flags |= MemberOfFlag; 8468 } 8469 8470 void getPlainLayout(const CXXRecordDecl *RD, 8471 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 8472 bool AsBase) const { 8473 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 8474 8475 llvm::StructType *St = 8476 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 8477 8478 unsigned NumElements = St->getNumElements(); 8479 llvm::SmallVector< 8480 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 8481 RecordLayout(NumElements); 8482 8483 // Fill bases. 8484 for (const auto &I : RD->bases()) { 8485 if (I.isVirtual()) 8486 continue; 8487 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8488 // Ignore empty bases. 8489 if (Base->isEmpty() || CGF.getContext() 8490 .getASTRecordLayout(Base) 8491 .getNonVirtualSize() 8492 .isZero()) 8493 continue; 8494 8495 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 8496 RecordLayout[FieldIndex] = Base; 8497 } 8498 // Fill in virtual bases. 8499 for (const auto &I : RD->vbases()) { 8500 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8501 // Ignore empty bases. 8502 if (Base->isEmpty()) 8503 continue; 8504 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 8505 if (RecordLayout[FieldIndex]) 8506 continue; 8507 RecordLayout[FieldIndex] = Base; 8508 } 8509 // Fill in all the fields. 8510 assert(!RD->isUnion() && "Unexpected union."); 8511 for (const auto *Field : RD->fields()) { 8512 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 8513 // will fill in later.) 8514 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 8515 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 8516 RecordLayout[FieldIndex] = Field; 8517 } 8518 } 8519 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 8520 &Data : RecordLayout) { 8521 if (Data.isNull()) 8522 continue; 8523 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 8524 getPlainLayout(Base, Layout, /*AsBase=*/true); 8525 else 8526 Layout.push_back(Data.get<const FieldDecl *>()); 8527 } 8528 } 8529 8530 /// Generate all the base pointers, section pointers, sizes, map types, and 8531 /// mappers for the extracted mappable expressions (all included in \a 8532 /// CombinedInfo). Also, for each item that relates with a device pointer, a 8533 /// pair of the relevant declaration and index where it occurs is appended to 8534 /// the device pointers info array. 8535 void generateAllInfoForClauses( 8536 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo, 8537 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 8538 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 8539 // We have to process the component lists that relate with the same 8540 // declaration in a single chunk so that we can generate the map flags 8541 // correctly. Therefore, we organize all lists in a map. 8542 enum MapKind { Present, Allocs, Other, Total }; 8543 llvm::MapVector<CanonicalDeclPtr<const Decl>, 8544 SmallVector<SmallVector<MapInfo, 8>, 4>> 8545 Info; 8546 8547 // Helper function to fill the information map for the different supported 8548 // clauses. 8549 auto &&InfoGen = 8550 [&Info, &SkipVarSet]( 8551 const ValueDecl *D, MapKind Kind, 8552 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8553 OpenMPMapClauseKind MapType, 8554 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8555 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 8556 bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper, 8557 const Expr *VarRef = nullptr, bool ForDeviceAddr = false) { 8558 if (SkipVarSet.contains(D)) 8559 return; 8560 auto It = Info.find(D); 8561 if (It == Info.end()) 8562 It = Info 8563 .insert(std::make_pair( 8564 D, SmallVector<SmallVector<MapInfo, 8>, 4>(Total))) 8565 .first; 8566 It->second[Kind].emplace_back( 8567 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer, 8568 IsImplicit, Mapper, VarRef, ForDeviceAddr); 8569 }; 8570 8571 for (const auto *Cl : Clauses) { 8572 const auto *C = dyn_cast<OMPMapClause>(Cl); 8573 if (!C) 8574 continue; 8575 MapKind Kind = Other; 8576 if (!C->getMapTypeModifiers().empty() && 8577 llvm::any_of(C->getMapTypeModifiers(), [](OpenMPMapModifierKind K) { 8578 return K == OMPC_MAP_MODIFIER_present; 8579 })) 8580 Kind = Present; 8581 else if (C->getMapType() == OMPC_MAP_alloc) 8582 Kind = Allocs; 8583 const auto *EI = C->getVarRefs().begin(); 8584 for (const auto L : C->component_lists()) { 8585 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 8586 InfoGen(std::get<0>(L), Kind, std::get<1>(L), C->getMapType(), 8587 C->getMapTypeModifiers(), llvm::None, 8588 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L), 8589 E); 8590 ++EI; 8591 } 8592 } 8593 for (const auto *Cl : Clauses) { 8594 const auto *C = dyn_cast<OMPToClause>(Cl); 8595 if (!C) 8596 continue; 8597 MapKind Kind = Other; 8598 if (!C->getMotionModifiers().empty() && 8599 llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) { 8600 return K == OMPC_MOTION_MODIFIER_present; 8601 })) 8602 Kind = Present; 8603 const auto *EI = C->getVarRefs().begin(); 8604 for (const auto L : C->component_lists()) { 8605 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, llvm::None, 8606 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8607 C->isImplicit(), std::get<2>(L), *EI); 8608 ++EI; 8609 } 8610 } 8611 for (const auto *Cl : Clauses) { 8612 const auto *C = dyn_cast<OMPFromClause>(Cl); 8613 if (!C) 8614 continue; 8615 MapKind Kind = Other; 8616 if (!C->getMotionModifiers().empty() && 8617 llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) { 8618 return K == OMPC_MOTION_MODIFIER_present; 8619 })) 8620 Kind = Present; 8621 const auto *EI = C->getVarRefs().begin(); 8622 for (const auto L : C->component_lists()) { 8623 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, llvm::None, 8624 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8625 C->isImplicit(), std::get<2>(L), *EI); 8626 ++EI; 8627 } 8628 } 8629 8630 // Look at the use_device_ptr clause information and mark the existing map 8631 // entries as such. If there is no map information for an entry in the 8632 // use_device_ptr list, we create one with map type 'alloc' and zero size 8633 // section. It is the user fault if that was not mapped before. If there is 8634 // no map information and the pointer is a struct member, then we defer the 8635 // emission of that entry until the whole struct has been processed. 8636 llvm::MapVector<CanonicalDeclPtr<const Decl>, 8637 SmallVector<DeferredDevicePtrEntryTy, 4>> 8638 DeferredInfo; 8639 MapCombinedInfoTy UseDevicePtrCombinedInfo; 8640 8641 for (const auto *Cl : Clauses) { 8642 const auto *C = dyn_cast<OMPUseDevicePtrClause>(Cl); 8643 if (!C) 8644 continue; 8645 for (const auto L : C->component_lists()) { 8646 OMPClauseMappableExprCommon::MappableExprComponentListRef Components = 8647 std::get<1>(L); 8648 assert(!Components.empty() && 8649 "Not expecting empty list of components!"); 8650 const ValueDecl *VD = Components.back().getAssociatedDeclaration(); 8651 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8652 const Expr *IE = Components.back().getAssociatedExpression(); 8653 // If the first component is a member expression, we have to look into 8654 // 'this', which maps to null in the map of map information. Otherwise 8655 // look directly for the information. 8656 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8657 8658 // We potentially have map information for this declaration already. 8659 // Look for the first set of components that refer to it. 8660 if (It != Info.end()) { 8661 bool Found = false; 8662 for (auto &Data : It->second) { 8663 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) { 8664 return MI.Components.back().getAssociatedDeclaration() == VD; 8665 }); 8666 // If we found a map entry, signal that the pointer has to be 8667 // returned and move on to the next declaration. Exclude cases where 8668 // the base pointer is mapped as array subscript, array section or 8669 // array shaping. The base address is passed as a pointer to base in 8670 // this case and cannot be used as a base for use_device_ptr list 8671 // item. 8672 if (CI != Data.end()) { 8673 auto PrevCI = std::next(CI->Components.rbegin()); 8674 const auto *VarD = dyn_cast<VarDecl>(VD); 8675 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8676 isa<MemberExpr>(IE) || 8677 !VD->getType().getNonReferenceType()->isPointerType() || 8678 PrevCI == CI->Components.rend() || 8679 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD || 8680 VarD->hasLocalStorage()) { 8681 CI->ReturnDevicePointer = true; 8682 Found = true; 8683 break; 8684 } 8685 } 8686 } 8687 if (Found) 8688 continue; 8689 } 8690 8691 // We didn't find any match in our map information - generate a zero 8692 // size array section - if the pointer is a struct member we defer this 8693 // action until the whole struct has been processed. 8694 if (isa<MemberExpr>(IE)) { 8695 // Insert the pointer into Info to be processed by 8696 // generateInfoForComponentList. Because it is a member pointer 8697 // without a pointee, no entry will be generated for it, therefore 8698 // we need to generate one after the whole struct has been processed. 8699 // Nonetheless, generateInfoForComponentList must be called to take 8700 // the pointer into account for the calculation of the range of the 8701 // partial struct. 8702 InfoGen(nullptr, Other, Components, OMPC_MAP_unknown, llvm::None, 8703 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8704 nullptr); 8705 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false); 8706 } else { 8707 llvm::Value *Ptr = 8708 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8709 UseDevicePtrCombinedInfo.Exprs.push_back(VD); 8710 UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD); 8711 UseDevicePtrCombinedInfo.Pointers.push_back(Ptr); 8712 UseDevicePtrCombinedInfo.Sizes.push_back( 8713 llvm::Constant::getNullValue(CGF.Int64Ty)); 8714 UseDevicePtrCombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM); 8715 UseDevicePtrCombinedInfo.Mappers.push_back(nullptr); 8716 } 8717 } 8718 } 8719 8720 // Look at the use_device_addr clause information and mark the existing map 8721 // entries as such. If there is no map information for an entry in the 8722 // use_device_addr list, we create one with map type 'alloc' and zero size 8723 // section. It is the user fault if that was not mapped before. If there is 8724 // no map information and the pointer is a struct member, then we defer the 8725 // emission of that entry until the whole struct has been processed. 8726 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed; 8727 for (const auto *Cl : Clauses) { 8728 const auto *C = dyn_cast<OMPUseDeviceAddrClause>(Cl); 8729 if (!C) 8730 continue; 8731 for (const auto L : C->component_lists()) { 8732 assert(!std::get<1>(L).empty() && 8733 "Not expecting empty list of components!"); 8734 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration(); 8735 if (!Processed.insert(VD).second) 8736 continue; 8737 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8738 const Expr *IE = std::get<1>(L).back().getAssociatedExpression(); 8739 // If the first component is a member expression, we have to look into 8740 // 'this', which maps to null in the map of map information. Otherwise 8741 // look directly for the information. 8742 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8743 8744 // We potentially have map information for this declaration already. 8745 // Look for the first set of components that refer to it. 8746 if (It != Info.end()) { 8747 bool Found = false; 8748 for (auto &Data : It->second) { 8749 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) { 8750 return MI.Components.back().getAssociatedDeclaration() == VD; 8751 }); 8752 // If we found a map entry, signal that the pointer has to be 8753 // returned and move on to the next declaration. 8754 if (CI != Data.end()) { 8755 CI->ReturnDevicePointer = true; 8756 Found = true; 8757 break; 8758 } 8759 } 8760 if (Found) 8761 continue; 8762 } 8763 8764 // We didn't find any match in our map information - generate a zero 8765 // size array section - if the pointer is a struct member we defer this 8766 // action until the whole struct has been processed. 8767 if (isa<MemberExpr>(IE)) { 8768 // Insert the pointer into Info to be processed by 8769 // generateInfoForComponentList. Because it is a member pointer 8770 // without a pointee, no entry will be generated for it, therefore 8771 // we need to generate one after the whole struct has been processed. 8772 // Nonetheless, generateInfoForComponentList must be called to take 8773 // the pointer into account for the calculation of the range of the 8774 // partial struct. 8775 InfoGen(nullptr, Other, std::get<1>(L), OMPC_MAP_unknown, llvm::None, 8776 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8777 nullptr, nullptr, /*ForDeviceAddr=*/true); 8778 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true); 8779 } else { 8780 llvm::Value *Ptr; 8781 if (IE->isGLValue()) 8782 Ptr = CGF.EmitLValue(IE).getPointer(CGF); 8783 else 8784 Ptr = CGF.EmitScalarExpr(IE); 8785 CombinedInfo.Exprs.push_back(VD); 8786 CombinedInfo.BasePointers.emplace_back(Ptr, VD); 8787 CombinedInfo.Pointers.push_back(Ptr); 8788 CombinedInfo.Sizes.push_back( 8789 llvm::Constant::getNullValue(CGF.Int64Ty)); 8790 CombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM); 8791 CombinedInfo.Mappers.push_back(nullptr); 8792 } 8793 } 8794 } 8795 8796 for (const auto &Data : Info) { 8797 StructRangeInfoTy PartialStruct; 8798 // Temporary generated information. 8799 MapCombinedInfoTy CurInfo; 8800 const Decl *D = Data.first; 8801 const ValueDecl *VD = cast_or_null<ValueDecl>(D); 8802 for (const auto &M : Data.second) { 8803 for (const MapInfo &L : M) { 8804 assert(!L.Components.empty() && 8805 "Not expecting declaration with no component lists."); 8806 8807 // Remember the current base pointer index. 8808 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size(); 8809 CurInfo.NonContigInfo.IsNonContiguous = 8810 L.Components.back().isNonContiguous(); 8811 generateInfoForComponentList( 8812 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components, 8813 CurInfo, PartialStruct, /*IsFirstComponentList=*/false, 8814 L.IsImplicit, L.Mapper, L.ForDeviceAddr, VD, L.VarRef); 8815 8816 // If this entry relates with a device pointer, set the relevant 8817 // declaration and add the 'return pointer' flag. 8818 if (L.ReturnDevicePointer) { 8819 assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx && 8820 "Unexpected number of mapped base pointers."); 8821 8822 const ValueDecl *RelevantVD = 8823 L.Components.back().getAssociatedDeclaration(); 8824 assert(RelevantVD && 8825 "No relevant declaration related with device pointer??"); 8826 8827 CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl( 8828 RelevantVD); 8829 CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8830 } 8831 } 8832 } 8833 8834 // Append any pending zero-length pointers which are struct members and 8835 // used with use_device_ptr or use_device_addr. 8836 auto CI = DeferredInfo.find(Data.first); 8837 if (CI != DeferredInfo.end()) { 8838 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8839 llvm::Value *BasePtr; 8840 llvm::Value *Ptr; 8841 if (L.ForDeviceAddr) { 8842 if (L.IE->isGLValue()) 8843 Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8844 else 8845 Ptr = this->CGF.EmitScalarExpr(L.IE); 8846 BasePtr = Ptr; 8847 // Entry is RETURN_PARAM. Also, set the placeholder value 8848 // MEMBER_OF=FFFF so that the entry is later updated with the 8849 // correct value of MEMBER_OF. 8850 CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF); 8851 } else { 8852 BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8853 Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE), 8854 L.IE->getExprLoc()); 8855 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the 8856 // placeholder value MEMBER_OF=FFFF so that the entry is later 8857 // updated with the correct value of MEMBER_OF. 8858 CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8859 OMP_MAP_MEMBER_OF); 8860 } 8861 CurInfo.Exprs.push_back(L.VD); 8862 CurInfo.BasePointers.emplace_back(BasePtr, L.VD); 8863 CurInfo.Pointers.push_back(Ptr); 8864 CurInfo.Sizes.push_back( 8865 llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8866 CurInfo.Mappers.push_back(nullptr); 8867 } 8868 } 8869 // If there is an entry in PartialStruct it means we have a struct with 8870 // individual members mapped. Emit an extra combined entry. 8871 if (PartialStruct.Base.isValid()) { 8872 CurInfo.NonContigInfo.Dims.push_back(0); 8873 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD); 8874 } 8875 8876 // We need to append the results of this capture to what we already 8877 // have. 8878 CombinedInfo.append(CurInfo); 8879 } 8880 // Append data for use_device_ptr clauses. 8881 CombinedInfo.append(UseDevicePtrCombinedInfo); 8882 } 8883 8884 public: 8885 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 8886 : CurDir(&Dir), CGF(CGF) { 8887 // Extract firstprivate clause information. 8888 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 8889 for (const auto *D : C->varlists()) 8890 FirstPrivateDecls.try_emplace( 8891 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 8892 // Extract implicit firstprivates from uses_allocators clauses. 8893 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) { 8894 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 8895 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 8896 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits)) 8897 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()), 8898 /*Implicit=*/true); 8899 else if (const auto *VD = dyn_cast<VarDecl>( 8900 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts()) 8901 ->getDecl())) 8902 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true); 8903 } 8904 } 8905 // Extract device pointer clause information. 8906 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 8907 for (auto L : C->component_lists()) 8908 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L)); 8909 } 8910 8911 /// Constructor for the declare mapper directive. 8912 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 8913 : CurDir(&Dir), CGF(CGF) {} 8914 8915 /// Generate code for the combined entry if we have a partially mapped struct 8916 /// and take care of the mapping flags of the arguments corresponding to 8917 /// individual struct members. 8918 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo, 8919 MapFlagsArrayTy &CurTypes, 8920 const StructRangeInfoTy &PartialStruct, 8921 const ValueDecl *VD = nullptr, 8922 bool NotTargetParams = true) const { 8923 if (CurTypes.size() == 1 && 8924 ((CurTypes.back() & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF) && 8925 !PartialStruct.IsArraySection) 8926 return; 8927 Address LBAddr = PartialStruct.LowestElem.second; 8928 Address HBAddr = PartialStruct.HighestElem.second; 8929 if (PartialStruct.HasCompleteRecord) { 8930 LBAddr = PartialStruct.LB; 8931 HBAddr = PartialStruct.LB; 8932 } 8933 CombinedInfo.Exprs.push_back(VD); 8934 // Base is the base of the struct 8935 CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); 8936 // Pointer is the address of the lowest element 8937 llvm::Value *LB = LBAddr.getPointer(); 8938 CombinedInfo.Pointers.push_back(LB); 8939 // There should not be a mapper for a combined entry. 8940 CombinedInfo.Mappers.push_back(nullptr); 8941 // Size is (addr of {highest+1} element) - (addr of lowest element) 8942 llvm::Value *HB = HBAddr.getPointer(); 8943 llvm::Value *HAddr = 8944 CGF.Builder.CreateConstGEP1_32(HBAddr.getElementType(), HB, /*Idx0=*/1); 8945 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 8946 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 8947 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 8948 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 8949 /*isSigned=*/false); 8950 CombinedInfo.Sizes.push_back(Size); 8951 // Map type is always TARGET_PARAM, if generate info for captures. 8952 CombinedInfo.Types.push_back(NotTargetParams ? OMP_MAP_NONE 8953 : OMP_MAP_TARGET_PARAM); 8954 // If any element has the present modifier, then make sure the runtime 8955 // doesn't attempt to allocate the struct. 8956 if (CurTypes.end() != 8957 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) { 8958 return Type & OMP_MAP_PRESENT; 8959 })) 8960 CombinedInfo.Types.back() |= OMP_MAP_PRESENT; 8961 // Remove TARGET_PARAM flag from the first element 8962 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 8963 // If any element has the ompx_hold modifier, then make sure the runtime 8964 // uses the hold reference count for the struct as a whole so that it won't 8965 // be unmapped by an extra dynamic reference count decrement. Add it to all 8966 // elements as well so the runtime knows which reference count to check 8967 // when determining whether it's time for device-to-host transfers of 8968 // individual elements. 8969 if (CurTypes.end() != 8970 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) { 8971 return Type & OMP_MAP_OMPX_HOLD; 8972 })) { 8973 CombinedInfo.Types.back() |= OMP_MAP_OMPX_HOLD; 8974 for (auto &M : CurTypes) 8975 M |= OMP_MAP_OMPX_HOLD; 8976 } 8977 8978 // All other current entries will be MEMBER_OF the combined entry 8979 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8980 // 0xFFFF in the MEMBER_OF field). 8981 OpenMPOffloadMappingFlags MemberOfFlag = 8982 getMemberOfFlag(CombinedInfo.BasePointers.size() - 1); 8983 for (auto &M : CurTypes) 8984 setCorrectMemberOfFlag(M, MemberOfFlag); 8985 } 8986 8987 /// Generate all the base pointers, section pointers, sizes, map types, and 8988 /// mappers for the extracted mappable expressions (all included in \a 8989 /// CombinedInfo). Also, for each item that relates with a device pointer, a 8990 /// pair of the relevant declaration and index where it occurs is appended to 8991 /// the device pointers info array. 8992 void generateAllInfo( 8993 MapCombinedInfoTy &CombinedInfo, 8994 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 8995 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 8996 assert(CurDir.is<const OMPExecutableDirective *>() && 8997 "Expect a executable directive"); 8998 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8999 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, SkipVarSet); 9000 } 9001 9002 /// Generate all the base pointers, section pointers, sizes, map types, and 9003 /// mappers for the extracted map clauses of user-defined mapper (all included 9004 /// in \a CombinedInfo). 9005 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const { 9006 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 9007 "Expect a declare mapper directive"); 9008 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 9009 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo); 9010 } 9011 9012 /// Emit capture info for lambdas for variables captured by reference. 9013 void generateInfoForLambdaCaptures( 9014 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 9015 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 9016 const auto *RD = VD->getType() 9017 .getCanonicalType() 9018 .getNonReferenceType() 9019 ->getAsCXXRecordDecl(); 9020 if (!RD || !RD->isLambda()) 9021 return; 9022 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 9023 LValue VDLVal = CGF.MakeAddrLValue( 9024 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 9025 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 9026 FieldDecl *ThisCapture = nullptr; 9027 RD->getCaptureFields(Captures, ThisCapture); 9028 if (ThisCapture) { 9029 LValue ThisLVal = 9030 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 9031 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 9032 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 9033 VDLVal.getPointer(CGF)); 9034 CombinedInfo.Exprs.push_back(VD); 9035 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF)); 9036 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF)); 9037 CombinedInfo.Sizes.push_back( 9038 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 9039 CGF.Int64Ty, /*isSigned=*/true)); 9040 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9041 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 9042 CombinedInfo.Mappers.push_back(nullptr); 9043 } 9044 for (const LambdaCapture &LC : RD->captures()) { 9045 if (!LC.capturesVariable()) 9046 continue; 9047 const VarDecl *VD = LC.getCapturedVar(); 9048 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 9049 continue; 9050 auto It = Captures.find(VD); 9051 assert(It != Captures.end() && "Found lambda capture without field."); 9052 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 9053 if (LC.getCaptureKind() == LCK_ByRef) { 9054 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 9055 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 9056 VDLVal.getPointer(CGF)); 9057 CombinedInfo.Exprs.push_back(VD); 9058 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 9059 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF)); 9060 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9061 CGF.getTypeSize( 9062 VD->getType().getCanonicalType().getNonReferenceType()), 9063 CGF.Int64Ty, /*isSigned=*/true)); 9064 } else { 9065 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 9066 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 9067 VDLVal.getPointer(CGF)); 9068 CombinedInfo.Exprs.push_back(VD); 9069 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 9070 CombinedInfo.Pointers.push_back(VarRVal.getScalarVal()); 9071 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 9072 } 9073 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9074 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 9075 CombinedInfo.Mappers.push_back(nullptr); 9076 } 9077 } 9078 9079 /// Set correct indices for lambdas captures. 9080 void adjustMemberOfForLambdaCaptures( 9081 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 9082 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 9083 MapFlagsArrayTy &Types) const { 9084 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 9085 // Set correct member_of idx for all implicit lambda captures. 9086 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9087 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 9088 continue; 9089 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 9090 assert(BasePtr && "Unable to find base lambda address."); 9091 int TgtIdx = -1; 9092 for (unsigned J = I; J > 0; --J) { 9093 unsigned Idx = J - 1; 9094 if (Pointers[Idx] != BasePtr) 9095 continue; 9096 TgtIdx = Idx; 9097 break; 9098 } 9099 assert(TgtIdx != -1 && "Unable to find parent lambda."); 9100 // All other current entries will be MEMBER_OF the combined entry 9101 // (except for PTR_AND_OBJ entries which do not have a placeholder value 9102 // 0xFFFF in the MEMBER_OF field). 9103 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 9104 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 9105 } 9106 } 9107 9108 /// Generate the base pointers, section pointers, sizes, map types, and 9109 /// mappers associated to a given capture (all included in \a CombinedInfo). 9110 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 9111 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 9112 StructRangeInfoTy &PartialStruct) const { 9113 assert(!Cap->capturesVariableArrayType() && 9114 "Not expecting to generate map info for a variable array type!"); 9115 9116 // We need to know when we generating information for the first component 9117 const ValueDecl *VD = Cap->capturesThis() 9118 ? nullptr 9119 : Cap->getCapturedVar()->getCanonicalDecl(); 9120 9121 // If this declaration appears in a is_device_ptr clause we just have to 9122 // pass the pointer by value. If it is a reference to a declaration, we just 9123 // pass its value. 9124 if (DevPointersMap.count(VD)) { 9125 CombinedInfo.Exprs.push_back(VD); 9126 CombinedInfo.BasePointers.emplace_back(Arg, VD); 9127 CombinedInfo.Pointers.push_back(Arg); 9128 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9129 CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty, 9130 /*isSigned=*/true)); 9131 CombinedInfo.Types.push_back( 9132 (Cap->capturesVariable() ? OMP_MAP_TO : OMP_MAP_LITERAL) | 9133 OMP_MAP_TARGET_PARAM); 9134 CombinedInfo.Mappers.push_back(nullptr); 9135 return; 9136 } 9137 9138 using MapData = 9139 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 9140 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool, 9141 const ValueDecl *, const Expr *>; 9142 SmallVector<MapData, 4> DeclComponentLists; 9143 assert(CurDir.is<const OMPExecutableDirective *>() && 9144 "Expect a executable directive"); 9145 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 9146 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 9147 const auto *EI = C->getVarRefs().begin(); 9148 for (const auto L : C->decl_component_lists(VD)) { 9149 const ValueDecl *VDecl, *Mapper; 9150 // The Expression is not correct if the mapping is implicit 9151 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 9152 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9153 std::tie(VDecl, Components, Mapper) = L; 9154 assert(VDecl == VD && "We got information for the wrong declaration??"); 9155 assert(!Components.empty() && 9156 "Not expecting declaration with no component lists."); 9157 DeclComponentLists.emplace_back(Components, C->getMapType(), 9158 C->getMapTypeModifiers(), 9159 C->isImplicit(), Mapper, E); 9160 ++EI; 9161 } 9162 } 9163 llvm::stable_sort(DeclComponentLists, [](const MapData &LHS, 9164 const MapData &RHS) { 9165 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS); 9166 OpenMPMapClauseKind MapType = std::get<1>(RHS); 9167 bool HasPresent = !MapModifiers.empty() && 9168 llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) { 9169 return K == clang::OMPC_MAP_MODIFIER_present; 9170 }); 9171 bool HasAllocs = MapType == OMPC_MAP_alloc; 9172 MapModifiers = std::get<2>(RHS); 9173 MapType = std::get<1>(LHS); 9174 bool HasPresentR = 9175 !MapModifiers.empty() && 9176 llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) { 9177 return K == clang::OMPC_MAP_MODIFIER_present; 9178 }); 9179 bool HasAllocsR = MapType == OMPC_MAP_alloc; 9180 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR); 9181 }); 9182 9183 // Find overlapping elements (including the offset from the base element). 9184 llvm::SmallDenseMap< 9185 const MapData *, 9186 llvm::SmallVector< 9187 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 9188 4> 9189 OverlappedData; 9190 size_t Count = 0; 9191 for (const MapData &L : DeclComponentLists) { 9192 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9193 OpenMPMapClauseKind MapType; 9194 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9195 bool IsImplicit; 9196 const ValueDecl *Mapper; 9197 const Expr *VarRef; 9198 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9199 L; 9200 ++Count; 9201 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 9202 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 9203 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper, 9204 VarRef) = L1; 9205 auto CI = Components.rbegin(); 9206 auto CE = Components.rend(); 9207 auto SI = Components1.rbegin(); 9208 auto SE = Components1.rend(); 9209 for (; CI != CE && SI != SE; ++CI, ++SI) { 9210 if (CI->getAssociatedExpression()->getStmtClass() != 9211 SI->getAssociatedExpression()->getStmtClass()) 9212 break; 9213 // Are we dealing with different variables/fields? 9214 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 9215 break; 9216 } 9217 // Found overlapping if, at least for one component, reached the head 9218 // of the components list. 9219 if (CI == CE || SI == SE) { 9220 // Ignore it if it is the same component. 9221 if (CI == CE && SI == SE) 9222 continue; 9223 const auto It = (SI == SE) ? CI : SI; 9224 // If one component is a pointer and another one is a kind of 9225 // dereference of this pointer (array subscript, section, dereference, 9226 // etc.), it is not an overlapping. 9227 // Same, if one component is a base and another component is a 9228 // dereferenced pointer memberexpr with the same base. 9229 if (!isa<MemberExpr>(It->getAssociatedExpression()) || 9230 (std::prev(It)->getAssociatedDeclaration() && 9231 std::prev(It) 9232 ->getAssociatedDeclaration() 9233 ->getType() 9234 ->isPointerType()) || 9235 (It->getAssociatedDeclaration() && 9236 It->getAssociatedDeclaration()->getType()->isPointerType() && 9237 std::next(It) != CE && std::next(It) != SE)) 9238 continue; 9239 const MapData &BaseData = CI == CE ? L : L1; 9240 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 9241 SI == SE ? Components : Components1; 9242 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 9243 OverlappedElements.getSecond().push_back(SubData); 9244 } 9245 } 9246 } 9247 // Sort the overlapped elements for each item. 9248 llvm::SmallVector<const FieldDecl *, 4> Layout; 9249 if (!OverlappedData.empty()) { 9250 const Type *BaseType = VD->getType().getCanonicalType().getTypePtr(); 9251 const Type *OrigType = BaseType->getPointeeOrArrayElementType(); 9252 while (BaseType != OrigType) { 9253 BaseType = OrigType->getCanonicalTypeInternal().getTypePtr(); 9254 OrigType = BaseType->getPointeeOrArrayElementType(); 9255 } 9256 9257 if (const auto *CRD = BaseType->getAsCXXRecordDecl()) 9258 getPlainLayout(CRD, Layout, /*AsBase=*/false); 9259 else { 9260 const auto *RD = BaseType->getAsRecordDecl(); 9261 Layout.append(RD->field_begin(), RD->field_end()); 9262 } 9263 } 9264 for (auto &Pair : OverlappedData) { 9265 llvm::stable_sort( 9266 Pair.getSecond(), 9267 [&Layout]( 9268 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 9269 OMPClauseMappableExprCommon::MappableExprComponentListRef 9270 Second) { 9271 auto CI = First.rbegin(); 9272 auto CE = First.rend(); 9273 auto SI = Second.rbegin(); 9274 auto SE = Second.rend(); 9275 for (; CI != CE && SI != SE; ++CI, ++SI) { 9276 if (CI->getAssociatedExpression()->getStmtClass() != 9277 SI->getAssociatedExpression()->getStmtClass()) 9278 break; 9279 // Are we dealing with different variables/fields? 9280 if (CI->getAssociatedDeclaration() != 9281 SI->getAssociatedDeclaration()) 9282 break; 9283 } 9284 9285 // Lists contain the same elements. 9286 if (CI == CE && SI == SE) 9287 return false; 9288 9289 // List with less elements is less than list with more elements. 9290 if (CI == CE || SI == SE) 9291 return CI == CE; 9292 9293 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 9294 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 9295 if (FD1->getParent() == FD2->getParent()) 9296 return FD1->getFieldIndex() < FD2->getFieldIndex(); 9297 const auto *It = 9298 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 9299 return FD == FD1 || FD == FD2; 9300 }); 9301 return *It == FD1; 9302 }); 9303 } 9304 9305 // Associated with a capture, because the mapping flags depend on it. 9306 // Go through all of the elements with the overlapped elements. 9307 bool IsFirstComponentList = true; 9308 for (const auto &Pair : OverlappedData) { 9309 const MapData &L = *Pair.getFirst(); 9310 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9311 OpenMPMapClauseKind MapType; 9312 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9313 bool IsImplicit; 9314 const ValueDecl *Mapper; 9315 const Expr *VarRef; 9316 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9317 L; 9318 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 9319 OverlappedComponents = Pair.getSecond(); 9320 generateInfoForComponentList( 9321 MapType, MapModifiers, llvm::None, Components, CombinedInfo, 9322 PartialStruct, IsFirstComponentList, IsImplicit, Mapper, 9323 /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents); 9324 IsFirstComponentList = false; 9325 } 9326 // Go through other elements without overlapped elements. 9327 for (const MapData &L : DeclComponentLists) { 9328 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9329 OpenMPMapClauseKind MapType; 9330 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9331 bool IsImplicit; 9332 const ValueDecl *Mapper; 9333 const Expr *VarRef; 9334 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9335 L; 9336 auto It = OverlappedData.find(&L); 9337 if (It == OverlappedData.end()) 9338 generateInfoForComponentList(MapType, MapModifiers, llvm::None, 9339 Components, CombinedInfo, PartialStruct, 9340 IsFirstComponentList, IsImplicit, Mapper, 9341 /*ForDeviceAddr=*/false, VD, VarRef); 9342 IsFirstComponentList = false; 9343 } 9344 } 9345 9346 /// Generate the default map information for a given capture \a CI, 9347 /// record field declaration \a RI and captured value \a CV. 9348 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 9349 const FieldDecl &RI, llvm::Value *CV, 9350 MapCombinedInfoTy &CombinedInfo) const { 9351 bool IsImplicit = true; 9352 // Do the default mapping. 9353 if (CI.capturesThis()) { 9354 CombinedInfo.Exprs.push_back(nullptr); 9355 CombinedInfo.BasePointers.push_back(CV); 9356 CombinedInfo.Pointers.push_back(CV); 9357 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 9358 CombinedInfo.Sizes.push_back( 9359 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 9360 CGF.Int64Ty, /*isSigned=*/true)); 9361 // Default map type. 9362 CombinedInfo.Types.push_back(OMP_MAP_TO | OMP_MAP_FROM); 9363 } else if (CI.capturesVariableByCopy()) { 9364 const VarDecl *VD = CI.getCapturedVar(); 9365 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9366 CombinedInfo.BasePointers.push_back(CV); 9367 CombinedInfo.Pointers.push_back(CV); 9368 if (!RI.getType()->isAnyPointerType()) { 9369 // We have to signal to the runtime captures passed by value that are 9370 // not pointers. 9371 CombinedInfo.Types.push_back(OMP_MAP_LITERAL); 9372 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9373 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 9374 } else { 9375 // Pointers are implicitly mapped with a zero size and no flags 9376 // (other than first map that is added for all implicit maps). 9377 CombinedInfo.Types.push_back(OMP_MAP_NONE); 9378 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 9379 } 9380 auto I = FirstPrivateDecls.find(VD); 9381 if (I != FirstPrivateDecls.end()) 9382 IsImplicit = I->getSecond(); 9383 } else { 9384 assert(CI.capturesVariable() && "Expected captured reference."); 9385 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 9386 QualType ElementType = PtrTy->getPointeeType(); 9387 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9388 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 9389 // The default map type for a scalar/complex type is 'to' because by 9390 // default the value doesn't have to be retrieved. For an aggregate 9391 // type, the default is 'tofrom'. 9392 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI)); 9393 const VarDecl *VD = CI.getCapturedVar(); 9394 auto I = FirstPrivateDecls.find(VD); 9395 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9396 CombinedInfo.BasePointers.push_back(CV); 9397 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 9398 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 9399 CV, ElementType, CGF.getContext().getDeclAlign(VD), 9400 AlignmentSource::Decl)); 9401 CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); 9402 } else { 9403 CombinedInfo.Pointers.push_back(CV); 9404 } 9405 if (I != FirstPrivateDecls.end()) 9406 IsImplicit = I->getSecond(); 9407 } 9408 // Every default map produces a single argument which is a target parameter. 9409 CombinedInfo.Types.back() |= OMP_MAP_TARGET_PARAM; 9410 9411 // Add flag stating this is an implicit map. 9412 if (IsImplicit) 9413 CombinedInfo.Types.back() |= OMP_MAP_IMPLICIT; 9414 9415 // No user-defined mapper for default mapping. 9416 CombinedInfo.Mappers.push_back(nullptr); 9417 } 9418 }; 9419 } // anonymous namespace 9420 9421 static void emitNonContiguousDescriptor( 9422 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9423 CGOpenMPRuntime::TargetDataInfo &Info) { 9424 CodeGenModule &CGM = CGF.CGM; 9425 MappableExprsHandler::MapCombinedInfoTy::StructNonContiguousInfo 9426 &NonContigInfo = CombinedInfo.NonContigInfo; 9427 9428 // Build an array of struct descriptor_dim and then assign it to 9429 // offload_args. 9430 // 9431 // struct descriptor_dim { 9432 // uint64_t offset; 9433 // uint64_t count; 9434 // uint64_t stride 9435 // }; 9436 ASTContext &C = CGF.getContext(); 9437 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 9438 RecordDecl *RD; 9439 RD = C.buildImplicitRecord("descriptor_dim"); 9440 RD->startDefinition(); 9441 addFieldToRecordDecl(C, RD, Int64Ty); 9442 addFieldToRecordDecl(C, RD, Int64Ty); 9443 addFieldToRecordDecl(C, RD, Int64Ty); 9444 RD->completeDefinition(); 9445 QualType DimTy = C.getRecordType(RD); 9446 9447 enum { OffsetFD = 0, CountFD, StrideFD }; 9448 // We need two index variable here since the size of "Dims" is the same as the 9449 // size of Components, however, the size of offset, count, and stride is equal 9450 // to the size of base declaration that is non-contiguous. 9451 for (unsigned I = 0, L = 0, E = NonContigInfo.Dims.size(); I < E; ++I) { 9452 // Skip emitting ir if dimension size is 1 since it cannot be 9453 // non-contiguous. 9454 if (NonContigInfo.Dims[I] == 1) 9455 continue; 9456 llvm::APInt Size(/*numBits=*/32, NonContigInfo.Dims[I]); 9457 QualType ArrayTy = 9458 C.getConstantArrayType(DimTy, Size, nullptr, ArrayType::Normal, 0); 9459 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 9460 for (unsigned II = 0, EE = NonContigInfo.Dims[I]; II < EE; ++II) { 9461 unsigned RevIdx = EE - II - 1; 9462 LValue DimsLVal = CGF.MakeAddrLValue( 9463 CGF.Builder.CreateConstArrayGEP(DimsAddr, II), DimTy); 9464 // Offset 9465 LValue OffsetLVal = CGF.EmitLValueForField( 9466 DimsLVal, *std::next(RD->field_begin(), OffsetFD)); 9467 CGF.EmitStoreOfScalar(NonContigInfo.Offsets[L][RevIdx], OffsetLVal); 9468 // Count 9469 LValue CountLVal = CGF.EmitLValueForField( 9470 DimsLVal, *std::next(RD->field_begin(), CountFD)); 9471 CGF.EmitStoreOfScalar(NonContigInfo.Counts[L][RevIdx], CountLVal); 9472 // Stride 9473 LValue StrideLVal = CGF.EmitLValueForField( 9474 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 9475 CGF.EmitStoreOfScalar(NonContigInfo.Strides[L][RevIdx], StrideLVal); 9476 } 9477 // args[I] = &dims 9478 Address DAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9479 DimsAddr, CGM.Int8PtrTy); 9480 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9481 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9482 Info.PointersArray, 0, I); 9483 Address PAddr(P, CGF.getPointerAlign()); 9484 CGF.Builder.CreateStore(DAddr.getPointer(), PAddr); 9485 ++L; 9486 } 9487 } 9488 9489 // Try to extract the base declaration from a `this->x` expression if possible. 9490 static ValueDecl *getDeclFromThisExpr(const Expr *E) { 9491 if (!E) 9492 return nullptr; 9493 9494 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E->IgnoreParenCasts())) 9495 if (const MemberExpr *ME = 9496 dyn_cast<MemberExpr>(OASE->getBase()->IgnoreParenImpCasts())) 9497 return ME->getMemberDecl(); 9498 return nullptr; 9499 } 9500 9501 /// Emit a string constant containing the names of the values mapped to the 9502 /// offloading runtime library. 9503 llvm::Constant * 9504 emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, 9505 MappableExprsHandler::MappingExprInfo &MapExprs) { 9506 9507 if (!MapExprs.getMapDecl() && !MapExprs.getMapExpr()) 9508 return OMPBuilder.getOrCreateDefaultSrcLocStr(); 9509 9510 SourceLocation Loc; 9511 if (!MapExprs.getMapDecl() && MapExprs.getMapExpr()) { 9512 if (const ValueDecl *VD = getDeclFromThisExpr(MapExprs.getMapExpr())) 9513 Loc = VD->getLocation(); 9514 else 9515 Loc = MapExprs.getMapExpr()->getExprLoc(); 9516 } else { 9517 Loc = MapExprs.getMapDecl()->getLocation(); 9518 } 9519 9520 std::string ExprName = ""; 9521 if (MapExprs.getMapExpr()) { 9522 PrintingPolicy P(CGF.getContext().getLangOpts()); 9523 llvm::raw_string_ostream OS(ExprName); 9524 MapExprs.getMapExpr()->printPretty(OS, nullptr, P); 9525 OS.flush(); 9526 } else { 9527 ExprName = MapExprs.getMapDecl()->getNameAsString(); 9528 } 9529 9530 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 9531 return OMPBuilder.getOrCreateSrcLocStr(PLoc.getFilename(), ExprName.c_str(), 9532 PLoc.getLine(), PLoc.getColumn()); 9533 } 9534 9535 /// Emit the arrays used to pass the captures and map information to the 9536 /// offloading runtime library. If there is no map or capture information, 9537 /// return nullptr by reference. 9538 static void emitOffloadingArrays( 9539 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9540 CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, 9541 bool IsNonContiguous = false) { 9542 CodeGenModule &CGM = CGF.CGM; 9543 ASTContext &Ctx = CGF.getContext(); 9544 9545 // Reset the array information. 9546 Info.clearArrayInfo(); 9547 Info.NumberOfPtrs = CombinedInfo.BasePointers.size(); 9548 9549 if (Info.NumberOfPtrs) { 9550 // Detect if we have any capture size requiring runtime evaluation of the 9551 // size so that a constant array could be eventually used. 9552 bool hasRuntimeEvaluationCaptureSize = false; 9553 for (llvm::Value *S : CombinedInfo.Sizes) 9554 if (!isa<llvm::Constant>(S)) { 9555 hasRuntimeEvaluationCaptureSize = true; 9556 break; 9557 } 9558 9559 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 9560 QualType PointerArrayType = Ctx.getConstantArrayType( 9561 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 9562 /*IndexTypeQuals=*/0); 9563 9564 Info.BasePointersArray = 9565 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 9566 Info.PointersArray = 9567 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 9568 Address MappersArray = 9569 CGF.CreateMemTemp(PointerArrayType, ".offload_mappers"); 9570 Info.MappersArray = MappersArray.getPointer(); 9571 9572 // If we don't have any VLA types or other types that require runtime 9573 // evaluation, we can use a constant array for the map sizes, otherwise we 9574 // need to fill up the arrays as we do for the pointers. 9575 QualType Int64Ty = 9576 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 9577 if (hasRuntimeEvaluationCaptureSize) { 9578 QualType SizeArrayType = Ctx.getConstantArrayType( 9579 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 9580 /*IndexTypeQuals=*/0); 9581 Info.SizesArray = 9582 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 9583 } else { 9584 // We expect all the sizes to be constant, so we collect them to create 9585 // a constant array. 9586 SmallVector<llvm::Constant *, 16> ConstSizes; 9587 for (unsigned I = 0, E = CombinedInfo.Sizes.size(); I < E; ++I) { 9588 if (IsNonContiguous && 9589 (CombinedInfo.Types[I] & MappableExprsHandler::OMP_MAP_NON_CONTIG)) { 9590 ConstSizes.push_back(llvm::ConstantInt::get( 9591 CGF.Int64Ty, CombinedInfo.NonContigInfo.Dims[I])); 9592 } else { 9593 ConstSizes.push_back(cast<llvm::Constant>(CombinedInfo.Sizes[I])); 9594 } 9595 } 9596 9597 auto *SizesArrayInit = llvm::ConstantArray::get( 9598 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 9599 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 9600 auto *SizesArrayGbl = new llvm::GlobalVariable( 9601 CGM.getModule(), SizesArrayInit->getType(), 9602 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 9603 SizesArrayInit, Name); 9604 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 9605 Info.SizesArray = SizesArrayGbl; 9606 } 9607 9608 // The map types are always constant so we don't need to generate code to 9609 // fill arrays. Instead, we create an array constant. 9610 SmallVector<uint64_t, 4> Mapping(CombinedInfo.Types.size(), 0); 9611 llvm::copy(CombinedInfo.Types, Mapping.begin()); 9612 std::string MaptypesName = 9613 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 9614 auto *MapTypesArrayGbl = 9615 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName); 9616 Info.MapTypesArray = MapTypesArrayGbl; 9617 9618 // The information types are only built if there is debug information 9619 // requested. 9620 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) { 9621 Info.MapNamesArray = llvm::Constant::getNullValue( 9622 llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo()); 9623 } else { 9624 auto fillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) { 9625 return emitMappingInformation(CGF, OMPBuilder, MapExpr); 9626 }; 9627 SmallVector<llvm::Constant *, 4> InfoMap(CombinedInfo.Exprs.size()); 9628 llvm::transform(CombinedInfo.Exprs, InfoMap.begin(), fillInfoMap); 9629 std::string MapnamesName = 9630 CGM.getOpenMPRuntime().getName({"offload_mapnames"}); 9631 auto *MapNamesArrayGbl = 9632 OMPBuilder.createOffloadMapnames(InfoMap, MapnamesName); 9633 Info.MapNamesArray = MapNamesArrayGbl; 9634 } 9635 9636 // If there's a present map type modifier, it must not be applied to the end 9637 // of a region, so generate a separate map type array in that case. 9638 if (Info.separateBeginEndCalls()) { 9639 bool EndMapTypesDiffer = false; 9640 for (uint64_t &Type : Mapping) { 9641 if (Type & MappableExprsHandler::OMP_MAP_PRESENT) { 9642 Type &= ~MappableExprsHandler::OMP_MAP_PRESENT; 9643 EndMapTypesDiffer = true; 9644 } 9645 } 9646 if (EndMapTypesDiffer) { 9647 MapTypesArrayGbl = 9648 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName); 9649 Info.MapTypesArrayEnd = MapTypesArrayGbl; 9650 } 9651 } 9652 9653 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 9654 llvm::Value *BPVal = *CombinedInfo.BasePointers[I]; 9655 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 9656 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9657 Info.BasePointersArray, 0, I); 9658 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9659 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9660 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9661 CGF.Builder.CreateStore(BPVal, BPAddr); 9662 9663 if (Info.requiresDevicePointerInfo()) 9664 if (const ValueDecl *DevVD = 9665 CombinedInfo.BasePointers[I].getDevicePtrDecl()) 9666 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 9667 9668 llvm::Value *PVal = CombinedInfo.Pointers[I]; 9669 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9670 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9671 Info.PointersArray, 0, I); 9672 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9673 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9674 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9675 CGF.Builder.CreateStore(PVal, PAddr); 9676 9677 if (hasRuntimeEvaluationCaptureSize) { 9678 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 9679 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9680 Info.SizesArray, 9681 /*Idx0=*/0, 9682 /*Idx1=*/I); 9683 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 9684 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(CombinedInfo.Sizes[I], 9685 CGM.Int64Ty, 9686 /*isSigned=*/true), 9687 SAddr); 9688 } 9689 9690 // Fill up the mapper array. 9691 llvm::Value *MFunc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 9692 if (CombinedInfo.Mappers[I]) { 9693 MFunc = CGM.getOpenMPRuntime().getOrCreateUserDefinedMapperFunc( 9694 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I])); 9695 MFunc = CGF.Builder.CreatePointerCast(MFunc, CGM.VoidPtrTy); 9696 Info.HasMapper = true; 9697 } 9698 Address MAddr = CGF.Builder.CreateConstArrayGEP(MappersArray, I); 9699 CGF.Builder.CreateStore(MFunc, MAddr); 9700 } 9701 } 9702 9703 if (!IsNonContiguous || CombinedInfo.NonContigInfo.Offsets.empty() || 9704 Info.NumberOfPtrs == 0) 9705 return; 9706 9707 emitNonContiguousDescriptor(CGF, CombinedInfo, Info); 9708 } 9709 9710 namespace { 9711 /// Additional arguments for emitOffloadingArraysArgument function. 9712 struct ArgumentsOptions { 9713 bool ForEndCall = false; 9714 ArgumentsOptions() = default; 9715 ArgumentsOptions(bool ForEndCall) : ForEndCall(ForEndCall) {} 9716 }; 9717 } // namespace 9718 9719 /// Emit the arguments to be passed to the runtime library based on the 9720 /// arrays of base pointers, pointers, sizes, map types, and mappers. If 9721 /// ForEndCall, emit map types to be passed for the end of the region instead of 9722 /// the beginning. 9723 static void emitOffloadingArraysArgument( 9724 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 9725 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 9726 llvm::Value *&MapTypesArrayArg, llvm::Value *&MapNamesArrayArg, 9727 llvm::Value *&MappersArrayArg, CGOpenMPRuntime::TargetDataInfo &Info, 9728 const ArgumentsOptions &Options = ArgumentsOptions()) { 9729 assert((!Options.ForEndCall || Info.separateBeginEndCalls()) && 9730 "expected region end call to runtime only when end call is separate"); 9731 CodeGenModule &CGM = CGF.CGM; 9732 if (Info.NumberOfPtrs) { 9733 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9734 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9735 Info.BasePointersArray, 9736 /*Idx0=*/0, /*Idx1=*/0); 9737 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9738 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9739 Info.PointersArray, 9740 /*Idx0=*/0, 9741 /*Idx1=*/0); 9742 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9743 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 9744 /*Idx0=*/0, /*Idx1=*/0); 9745 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9746 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9747 Options.ForEndCall && Info.MapTypesArrayEnd ? Info.MapTypesArrayEnd 9748 : Info.MapTypesArray, 9749 /*Idx0=*/0, 9750 /*Idx1=*/0); 9751 9752 // Only emit the mapper information arrays if debug information is 9753 // requested. 9754 if (CGF.CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 9755 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9756 else 9757 MapNamesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9758 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9759 Info.MapNamesArray, 9760 /*Idx0=*/0, 9761 /*Idx1=*/0); 9762 // If there is no user-defined mapper, set the mapper array to nullptr to 9763 // avoid an unnecessary data privatization 9764 if (!Info.HasMapper) 9765 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9766 else 9767 MappersArrayArg = 9768 CGF.Builder.CreatePointerCast(Info.MappersArray, CGM.VoidPtrPtrTy); 9769 } else { 9770 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9771 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9772 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9773 MapTypesArrayArg = 9774 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9775 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9776 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9777 } 9778 } 9779 9780 /// Check for inner distribute directive. 9781 static const OMPExecutableDirective * 9782 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 9783 const auto *CS = D.getInnermostCapturedStmt(); 9784 const auto *Body = 9785 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 9786 const Stmt *ChildStmt = 9787 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9788 9789 if (const auto *NestedDir = 9790 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9791 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 9792 switch (D.getDirectiveKind()) { 9793 case OMPD_target: 9794 if (isOpenMPDistributeDirective(DKind)) 9795 return NestedDir; 9796 if (DKind == OMPD_teams) { 9797 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 9798 /*IgnoreCaptured=*/true); 9799 if (!Body) 9800 return nullptr; 9801 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9802 if (const auto *NND = 9803 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9804 DKind = NND->getDirectiveKind(); 9805 if (isOpenMPDistributeDirective(DKind)) 9806 return NND; 9807 } 9808 } 9809 return nullptr; 9810 case OMPD_target_teams: 9811 if (isOpenMPDistributeDirective(DKind)) 9812 return NestedDir; 9813 return nullptr; 9814 case OMPD_target_parallel: 9815 case OMPD_target_simd: 9816 case OMPD_target_parallel_for: 9817 case OMPD_target_parallel_for_simd: 9818 return nullptr; 9819 case OMPD_target_teams_distribute: 9820 case OMPD_target_teams_distribute_simd: 9821 case OMPD_target_teams_distribute_parallel_for: 9822 case OMPD_target_teams_distribute_parallel_for_simd: 9823 case OMPD_parallel: 9824 case OMPD_for: 9825 case OMPD_parallel_for: 9826 case OMPD_parallel_master: 9827 case OMPD_parallel_sections: 9828 case OMPD_for_simd: 9829 case OMPD_parallel_for_simd: 9830 case OMPD_cancel: 9831 case OMPD_cancellation_point: 9832 case OMPD_ordered: 9833 case OMPD_threadprivate: 9834 case OMPD_allocate: 9835 case OMPD_task: 9836 case OMPD_simd: 9837 case OMPD_tile: 9838 case OMPD_unroll: 9839 case OMPD_sections: 9840 case OMPD_section: 9841 case OMPD_single: 9842 case OMPD_master: 9843 case OMPD_critical: 9844 case OMPD_taskyield: 9845 case OMPD_barrier: 9846 case OMPD_taskwait: 9847 case OMPD_taskgroup: 9848 case OMPD_atomic: 9849 case OMPD_flush: 9850 case OMPD_depobj: 9851 case OMPD_scan: 9852 case OMPD_teams: 9853 case OMPD_target_data: 9854 case OMPD_target_exit_data: 9855 case OMPD_target_enter_data: 9856 case OMPD_distribute: 9857 case OMPD_distribute_simd: 9858 case OMPD_distribute_parallel_for: 9859 case OMPD_distribute_parallel_for_simd: 9860 case OMPD_teams_distribute: 9861 case OMPD_teams_distribute_simd: 9862 case OMPD_teams_distribute_parallel_for: 9863 case OMPD_teams_distribute_parallel_for_simd: 9864 case OMPD_target_update: 9865 case OMPD_declare_simd: 9866 case OMPD_declare_variant: 9867 case OMPD_begin_declare_variant: 9868 case OMPD_end_declare_variant: 9869 case OMPD_declare_target: 9870 case OMPD_end_declare_target: 9871 case OMPD_declare_reduction: 9872 case OMPD_declare_mapper: 9873 case OMPD_taskloop: 9874 case OMPD_taskloop_simd: 9875 case OMPD_master_taskloop: 9876 case OMPD_master_taskloop_simd: 9877 case OMPD_parallel_master_taskloop: 9878 case OMPD_parallel_master_taskloop_simd: 9879 case OMPD_requires: 9880 case OMPD_metadirective: 9881 case OMPD_unknown: 9882 default: 9883 llvm_unreachable("Unexpected directive."); 9884 } 9885 } 9886 9887 return nullptr; 9888 } 9889 9890 /// Emit the user-defined mapper function. The code generation follows the 9891 /// pattern in the example below. 9892 /// \code 9893 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 9894 /// void *base, void *begin, 9895 /// int64_t size, int64_t type, 9896 /// void *name = nullptr) { 9897 /// // Allocate space for an array section first or add a base/begin for 9898 /// // pointer dereference. 9899 /// if ((size > 1 || (base != begin && maptype.IsPtrAndObj)) && 9900 /// !maptype.IsDelete) 9901 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9902 /// size*sizeof(Ty), clearToFromMember(type)); 9903 /// // Map members. 9904 /// for (unsigned i = 0; i < size; i++) { 9905 /// // For each component specified by this mapper: 9906 /// for (auto c : begin[i]->all_components) { 9907 /// if (c.hasMapper()) 9908 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 9909 /// c.arg_type, c.arg_name); 9910 /// else 9911 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 9912 /// c.arg_begin, c.arg_size, c.arg_type, 9913 /// c.arg_name); 9914 /// } 9915 /// } 9916 /// // Delete the array section. 9917 /// if (size > 1 && maptype.IsDelete) 9918 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9919 /// size*sizeof(Ty), clearToFromMember(type)); 9920 /// } 9921 /// \endcode 9922 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 9923 CodeGenFunction *CGF) { 9924 if (UDMMap.count(D) > 0) 9925 return; 9926 ASTContext &C = CGM.getContext(); 9927 QualType Ty = D->getType(); 9928 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 9929 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 9930 auto *MapperVarDecl = 9931 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 9932 SourceLocation Loc = D->getLocation(); 9933 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 9934 9935 // Prepare mapper function arguments and attributes. 9936 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9937 C.VoidPtrTy, ImplicitParamDecl::Other); 9938 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9939 ImplicitParamDecl::Other); 9940 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9941 C.VoidPtrTy, ImplicitParamDecl::Other); 9942 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9943 ImplicitParamDecl::Other); 9944 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9945 ImplicitParamDecl::Other); 9946 ImplicitParamDecl NameArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9947 ImplicitParamDecl::Other); 9948 FunctionArgList Args; 9949 Args.push_back(&HandleArg); 9950 Args.push_back(&BaseArg); 9951 Args.push_back(&BeginArg); 9952 Args.push_back(&SizeArg); 9953 Args.push_back(&TypeArg); 9954 Args.push_back(&NameArg); 9955 const CGFunctionInfo &FnInfo = 9956 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 9957 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 9958 SmallString<64> TyStr; 9959 llvm::raw_svector_ostream Out(TyStr); 9960 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 9961 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 9962 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 9963 Name, &CGM.getModule()); 9964 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 9965 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 9966 // Start the mapper function code generation. 9967 CodeGenFunction MapperCGF(CGM); 9968 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 9969 // Compute the starting and end addresses of array elements. 9970 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 9971 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 9972 C.getPointerType(Int64Ty), Loc); 9973 // Prepare common arguments for array initiation and deletion. 9974 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 9975 MapperCGF.GetAddrOfLocalVar(&HandleArg), 9976 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9977 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 9978 MapperCGF.GetAddrOfLocalVar(&BaseArg), 9979 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9980 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 9981 MapperCGF.GetAddrOfLocalVar(&BeginArg), 9982 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9983 // Convert the size in bytes into the number of array elements. 9984 Size = MapperCGF.Builder.CreateExactUDiv( 9985 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9986 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 9987 BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy)); 9988 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP( 9989 PtrBegin->getType()->getPointerElementType(), PtrBegin, Size); 9990 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 9991 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 9992 C.getPointerType(Int64Ty), Loc); 9993 llvm::Value *MapName = MapperCGF.EmitLoadOfScalar( 9994 MapperCGF.GetAddrOfLocalVar(&NameArg), 9995 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9996 9997 // Emit array initiation if this is an array section and \p MapType indicates 9998 // that memory allocation is required. 9999 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 10000 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 10001 MapName, ElementSize, HeadBB, /*IsInit=*/true); 10002 10003 // Emit a for loop to iterate through SizeArg of elements and map all of them. 10004 10005 // Emit the loop header block. 10006 MapperCGF.EmitBlock(HeadBB); 10007 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 10008 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 10009 // Evaluate whether the initial condition is satisfied. 10010 llvm::Value *IsEmpty = 10011 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 10012 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 10013 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 10014 10015 // Emit the loop body block. 10016 MapperCGF.EmitBlock(BodyBB); 10017 llvm::BasicBlock *LastBB = BodyBB; 10018 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 10019 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 10020 PtrPHI->addIncoming(PtrBegin, EntryBB); 10021 Address PtrCurrent = 10022 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 10023 .getAlignment() 10024 .alignmentOfArrayElement(ElementSize)); 10025 // Privatize the declared variable of mapper to be the current array element. 10026 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 10027 Scope.addPrivate(MapperVarDecl, [PtrCurrent]() { return PtrCurrent; }); 10028 (void)Scope.Privatize(); 10029 10030 // Get map clause information. Fill up the arrays with all mapped variables. 10031 MappableExprsHandler::MapCombinedInfoTy Info; 10032 MappableExprsHandler MEHandler(*D, MapperCGF); 10033 MEHandler.generateAllInfoForMapper(Info); 10034 10035 // Call the runtime API __tgt_mapper_num_components to get the number of 10036 // pre-existing components. 10037 llvm::Value *OffloadingArgs[] = {Handle}; 10038 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 10039 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 10040 OMPRTL___tgt_mapper_num_components), 10041 OffloadingArgs); 10042 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 10043 PreviousSize, 10044 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 10045 10046 // Fill up the runtime mapper handle for all components. 10047 for (unsigned I = 0; I < Info.BasePointers.size(); ++I) { 10048 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 10049 *Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 10050 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 10051 Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 10052 llvm::Value *CurSizeArg = Info.Sizes[I]; 10053 llvm::Value *CurNameArg = 10054 (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 10055 ? llvm::ConstantPointerNull::get(CGM.VoidPtrTy) 10056 : emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]); 10057 10058 // Extract the MEMBER_OF field from the map type. 10059 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(Info.Types[I]); 10060 llvm::Value *MemberMapType = 10061 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 10062 10063 // Combine the map type inherited from user-defined mapper with that 10064 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 10065 // bits of the \a MapType, which is the input argument of the mapper 10066 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 10067 // bits of MemberMapType. 10068 // [OpenMP 5.0], 1.2.6. map-type decay. 10069 // | alloc | to | from | tofrom | release | delete 10070 // ---------------------------------------------------------- 10071 // alloc | alloc | alloc | alloc | alloc | release | delete 10072 // to | alloc | to | alloc | to | release | delete 10073 // from | alloc | alloc | from | from | release | delete 10074 // tofrom | alloc | to | from | tofrom | release | delete 10075 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 10076 MapType, 10077 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 10078 MappableExprsHandler::OMP_MAP_FROM)); 10079 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 10080 llvm::BasicBlock *AllocElseBB = 10081 MapperCGF.createBasicBlock("omp.type.alloc.else"); 10082 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 10083 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 10084 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 10085 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 10086 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 10087 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 10088 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 10089 MapperCGF.EmitBlock(AllocBB); 10090 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 10091 MemberMapType, 10092 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 10093 MappableExprsHandler::OMP_MAP_FROM))); 10094 MapperCGF.Builder.CreateBr(EndBB); 10095 MapperCGF.EmitBlock(AllocElseBB); 10096 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 10097 LeftToFrom, 10098 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 10099 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 10100 // In case of to, clear OMP_MAP_FROM. 10101 MapperCGF.EmitBlock(ToBB); 10102 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 10103 MemberMapType, 10104 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 10105 MapperCGF.Builder.CreateBr(EndBB); 10106 MapperCGF.EmitBlock(ToElseBB); 10107 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 10108 LeftToFrom, 10109 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 10110 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 10111 // In case of from, clear OMP_MAP_TO. 10112 MapperCGF.EmitBlock(FromBB); 10113 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 10114 MemberMapType, 10115 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 10116 // In case of tofrom, do nothing. 10117 MapperCGF.EmitBlock(EndBB); 10118 LastBB = EndBB; 10119 llvm::PHINode *CurMapType = 10120 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 10121 CurMapType->addIncoming(AllocMapType, AllocBB); 10122 CurMapType->addIncoming(ToMapType, ToBB); 10123 CurMapType->addIncoming(FromMapType, FromBB); 10124 CurMapType->addIncoming(MemberMapType, ToElseBB); 10125 10126 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 10127 CurSizeArg, CurMapType, CurNameArg}; 10128 if (Info.Mappers[I]) { 10129 // Call the corresponding mapper function. 10130 llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc( 10131 cast<OMPDeclareMapperDecl>(Info.Mappers[I])); 10132 assert(MapperFunc && "Expect a valid mapper function is available."); 10133 MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs); 10134 } else { 10135 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 10136 // data structure. 10137 MapperCGF.EmitRuntimeCall( 10138 OMPBuilder.getOrCreateRuntimeFunction( 10139 CGM.getModule(), OMPRTL___tgt_push_mapper_component), 10140 OffloadingArgs); 10141 } 10142 } 10143 10144 // Update the pointer to point to the next element that needs to be mapped, 10145 // and check whether we have mapped all elements. 10146 llvm::Type *ElemTy = PtrPHI->getType()->getPointerElementType(); 10147 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 10148 ElemTy, PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 10149 PtrPHI->addIncoming(PtrNext, LastBB); 10150 llvm::Value *IsDone = 10151 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 10152 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 10153 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 10154 10155 MapperCGF.EmitBlock(ExitBB); 10156 // Emit array deletion if this is an array section and \p MapType indicates 10157 // that deletion is required. 10158 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 10159 MapName, ElementSize, DoneBB, /*IsInit=*/false); 10160 10161 // Emit the function exit block. 10162 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 10163 MapperCGF.FinishFunction(); 10164 UDMMap.try_emplace(D, Fn); 10165 if (CGF) { 10166 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 10167 Decls.second.push_back(D); 10168 } 10169 } 10170 10171 /// Emit the array initialization or deletion portion for user-defined mapper 10172 /// code generation. First, it evaluates whether an array section is mapped and 10173 /// whether the \a MapType instructs to delete this section. If \a IsInit is 10174 /// true, and \a MapType indicates to not delete this array, array 10175 /// initialization code is generated. If \a IsInit is false, and \a MapType 10176 /// indicates to not this array, array deletion code is generated. 10177 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 10178 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 10179 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 10180 llvm::Value *MapName, CharUnits ElementSize, llvm::BasicBlock *ExitBB, 10181 bool IsInit) { 10182 StringRef Prefix = IsInit ? ".init" : ".del"; 10183 10184 // Evaluate if this is an array section. 10185 llvm::BasicBlock *BodyBB = 10186 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 10187 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGT( 10188 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 10189 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 10190 MapType, 10191 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 10192 llvm::Value *DeleteCond; 10193 llvm::Value *Cond; 10194 if (IsInit) { 10195 // base != begin? 10196 llvm::Value *BaseIsBegin = MapperCGF.Builder.CreateIsNotNull( 10197 MapperCGF.Builder.CreatePtrDiff(Base, Begin)); 10198 // IsPtrAndObj? 10199 llvm::Value *PtrAndObjBit = MapperCGF.Builder.CreateAnd( 10200 MapType, 10201 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_PTR_AND_OBJ)); 10202 PtrAndObjBit = MapperCGF.Builder.CreateIsNotNull(PtrAndObjBit); 10203 BaseIsBegin = MapperCGF.Builder.CreateAnd(BaseIsBegin, PtrAndObjBit); 10204 Cond = MapperCGF.Builder.CreateOr(IsArray, BaseIsBegin); 10205 DeleteCond = MapperCGF.Builder.CreateIsNull( 10206 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 10207 } else { 10208 Cond = IsArray; 10209 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 10210 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 10211 } 10212 Cond = MapperCGF.Builder.CreateAnd(Cond, DeleteCond); 10213 MapperCGF.Builder.CreateCondBr(Cond, BodyBB, ExitBB); 10214 10215 MapperCGF.EmitBlock(BodyBB); 10216 // Get the array size by multiplying element size and element number (i.e., \p 10217 // Size). 10218 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 10219 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 10220 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 10221 // memory allocation/deletion purpose only. 10222 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 10223 MapType, 10224 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 10225 MappableExprsHandler::OMP_MAP_FROM))); 10226 MapTypeArg = MapperCGF.Builder.CreateOr( 10227 MapTypeArg, 10228 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_IMPLICIT)); 10229 10230 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 10231 // data structure. 10232 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, 10233 ArraySize, MapTypeArg, MapName}; 10234 MapperCGF.EmitRuntimeCall( 10235 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 10236 OMPRTL___tgt_push_mapper_component), 10237 OffloadingArgs); 10238 } 10239 10240 llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc( 10241 const OMPDeclareMapperDecl *D) { 10242 auto I = UDMMap.find(D); 10243 if (I != UDMMap.end()) 10244 return I->second; 10245 emitUserDefinedMapper(D); 10246 return UDMMap.lookup(D); 10247 } 10248 10249 void CGOpenMPRuntime::emitTargetNumIterationsCall( 10250 CodeGenFunction &CGF, const OMPExecutableDirective &D, 10251 llvm::Value *DeviceID, 10252 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 10253 const OMPLoopDirective &D)> 10254 SizeEmitter) { 10255 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 10256 const OMPExecutableDirective *TD = &D; 10257 // Get nested teams distribute kind directive, if any. 10258 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 10259 TD = getNestedDistributeDirective(CGM.getContext(), D); 10260 if (!TD) 10261 return; 10262 const auto *LD = cast<OMPLoopDirective>(TD); 10263 auto &&CodeGen = [LD, DeviceID, SizeEmitter, &D, this](CodeGenFunction &CGF, 10264 PrePostActionTy &) { 10265 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 10266 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10267 llvm::Value *Args[] = {RTLoc, DeviceID, NumIterations}; 10268 CGF.EmitRuntimeCall( 10269 OMPBuilder.getOrCreateRuntimeFunction( 10270 CGM.getModule(), OMPRTL___kmpc_push_target_tripcount_mapper), 10271 Args); 10272 } 10273 }; 10274 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 10275 } 10276 10277 void CGOpenMPRuntime::emitTargetCall( 10278 CodeGenFunction &CGF, const OMPExecutableDirective &D, 10279 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 10280 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 10281 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 10282 const OMPLoopDirective &D)> 10283 SizeEmitter) { 10284 if (!CGF.HaveInsertPoint()) 10285 return; 10286 10287 assert(OutlinedFn && "Invalid outlined function!"); 10288 10289 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 10290 D.hasClausesOfKind<OMPNowaitClause>(); 10291 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 10292 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 10293 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 10294 PrePostActionTy &) { 10295 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10296 }; 10297 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 10298 10299 CodeGenFunction::OMPTargetDataInfo InputInfo; 10300 llvm::Value *MapTypesArray = nullptr; 10301 llvm::Value *MapNamesArray = nullptr; 10302 // Fill up the pointer arrays and transfer execution to the device. 10303 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 10304 &MapTypesArray, &MapNamesArray, &CS, RequiresOuterTask, 10305 &CapturedVars, 10306 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 10307 if (Device.getInt() == OMPC_DEVICE_ancestor) { 10308 // Reverse offloading is not supported, so just execute on the host. 10309 if (RequiresOuterTask) { 10310 CapturedVars.clear(); 10311 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10312 } 10313 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10314 return; 10315 } 10316 10317 // On top of the arrays that were filled up, the target offloading call 10318 // takes as arguments the device id as well as the host pointer. The host 10319 // pointer is used by the runtime library to identify the current target 10320 // region, so it only has to be unique and not necessarily point to 10321 // anything. It could be the pointer to the outlined function that 10322 // implements the target region, but we aren't using that so that the 10323 // compiler doesn't need to keep that, and could therefore inline the host 10324 // function if proven worthwhile during optimization. 10325 10326 // From this point on, we need to have an ID of the target region defined. 10327 assert(OutlinedFnID && "Invalid outlined function ID!"); 10328 10329 // Emit device ID if any. 10330 llvm::Value *DeviceID; 10331 if (Device.getPointer()) { 10332 assert((Device.getInt() == OMPC_DEVICE_unknown || 10333 Device.getInt() == OMPC_DEVICE_device_num) && 10334 "Expected device_num modifier."); 10335 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer()); 10336 DeviceID = 10337 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true); 10338 } else { 10339 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10340 } 10341 10342 // Emit the number of elements in the offloading arrays. 10343 llvm::Value *PointerNum = 10344 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10345 10346 // Return value of the runtime offloading call. 10347 llvm::Value *Return; 10348 10349 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 10350 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 10351 10352 // Source location for the ident struct 10353 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10354 10355 // Emit tripcount for the target loop-based directive. 10356 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 10357 10358 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10359 // The target region is an outlined function launched by the runtime 10360 // via calls __tgt_target() or __tgt_target_teams(). 10361 // 10362 // __tgt_target() launches a target region with one team and one thread, 10363 // executing a serial region. This master thread may in turn launch 10364 // more threads within its team upon encountering a parallel region, 10365 // however, no additional teams can be launched on the device. 10366 // 10367 // __tgt_target_teams() launches a target region with one or more teams, 10368 // each with one or more threads. This call is required for target 10369 // constructs such as: 10370 // 'target teams' 10371 // 'target' / 'teams' 10372 // 'target teams distribute parallel for' 10373 // 'target parallel' 10374 // and so on. 10375 // 10376 // Note that on the host and CPU targets, the runtime implementation of 10377 // these calls simply call the outlined function without forking threads. 10378 // The outlined functions themselves have runtime calls to 10379 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 10380 // the compiler in emitTeamsCall() and emitParallelCall(). 10381 // 10382 // In contrast, on the NVPTX target, the implementation of 10383 // __tgt_target_teams() launches a GPU kernel with the requested number 10384 // of teams and threads so no additional calls to the runtime are required. 10385 if (NumTeams) { 10386 // If we have NumTeams defined this means that we have an enclosed teams 10387 // region. Therefore we also expect to have NumThreads defined. These two 10388 // values should be defined in the presence of a teams directive, 10389 // regardless of having any clauses associated. If the user is using teams 10390 // but no clauses, these two values will be the default that should be 10391 // passed to the runtime library - a 32-bit integer with the value zero. 10392 assert(NumThreads && "Thread limit expression should be available along " 10393 "with number of teams."); 10394 SmallVector<llvm::Value *> OffloadingArgs = { 10395 RTLoc, 10396 DeviceID, 10397 OutlinedFnID, 10398 PointerNum, 10399 InputInfo.BasePointersArray.getPointer(), 10400 InputInfo.PointersArray.getPointer(), 10401 InputInfo.SizesArray.getPointer(), 10402 MapTypesArray, 10403 MapNamesArray, 10404 InputInfo.MappersArray.getPointer(), 10405 NumTeams, 10406 NumThreads}; 10407 if (HasNowait) { 10408 // Add int32_t depNum = 0, void *depList = nullptr, int32_t 10409 // noAliasDepNum = 0, void *noAliasDepList = nullptr. 10410 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10411 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10412 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10413 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10414 } 10415 Return = CGF.EmitRuntimeCall( 10416 OMPBuilder.getOrCreateRuntimeFunction( 10417 CGM.getModule(), HasNowait 10418 ? OMPRTL___tgt_target_teams_nowait_mapper 10419 : OMPRTL___tgt_target_teams_mapper), 10420 OffloadingArgs); 10421 } else { 10422 SmallVector<llvm::Value *> OffloadingArgs = { 10423 RTLoc, 10424 DeviceID, 10425 OutlinedFnID, 10426 PointerNum, 10427 InputInfo.BasePointersArray.getPointer(), 10428 InputInfo.PointersArray.getPointer(), 10429 InputInfo.SizesArray.getPointer(), 10430 MapTypesArray, 10431 MapNamesArray, 10432 InputInfo.MappersArray.getPointer()}; 10433 if (HasNowait) { 10434 // Add int32_t depNum = 0, void *depList = nullptr, int32_t 10435 // noAliasDepNum = 0, void *noAliasDepList = nullptr. 10436 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10437 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10438 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10439 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10440 } 10441 Return = CGF.EmitRuntimeCall( 10442 OMPBuilder.getOrCreateRuntimeFunction( 10443 CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper 10444 : OMPRTL___tgt_target_mapper), 10445 OffloadingArgs); 10446 } 10447 10448 // Check the error code and execute the host version if required. 10449 llvm::BasicBlock *OffloadFailedBlock = 10450 CGF.createBasicBlock("omp_offload.failed"); 10451 llvm::BasicBlock *OffloadContBlock = 10452 CGF.createBasicBlock("omp_offload.cont"); 10453 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 10454 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 10455 10456 CGF.EmitBlock(OffloadFailedBlock); 10457 if (RequiresOuterTask) { 10458 CapturedVars.clear(); 10459 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10460 } 10461 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10462 CGF.EmitBranch(OffloadContBlock); 10463 10464 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 10465 }; 10466 10467 // Notify that the host version must be executed. 10468 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 10469 RequiresOuterTask](CodeGenFunction &CGF, 10470 PrePostActionTy &) { 10471 if (RequiresOuterTask) { 10472 CapturedVars.clear(); 10473 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10474 } 10475 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10476 }; 10477 10478 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 10479 &MapNamesArray, &CapturedVars, RequiresOuterTask, 10480 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 10481 // Fill up the arrays with all the captured variables. 10482 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 10483 10484 // Get mappable expression information. 10485 MappableExprsHandler MEHandler(D, CGF); 10486 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 10487 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet; 10488 10489 auto RI = CS.getCapturedRecordDecl()->field_begin(); 10490 auto *CV = CapturedVars.begin(); 10491 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 10492 CE = CS.capture_end(); 10493 CI != CE; ++CI, ++RI, ++CV) { 10494 MappableExprsHandler::MapCombinedInfoTy CurInfo; 10495 MappableExprsHandler::StructRangeInfoTy PartialStruct; 10496 10497 // VLA sizes are passed to the outlined region by copy and do not have map 10498 // information associated. 10499 if (CI->capturesVariableArrayType()) { 10500 CurInfo.Exprs.push_back(nullptr); 10501 CurInfo.BasePointers.push_back(*CV); 10502 CurInfo.Pointers.push_back(*CV); 10503 CurInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 10504 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 10505 // Copy to the device as an argument. No need to retrieve it. 10506 CurInfo.Types.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 10507 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 10508 MappableExprsHandler::OMP_MAP_IMPLICIT); 10509 CurInfo.Mappers.push_back(nullptr); 10510 } else { 10511 // If we have any information in the map clause, we use it, otherwise we 10512 // just do a default mapping. 10513 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct); 10514 if (!CI->capturesThis()) 10515 MappedVarSet.insert(CI->getCapturedVar()); 10516 else 10517 MappedVarSet.insert(nullptr); 10518 if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid()) 10519 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo); 10520 // Generate correct mapping for variables captured by reference in 10521 // lambdas. 10522 if (CI->capturesVariable()) 10523 MEHandler.generateInfoForLambdaCaptures(CI->getCapturedVar(), *CV, 10524 CurInfo, LambdaPointers); 10525 } 10526 // We expect to have at least an element of information for this capture. 10527 assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) && 10528 "Non-existing map pointer for capture!"); 10529 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() && 10530 CurInfo.BasePointers.size() == CurInfo.Sizes.size() && 10531 CurInfo.BasePointers.size() == CurInfo.Types.size() && 10532 CurInfo.BasePointers.size() == CurInfo.Mappers.size() && 10533 "Inconsistent map information sizes!"); 10534 10535 // If there is an entry in PartialStruct it means we have a struct with 10536 // individual members mapped. Emit an extra combined entry. 10537 if (PartialStruct.Base.isValid()) { 10538 CombinedInfo.append(PartialStruct.PreliminaryMapData); 10539 MEHandler.emitCombinedEntry( 10540 CombinedInfo, CurInfo.Types, PartialStruct, nullptr, 10541 !PartialStruct.PreliminaryMapData.BasePointers.empty()); 10542 } 10543 10544 // We need to append the results of this capture to what we already have. 10545 CombinedInfo.append(CurInfo); 10546 } 10547 // Adjust MEMBER_OF flags for the lambdas captures. 10548 MEHandler.adjustMemberOfForLambdaCaptures( 10549 LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers, 10550 CombinedInfo.Types); 10551 // Map any list items in a map clause that were not captures because they 10552 // weren't referenced within the construct. 10553 MEHandler.generateAllInfo(CombinedInfo, MappedVarSet); 10554 10555 TargetDataInfo Info; 10556 // Fill up the arrays and create the arguments. 10557 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder); 10558 emitOffloadingArraysArgument( 10559 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 10560 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 10561 {/*ForEndTask=*/false}); 10562 10563 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10564 InputInfo.BasePointersArray = 10565 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10566 InputInfo.PointersArray = 10567 Address(Info.PointersArray, CGM.getPointerAlign()); 10568 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 10569 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 10570 MapTypesArray = Info.MapTypesArray; 10571 MapNamesArray = Info.MapNamesArray; 10572 if (RequiresOuterTask) 10573 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10574 else 10575 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10576 }; 10577 10578 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 10579 CodeGenFunction &CGF, PrePostActionTy &) { 10580 if (RequiresOuterTask) { 10581 CodeGenFunction::OMPTargetDataInfo InputInfo; 10582 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 10583 } else { 10584 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 10585 } 10586 }; 10587 10588 // If we have a target function ID it means that we need to support 10589 // offloading, otherwise, just execute on the host. We need to execute on host 10590 // regardless of the conditional in the if clause if, e.g., the user do not 10591 // specify target triples. 10592 if (OutlinedFnID) { 10593 if (IfCond) { 10594 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 10595 } else { 10596 RegionCodeGenTy ThenRCG(TargetThenGen); 10597 ThenRCG(CGF); 10598 } 10599 } else { 10600 RegionCodeGenTy ElseRCG(TargetElseGen); 10601 ElseRCG(CGF); 10602 } 10603 } 10604 10605 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 10606 StringRef ParentName) { 10607 if (!S) 10608 return; 10609 10610 // Codegen OMP target directives that offload compute to the device. 10611 bool RequiresDeviceCodegen = 10612 isa<OMPExecutableDirective>(S) && 10613 isOpenMPTargetExecutionDirective( 10614 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 10615 10616 if (RequiresDeviceCodegen) { 10617 const auto &E = *cast<OMPExecutableDirective>(S); 10618 unsigned DeviceID; 10619 unsigned FileID; 10620 unsigned Line; 10621 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 10622 FileID, Line); 10623 10624 // Is this a target region that should not be emitted as an entry point? If 10625 // so just signal we are done with this target region. 10626 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 10627 ParentName, Line)) 10628 return; 10629 10630 switch (E.getDirectiveKind()) { 10631 case OMPD_target: 10632 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 10633 cast<OMPTargetDirective>(E)); 10634 break; 10635 case OMPD_target_parallel: 10636 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 10637 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 10638 break; 10639 case OMPD_target_teams: 10640 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 10641 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 10642 break; 10643 case OMPD_target_teams_distribute: 10644 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 10645 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 10646 break; 10647 case OMPD_target_teams_distribute_simd: 10648 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 10649 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 10650 break; 10651 case OMPD_target_parallel_for: 10652 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 10653 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 10654 break; 10655 case OMPD_target_parallel_for_simd: 10656 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 10657 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 10658 break; 10659 case OMPD_target_simd: 10660 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 10661 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 10662 break; 10663 case OMPD_target_teams_distribute_parallel_for: 10664 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 10665 CGM, ParentName, 10666 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 10667 break; 10668 case OMPD_target_teams_distribute_parallel_for_simd: 10669 CodeGenFunction:: 10670 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 10671 CGM, ParentName, 10672 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 10673 break; 10674 case OMPD_parallel: 10675 case OMPD_for: 10676 case OMPD_parallel_for: 10677 case OMPD_parallel_master: 10678 case OMPD_parallel_sections: 10679 case OMPD_for_simd: 10680 case OMPD_parallel_for_simd: 10681 case OMPD_cancel: 10682 case OMPD_cancellation_point: 10683 case OMPD_ordered: 10684 case OMPD_threadprivate: 10685 case OMPD_allocate: 10686 case OMPD_task: 10687 case OMPD_simd: 10688 case OMPD_tile: 10689 case OMPD_unroll: 10690 case OMPD_sections: 10691 case OMPD_section: 10692 case OMPD_single: 10693 case OMPD_master: 10694 case OMPD_critical: 10695 case OMPD_taskyield: 10696 case OMPD_barrier: 10697 case OMPD_taskwait: 10698 case OMPD_taskgroup: 10699 case OMPD_atomic: 10700 case OMPD_flush: 10701 case OMPD_depobj: 10702 case OMPD_scan: 10703 case OMPD_teams: 10704 case OMPD_target_data: 10705 case OMPD_target_exit_data: 10706 case OMPD_target_enter_data: 10707 case OMPD_distribute: 10708 case OMPD_distribute_simd: 10709 case OMPD_distribute_parallel_for: 10710 case OMPD_distribute_parallel_for_simd: 10711 case OMPD_teams_distribute: 10712 case OMPD_teams_distribute_simd: 10713 case OMPD_teams_distribute_parallel_for: 10714 case OMPD_teams_distribute_parallel_for_simd: 10715 case OMPD_target_update: 10716 case OMPD_declare_simd: 10717 case OMPD_declare_variant: 10718 case OMPD_begin_declare_variant: 10719 case OMPD_end_declare_variant: 10720 case OMPD_declare_target: 10721 case OMPD_end_declare_target: 10722 case OMPD_declare_reduction: 10723 case OMPD_declare_mapper: 10724 case OMPD_taskloop: 10725 case OMPD_taskloop_simd: 10726 case OMPD_master_taskloop: 10727 case OMPD_master_taskloop_simd: 10728 case OMPD_parallel_master_taskloop: 10729 case OMPD_parallel_master_taskloop_simd: 10730 case OMPD_requires: 10731 case OMPD_metadirective: 10732 case OMPD_unknown: 10733 default: 10734 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 10735 } 10736 return; 10737 } 10738 10739 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 10740 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 10741 return; 10742 10743 scanForTargetRegionsFunctions(E->getRawStmt(), ParentName); 10744 return; 10745 } 10746 10747 // If this is a lambda function, look into its body. 10748 if (const auto *L = dyn_cast<LambdaExpr>(S)) 10749 S = L->getBody(); 10750 10751 // Keep looking for target regions recursively. 10752 for (const Stmt *II : S->children()) 10753 scanForTargetRegionsFunctions(II, ParentName); 10754 } 10755 10756 static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice) { 10757 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10758 OMPDeclareTargetDeclAttr::getDeviceType(VD); 10759 if (!DevTy) 10760 return false; 10761 // Do not emit device_type(nohost) functions for the host. 10762 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 10763 return true; 10764 // Do not emit device_type(host) functions for the device. 10765 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host) 10766 return true; 10767 return false; 10768 } 10769 10770 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 10771 // If emitting code for the host, we do not process FD here. Instead we do 10772 // the normal code generation. 10773 if (!CGM.getLangOpts().OpenMPIsDevice) { 10774 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) 10775 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD), 10776 CGM.getLangOpts().OpenMPIsDevice)) 10777 return true; 10778 return false; 10779 } 10780 10781 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 10782 // Try to detect target regions in the function. 10783 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 10784 StringRef Name = CGM.getMangledName(GD); 10785 scanForTargetRegionsFunctions(FD->getBody(), Name); 10786 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD), 10787 CGM.getLangOpts().OpenMPIsDevice)) 10788 return true; 10789 } 10790 10791 // Do not to emit function if it is not marked as declare target. 10792 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 10793 AlreadyEmittedTargetDecls.count(VD) == 0; 10794 } 10795 10796 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 10797 if (isAssumedToBeNotEmitted(cast<ValueDecl>(GD.getDecl()), 10798 CGM.getLangOpts().OpenMPIsDevice)) 10799 return true; 10800 10801 if (!CGM.getLangOpts().OpenMPIsDevice) 10802 return false; 10803 10804 // Check if there are Ctors/Dtors in this declaration and look for target 10805 // regions in it. We use the complete variant to produce the kernel name 10806 // mangling. 10807 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 10808 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 10809 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 10810 StringRef ParentName = 10811 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 10812 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 10813 } 10814 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 10815 StringRef ParentName = 10816 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 10817 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 10818 } 10819 } 10820 10821 // Do not to emit variable if it is not marked as declare target. 10822 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10823 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 10824 cast<VarDecl>(GD.getDecl())); 10825 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 10826 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10827 HasRequiresUnifiedSharedMemory)) { 10828 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 10829 return true; 10830 } 10831 return false; 10832 } 10833 10834 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 10835 llvm::Constant *Addr) { 10836 if (CGM.getLangOpts().OMPTargetTriples.empty() && 10837 !CGM.getLangOpts().OpenMPIsDevice) 10838 return; 10839 10840 // If we have host/nohost variables, they do not need to be registered. 10841 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10842 OMPDeclareTargetDeclAttr::getDeviceType(VD); 10843 if (DevTy && DevTy.getValue() != OMPDeclareTargetDeclAttr::DT_Any) 10844 return; 10845 10846 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10847 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10848 if (!Res) { 10849 if (CGM.getLangOpts().OpenMPIsDevice) { 10850 // Register non-target variables being emitted in device code (debug info 10851 // may cause this). 10852 StringRef VarName = CGM.getMangledName(VD); 10853 EmittedNonTargetVariables.try_emplace(VarName, Addr); 10854 } 10855 return; 10856 } 10857 // Register declare target variables. 10858 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 10859 StringRef VarName; 10860 CharUnits VarSize; 10861 llvm::GlobalValue::LinkageTypes Linkage; 10862 10863 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10864 !HasRequiresUnifiedSharedMemory) { 10865 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10866 VarName = CGM.getMangledName(VD); 10867 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 10868 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 10869 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 10870 } else { 10871 VarSize = CharUnits::Zero(); 10872 } 10873 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 10874 // Temp solution to prevent optimizations of the internal variables. 10875 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 10876 // Do not create a "ref-variable" if the original is not also available 10877 // on the host. 10878 if (!OffloadEntriesInfoManager.hasDeviceGlobalVarEntryInfo(VarName)) 10879 return; 10880 std::string RefName = getName({VarName, "ref"}); 10881 if (!CGM.GetGlobalValue(RefName)) { 10882 llvm::Constant *AddrRef = 10883 getOrCreateInternalVariable(Addr->getType(), RefName); 10884 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 10885 GVAddrRef->setConstant(/*Val=*/true); 10886 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 10887 GVAddrRef->setInitializer(Addr); 10888 CGM.addCompilerUsedGlobal(GVAddrRef); 10889 } 10890 } 10891 } else { 10892 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 10893 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10894 HasRequiresUnifiedSharedMemory)) && 10895 "Declare target attribute must link or to with unified memory."); 10896 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 10897 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 10898 else 10899 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10900 10901 if (CGM.getLangOpts().OpenMPIsDevice) { 10902 VarName = Addr->getName(); 10903 Addr = nullptr; 10904 } else { 10905 VarName = getAddrOfDeclareTargetVar(VD).getName(); 10906 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 10907 } 10908 VarSize = CGM.getPointerSize(); 10909 Linkage = llvm::GlobalValue::WeakAnyLinkage; 10910 } 10911 10912 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10913 VarName, Addr, VarSize, Flags, Linkage); 10914 } 10915 10916 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 10917 if (isa<FunctionDecl>(GD.getDecl()) || 10918 isa<OMPDeclareReductionDecl>(GD.getDecl())) 10919 return emitTargetFunctions(GD); 10920 10921 return emitTargetGlobalVariable(GD); 10922 } 10923 10924 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 10925 for (const VarDecl *VD : DeferredGlobalVariables) { 10926 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10927 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10928 if (!Res) 10929 continue; 10930 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10931 !HasRequiresUnifiedSharedMemory) { 10932 CGM.EmitGlobal(VD); 10933 } else { 10934 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 10935 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10936 HasRequiresUnifiedSharedMemory)) && 10937 "Expected link clause or to clause with unified memory."); 10938 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 10939 } 10940 } 10941 } 10942 10943 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 10944 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 10945 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 10946 " Expected target-based directive."); 10947 } 10948 10949 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 10950 for (const OMPClause *Clause : D->clauselists()) { 10951 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 10952 HasRequiresUnifiedSharedMemory = true; 10953 } else if (const auto *AC = 10954 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 10955 switch (AC->getAtomicDefaultMemOrderKind()) { 10956 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 10957 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 10958 break; 10959 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 10960 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 10961 break; 10962 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 10963 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 10964 break; 10965 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 10966 break; 10967 } 10968 } 10969 } 10970 } 10971 10972 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 10973 return RequiresAtomicOrdering; 10974 } 10975 10976 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 10977 LangAS &AS) { 10978 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 10979 return false; 10980 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 10981 switch(A->getAllocatorType()) { 10982 case OMPAllocateDeclAttr::OMPNullMemAlloc: 10983 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 10984 // Not supported, fallback to the default mem space. 10985 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 10986 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 10987 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 10988 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 10989 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 10990 case OMPAllocateDeclAttr::OMPConstMemAlloc: 10991 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 10992 AS = LangAS::Default; 10993 return true; 10994 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 10995 llvm_unreachable("Expected predefined allocator for the variables with the " 10996 "static storage."); 10997 } 10998 return false; 10999 } 11000 11001 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 11002 return HasRequiresUnifiedSharedMemory; 11003 } 11004 11005 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 11006 CodeGenModule &CGM) 11007 : CGM(CGM) { 11008 if (CGM.getLangOpts().OpenMPIsDevice) { 11009 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 11010 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 11011 } 11012 } 11013 11014 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 11015 if (CGM.getLangOpts().OpenMPIsDevice) 11016 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 11017 } 11018 11019 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 11020 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 11021 return true; 11022 11023 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11024 // Do not to emit function if it is marked as declare target as it was already 11025 // emitted. 11026 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 11027 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 11028 if (auto *F = dyn_cast_or_null<llvm::Function>( 11029 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 11030 return !F->isDeclaration(); 11031 return false; 11032 } 11033 return true; 11034 } 11035 11036 return !AlreadyEmittedTargetDecls.insert(D).second; 11037 } 11038 11039 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 11040 // If we don't have entries or if we are emitting code for the device, we 11041 // don't need to do anything. 11042 if (CGM.getLangOpts().OMPTargetTriples.empty() || 11043 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 11044 (OffloadEntriesInfoManager.empty() && 11045 !HasEmittedDeclareTargetRegion && 11046 !HasEmittedTargetRegion)) 11047 return nullptr; 11048 11049 // Create and register the function that handles the requires directives. 11050 ASTContext &C = CGM.getContext(); 11051 11052 llvm::Function *RequiresRegFn; 11053 { 11054 CodeGenFunction CGF(CGM); 11055 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 11056 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 11057 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 11058 RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI); 11059 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 11060 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 11061 // TODO: check for other requires clauses. 11062 // The requires directive takes effect only when a target region is 11063 // present in the compilation unit. Otherwise it is ignored and not 11064 // passed to the runtime. This avoids the runtime from throwing an error 11065 // for mismatching requires clauses across compilation units that don't 11066 // contain at least 1 target region. 11067 assert((HasEmittedTargetRegion || 11068 HasEmittedDeclareTargetRegion || 11069 !OffloadEntriesInfoManager.empty()) && 11070 "Target or declare target region expected."); 11071 if (HasRequiresUnifiedSharedMemory) 11072 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 11073 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 11074 CGM.getModule(), OMPRTL___tgt_register_requires), 11075 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 11076 CGF.FinishFunction(); 11077 } 11078 return RequiresRegFn; 11079 } 11080 11081 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 11082 const OMPExecutableDirective &D, 11083 SourceLocation Loc, 11084 llvm::Function *OutlinedFn, 11085 ArrayRef<llvm::Value *> CapturedVars) { 11086 if (!CGF.HaveInsertPoint()) 11087 return; 11088 11089 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 11090 CodeGenFunction::RunCleanupsScope Scope(CGF); 11091 11092 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 11093 llvm::Value *Args[] = { 11094 RTLoc, 11095 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 11096 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 11097 llvm::SmallVector<llvm::Value *, 16> RealArgs; 11098 RealArgs.append(std::begin(Args), std::end(Args)); 11099 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 11100 11101 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11102 CGM.getModule(), OMPRTL___kmpc_fork_teams); 11103 CGF.EmitRuntimeCall(RTLFn, RealArgs); 11104 } 11105 11106 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11107 const Expr *NumTeams, 11108 const Expr *ThreadLimit, 11109 SourceLocation Loc) { 11110 if (!CGF.HaveInsertPoint()) 11111 return; 11112 11113 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 11114 11115 llvm::Value *NumTeamsVal = 11116 NumTeams 11117 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 11118 CGF.CGM.Int32Ty, /* isSigned = */ true) 11119 : CGF.Builder.getInt32(0); 11120 11121 llvm::Value *ThreadLimitVal = 11122 ThreadLimit 11123 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 11124 CGF.CGM.Int32Ty, /* isSigned = */ true) 11125 : CGF.Builder.getInt32(0); 11126 11127 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 11128 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 11129 ThreadLimitVal}; 11130 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 11131 CGM.getModule(), OMPRTL___kmpc_push_num_teams), 11132 PushNumTeamsArgs); 11133 } 11134 11135 void CGOpenMPRuntime::emitTargetDataCalls( 11136 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11137 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11138 if (!CGF.HaveInsertPoint()) 11139 return; 11140 11141 // Action used to replace the default codegen action and turn privatization 11142 // off. 11143 PrePostActionTy NoPrivAction; 11144 11145 // Generate the code for the opening of the data environment. Capture all the 11146 // arguments of the runtime call by reference because they are used in the 11147 // closing of the region. 11148 auto &&BeginThenGen = [this, &D, Device, &Info, 11149 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 11150 // Fill up the arrays with all the mapped variables. 11151 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 11152 11153 // Get map clause information. 11154 MappableExprsHandler MEHandler(D, CGF); 11155 MEHandler.generateAllInfo(CombinedInfo); 11156 11157 // Fill up the arrays and create the arguments. 11158 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 11159 /*IsNonContiguous=*/true); 11160 11161 llvm::Value *BasePointersArrayArg = nullptr; 11162 llvm::Value *PointersArrayArg = nullptr; 11163 llvm::Value *SizesArrayArg = nullptr; 11164 llvm::Value *MapTypesArrayArg = nullptr; 11165 llvm::Value *MapNamesArrayArg = nullptr; 11166 llvm::Value *MappersArrayArg = nullptr; 11167 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 11168 SizesArrayArg, MapTypesArrayArg, 11169 MapNamesArrayArg, MappersArrayArg, Info); 11170 11171 // Emit device ID if any. 11172 llvm::Value *DeviceID = nullptr; 11173 if (Device) { 11174 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11175 CGF.Int64Ty, /*isSigned=*/true); 11176 } else { 11177 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11178 } 11179 11180 // Emit the number of elements in the offloading arrays. 11181 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 11182 // 11183 // Source location for the ident struct 11184 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11185 11186 llvm::Value *OffloadingArgs[] = {RTLoc, 11187 DeviceID, 11188 PointerNum, 11189 BasePointersArrayArg, 11190 PointersArrayArg, 11191 SizesArrayArg, 11192 MapTypesArrayArg, 11193 MapNamesArrayArg, 11194 MappersArrayArg}; 11195 CGF.EmitRuntimeCall( 11196 OMPBuilder.getOrCreateRuntimeFunction( 11197 CGM.getModule(), OMPRTL___tgt_target_data_begin_mapper), 11198 OffloadingArgs); 11199 11200 // If device pointer privatization is required, emit the body of the region 11201 // here. It will have to be duplicated: with and without privatization. 11202 if (!Info.CaptureDeviceAddrMap.empty()) 11203 CodeGen(CGF); 11204 }; 11205 11206 // Generate code for the closing of the data region. 11207 auto &&EndThenGen = [this, Device, &Info, &D](CodeGenFunction &CGF, 11208 PrePostActionTy &) { 11209 assert(Info.isValid() && "Invalid data environment closing arguments."); 11210 11211 llvm::Value *BasePointersArrayArg = nullptr; 11212 llvm::Value *PointersArrayArg = nullptr; 11213 llvm::Value *SizesArrayArg = nullptr; 11214 llvm::Value *MapTypesArrayArg = nullptr; 11215 llvm::Value *MapNamesArrayArg = nullptr; 11216 llvm::Value *MappersArrayArg = nullptr; 11217 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 11218 SizesArrayArg, MapTypesArrayArg, 11219 MapNamesArrayArg, MappersArrayArg, Info, 11220 {/*ForEndCall=*/true}); 11221 11222 // Emit device ID if any. 11223 llvm::Value *DeviceID = nullptr; 11224 if (Device) { 11225 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11226 CGF.Int64Ty, /*isSigned=*/true); 11227 } else { 11228 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11229 } 11230 11231 // Emit the number of elements in the offloading arrays. 11232 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 11233 11234 // Source location for the ident struct 11235 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11236 11237 llvm::Value *OffloadingArgs[] = {RTLoc, 11238 DeviceID, 11239 PointerNum, 11240 BasePointersArrayArg, 11241 PointersArrayArg, 11242 SizesArrayArg, 11243 MapTypesArrayArg, 11244 MapNamesArrayArg, 11245 MappersArrayArg}; 11246 CGF.EmitRuntimeCall( 11247 OMPBuilder.getOrCreateRuntimeFunction( 11248 CGM.getModule(), OMPRTL___tgt_target_data_end_mapper), 11249 OffloadingArgs); 11250 }; 11251 11252 // If we need device pointer privatization, we need to emit the body of the 11253 // region with no privatization in the 'else' branch of the conditional. 11254 // Otherwise, we don't have to do anything. 11255 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 11256 PrePostActionTy &) { 11257 if (!Info.CaptureDeviceAddrMap.empty()) { 11258 CodeGen.setAction(NoPrivAction); 11259 CodeGen(CGF); 11260 } 11261 }; 11262 11263 // We don't have to do anything to close the region if the if clause evaluates 11264 // to false. 11265 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 11266 11267 if (IfCond) { 11268 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 11269 } else { 11270 RegionCodeGenTy RCG(BeginThenGen); 11271 RCG(CGF); 11272 } 11273 11274 // If we don't require privatization of device pointers, we emit the body in 11275 // between the runtime calls. This avoids duplicating the body code. 11276 if (Info.CaptureDeviceAddrMap.empty()) { 11277 CodeGen.setAction(NoPrivAction); 11278 CodeGen(CGF); 11279 } 11280 11281 if (IfCond) { 11282 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 11283 } else { 11284 RegionCodeGenTy RCG(EndThenGen); 11285 RCG(CGF); 11286 } 11287 } 11288 11289 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 11290 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11291 const Expr *Device) { 11292 if (!CGF.HaveInsertPoint()) 11293 return; 11294 11295 assert((isa<OMPTargetEnterDataDirective>(D) || 11296 isa<OMPTargetExitDataDirective>(D) || 11297 isa<OMPTargetUpdateDirective>(D)) && 11298 "Expecting either target enter, exit data, or update directives."); 11299 11300 CodeGenFunction::OMPTargetDataInfo InputInfo; 11301 llvm::Value *MapTypesArray = nullptr; 11302 llvm::Value *MapNamesArray = nullptr; 11303 // Generate the code for the opening of the data environment. 11304 auto &&ThenGen = [this, &D, Device, &InputInfo, &MapTypesArray, 11305 &MapNamesArray](CodeGenFunction &CGF, PrePostActionTy &) { 11306 // Emit device ID if any. 11307 llvm::Value *DeviceID = nullptr; 11308 if (Device) { 11309 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11310 CGF.Int64Ty, /*isSigned=*/true); 11311 } else { 11312 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11313 } 11314 11315 // Emit the number of elements in the offloading arrays. 11316 llvm::Constant *PointerNum = 11317 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 11318 11319 // Source location for the ident struct 11320 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11321 11322 llvm::Value *OffloadingArgs[] = {RTLoc, 11323 DeviceID, 11324 PointerNum, 11325 InputInfo.BasePointersArray.getPointer(), 11326 InputInfo.PointersArray.getPointer(), 11327 InputInfo.SizesArray.getPointer(), 11328 MapTypesArray, 11329 MapNamesArray, 11330 InputInfo.MappersArray.getPointer()}; 11331 11332 // Select the right runtime function call for each standalone 11333 // directive. 11334 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 11335 RuntimeFunction RTLFn; 11336 switch (D.getDirectiveKind()) { 11337 case OMPD_target_enter_data: 11338 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper 11339 : OMPRTL___tgt_target_data_begin_mapper; 11340 break; 11341 case OMPD_target_exit_data: 11342 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper 11343 : OMPRTL___tgt_target_data_end_mapper; 11344 break; 11345 case OMPD_target_update: 11346 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper 11347 : OMPRTL___tgt_target_data_update_mapper; 11348 break; 11349 case OMPD_parallel: 11350 case OMPD_for: 11351 case OMPD_parallel_for: 11352 case OMPD_parallel_master: 11353 case OMPD_parallel_sections: 11354 case OMPD_for_simd: 11355 case OMPD_parallel_for_simd: 11356 case OMPD_cancel: 11357 case OMPD_cancellation_point: 11358 case OMPD_ordered: 11359 case OMPD_threadprivate: 11360 case OMPD_allocate: 11361 case OMPD_task: 11362 case OMPD_simd: 11363 case OMPD_tile: 11364 case OMPD_unroll: 11365 case OMPD_sections: 11366 case OMPD_section: 11367 case OMPD_single: 11368 case OMPD_master: 11369 case OMPD_critical: 11370 case OMPD_taskyield: 11371 case OMPD_barrier: 11372 case OMPD_taskwait: 11373 case OMPD_taskgroup: 11374 case OMPD_atomic: 11375 case OMPD_flush: 11376 case OMPD_depobj: 11377 case OMPD_scan: 11378 case OMPD_teams: 11379 case OMPD_target_data: 11380 case OMPD_distribute: 11381 case OMPD_distribute_simd: 11382 case OMPD_distribute_parallel_for: 11383 case OMPD_distribute_parallel_for_simd: 11384 case OMPD_teams_distribute: 11385 case OMPD_teams_distribute_simd: 11386 case OMPD_teams_distribute_parallel_for: 11387 case OMPD_teams_distribute_parallel_for_simd: 11388 case OMPD_declare_simd: 11389 case OMPD_declare_variant: 11390 case OMPD_begin_declare_variant: 11391 case OMPD_end_declare_variant: 11392 case OMPD_declare_target: 11393 case OMPD_end_declare_target: 11394 case OMPD_declare_reduction: 11395 case OMPD_declare_mapper: 11396 case OMPD_taskloop: 11397 case OMPD_taskloop_simd: 11398 case OMPD_master_taskloop: 11399 case OMPD_master_taskloop_simd: 11400 case OMPD_parallel_master_taskloop: 11401 case OMPD_parallel_master_taskloop_simd: 11402 case OMPD_target: 11403 case OMPD_target_simd: 11404 case OMPD_target_teams_distribute: 11405 case OMPD_target_teams_distribute_simd: 11406 case OMPD_target_teams_distribute_parallel_for: 11407 case OMPD_target_teams_distribute_parallel_for_simd: 11408 case OMPD_target_teams: 11409 case OMPD_target_parallel: 11410 case OMPD_target_parallel_for: 11411 case OMPD_target_parallel_for_simd: 11412 case OMPD_requires: 11413 case OMPD_metadirective: 11414 case OMPD_unknown: 11415 default: 11416 llvm_unreachable("Unexpected standalone target data directive."); 11417 break; 11418 } 11419 CGF.EmitRuntimeCall( 11420 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), RTLFn), 11421 OffloadingArgs); 11422 }; 11423 11424 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 11425 &MapNamesArray](CodeGenFunction &CGF, 11426 PrePostActionTy &) { 11427 // Fill up the arrays with all the mapped variables. 11428 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 11429 11430 // Get map clause information. 11431 MappableExprsHandler MEHandler(D, CGF); 11432 MEHandler.generateAllInfo(CombinedInfo); 11433 11434 TargetDataInfo Info; 11435 // Fill up the arrays and create the arguments. 11436 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 11437 /*IsNonContiguous=*/true); 11438 bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 11439 D.hasClausesOfKind<OMPNowaitClause>(); 11440 emitOffloadingArraysArgument( 11441 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 11442 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 11443 {/*ForEndTask=*/false}); 11444 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 11445 InputInfo.BasePointersArray = 11446 Address(Info.BasePointersArray, CGM.getPointerAlign()); 11447 InputInfo.PointersArray = 11448 Address(Info.PointersArray, CGM.getPointerAlign()); 11449 InputInfo.SizesArray = 11450 Address(Info.SizesArray, CGM.getPointerAlign()); 11451 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 11452 MapTypesArray = Info.MapTypesArray; 11453 MapNamesArray = Info.MapNamesArray; 11454 if (RequiresOuterTask) 11455 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 11456 else 11457 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 11458 }; 11459 11460 if (IfCond) { 11461 emitIfClause(CGF, IfCond, TargetThenGen, 11462 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 11463 } else { 11464 RegionCodeGenTy ThenRCG(TargetThenGen); 11465 ThenRCG(CGF); 11466 } 11467 } 11468 11469 namespace { 11470 /// Kind of parameter in a function with 'declare simd' directive. 11471 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 11472 /// Attribute set of the parameter. 11473 struct ParamAttrTy { 11474 ParamKindTy Kind = Vector; 11475 llvm::APSInt StrideOrArg; 11476 llvm::APSInt Alignment; 11477 }; 11478 } // namespace 11479 11480 static unsigned evaluateCDTSize(const FunctionDecl *FD, 11481 ArrayRef<ParamAttrTy> ParamAttrs) { 11482 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 11483 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 11484 // of that clause. The VLEN value must be power of 2. 11485 // In other case the notion of the function`s "characteristic data type" (CDT) 11486 // is used to compute the vector length. 11487 // CDT is defined in the following order: 11488 // a) For non-void function, the CDT is the return type. 11489 // b) If the function has any non-uniform, non-linear parameters, then the 11490 // CDT is the type of the first such parameter. 11491 // c) If the CDT determined by a) or b) above is struct, union, or class 11492 // type which is pass-by-value (except for the type that maps to the 11493 // built-in complex data type), the characteristic data type is int. 11494 // d) If none of the above three cases is applicable, the CDT is int. 11495 // The VLEN is then determined based on the CDT and the size of vector 11496 // register of that ISA for which current vector version is generated. The 11497 // VLEN is computed using the formula below: 11498 // VLEN = sizeof(vector_register) / sizeof(CDT), 11499 // where vector register size specified in section 3.2.1 Registers and the 11500 // Stack Frame of original AMD64 ABI document. 11501 QualType RetType = FD->getReturnType(); 11502 if (RetType.isNull()) 11503 return 0; 11504 ASTContext &C = FD->getASTContext(); 11505 QualType CDT; 11506 if (!RetType.isNull() && !RetType->isVoidType()) { 11507 CDT = RetType; 11508 } else { 11509 unsigned Offset = 0; 11510 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 11511 if (ParamAttrs[Offset].Kind == Vector) 11512 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 11513 ++Offset; 11514 } 11515 if (CDT.isNull()) { 11516 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11517 if (ParamAttrs[I + Offset].Kind == Vector) { 11518 CDT = FD->getParamDecl(I)->getType(); 11519 break; 11520 } 11521 } 11522 } 11523 } 11524 if (CDT.isNull()) 11525 CDT = C.IntTy; 11526 CDT = CDT->getCanonicalTypeUnqualified(); 11527 if (CDT->isRecordType() || CDT->isUnionType()) 11528 CDT = C.IntTy; 11529 return C.getTypeSize(CDT); 11530 } 11531 11532 static void 11533 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 11534 const llvm::APSInt &VLENVal, 11535 ArrayRef<ParamAttrTy> ParamAttrs, 11536 OMPDeclareSimdDeclAttr::BranchStateTy State) { 11537 struct ISADataTy { 11538 char ISA; 11539 unsigned VecRegSize; 11540 }; 11541 ISADataTy ISAData[] = { 11542 { 11543 'b', 128 11544 }, // SSE 11545 { 11546 'c', 256 11547 }, // AVX 11548 { 11549 'd', 256 11550 }, // AVX2 11551 { 11552 'e', 512 11553 }, // AVX512 11554 }; 11555 llvm::SmallVector<char, 2> Masked; 11556 switch (State) { 11557 case OMPDeclareSimdDeclAttr::BS_Undefined: 11558 Masked.push_back('N'); 11559 Masked.push_back('M'); 11560 break; 11561 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11562 Masked.push_back('N'); 11563 break; 11564 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11565 Masked.push_back('M'); 11566 break; 11567 } 11568 for (char Mask : Masked) { 11569 for (const ISADataTy &Data : ISAData) { 11570 SmallString<256> Buffer; 11571 llvm::raw_svector_ostream Out(Buffer); 11572 Out << "_ZGV" << Data.ISA << Mask; 11573 if (!VLENVal) { 11574 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 11575 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 11576 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 11577 } else { 11578 Out << VLENVal; 11579 } 11580 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 11581 switch (ParamAttr.Kind){ 11582 case LinearWithVarStride: 11583 Out << 's' << ParamAttr.StrideOrArg; 11584 break; 11585 case Linear: 11586 Out << 'l'; 11587 if (ParamAttr.StrideOrArg != 1) 11588 Out << ParamAttr.StrideOrArg; 11589 break; 11590 case Uniform: 11591 Out << 'u'; 11592 break; 11593 case Vector: 11594 Out << 'v'; 11595 break; 11596 } 11597 if (!!ParamAttr.Alignment) 11598 Out << 'a' << ParamAttr.Alignment; 11599 } 11600 Out << '_' << Fn->getName(); 11601 Fn->addFnAttr(Out.str()); 11602 } 11603 } 11604 } 11605 11606 // This are the Functions that are needed to mangle the name of the 11607 // vector functions generated by the compiler, according to the rules 11608 // defined in the "Vector Function ABI specifications for AArch64", 11609 // available at 11610 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 11611 11612 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 11613 /// 11614 /// TODO: Need to implement the behavior for reference marked with a 11615 /// var or no linear modifiers (1.b in the section). For this, we 11616 /// need to extend ParamKindTy to support the linear modifiers. 11617 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 11618 QT = QT.getCanonicalType(); 11619 11620 if (QT->isVoidType()) 11621 return false; 11622 11623 if (Kind == ParamKindTy::Uniform) 11624 return false; 11625 11626 if (Kind == ParamKindTy::Linear) 11627 return false; 11628 11629 // TODO: Handle linear references with modifiers 11630 11631 if (Kind == ParamKindTy::LinearWithVarStride) 11632 return false; 11633 11634 return true; 11635 } 11636 11637 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 11638 static bool getAArch64PBV(QualType QT, ASTContext &C) { 11639 QT = QT.getCanonicalType(); 11640 unsigned Size = C.getTypeSize(QT); 11641 11642 // Only scalars and complex within 16 bytes wide set PVB to true. 11643 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 11644 return false; 11645 11646 if (QT->isFloatingType()) 11647 return true; 11648 11649 if (QT->isIntegerType()) 11650 return true; 11651 11652 if (QT->isPointerType()) 11653 return true; 11654 11655 // TODO: Add support for complex types (section 3.1.2, item 2). 11656 11657 return false; 11658 } 11659 11660 /// Computes the lane size (LS) of a return type or of an input parameter, 11661 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 11662 /// TODO: Add support for references, section 3.2.1, item 1. 11663 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 11664 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 11665 QualType PTy = QT.getCanonicalType()->getPointeeType(); 11666 if (getAArch64PBV(PTy, C)) 11667 return C.getTypeSize(PTy); 11668 } 11669 if (getAArch64PBV(QT, C)) 11670 return C.getTypeSize(QT); 11671 11672 return C.getTypeSize(C.getUIntPtrType()); 11673 } 11674 11675 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 11676 // signature of the scalar function, as defined in 3.2.2 of the 11677 // AAVFABI. 11678 static std::tuple<unsigned, unsigned, bool> 11679 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 11680 QualType RetType = FD->getReturnType().getCanonicalType(); 11681 11682 ASTContext &C = FD->getASTContext(); 11683 11684 bool OutputBecomesInput = false; 11685 11686 llvm::SmallVector<unsigned, 8> Sizes; 11687 if (!RetType->isVoidType()) { 11688 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 11689 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 11690 OutputBecomesInput = true; 11691 } 11692 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11693 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 11694 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 11695 } 11696 11697 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 11698 // The LS of a function parameter / return value can only be a power 11699 // of 2, starting from 8 bits, up to 128. 11700 assert(std::all_of(Sizes.begin(), Sizes.end(), 11701 [](unsigned Size) { 11702 return Size == 8 || Size == 16 || Size == 32 || 11703 Size == 64 || Size == 128; 11704 }) && 11705 "Invalid size"); 11706 11707 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 11708 *std::max_element(std::begin(Sizes), std::end(Sizes)), 11709 OutputBecomesInput); 11710 } 11711 11712 /// Mangle the parameter part of the vector function name according to 11713 /// their OpenMP classification. The mangling function is defined in 11714 /// section 3.5 of the AAVFABI. 11715 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 11716 SmallString<256> Buffer; 11717 llvm::raw_svector_ostream Out(Buffer); 11718 for (const auto &ParamAttr : ParamAttrs) { 11719 switch (ParamAttr.Kind) { 11720 case LinearWithVarStride: 11721 Out << "ls" << ParamAttr.StrideOrArg; 11722 break; 11723 case Linear: 11724 Out << 'l'; 11725 // Don't print the step value if it is not present or if it is 11726 // equal to 1. 11727 if (ParamAttr.StrideOrArg != 1) 11728 Out << ParamAttr.StrideOrArg; 11729 break; 11730 case Uniform: 11731 Out << 'u'; 11732 break; 11733 case Vector: 11734 Out << 'v'; 11735 break; 11736 } 11737 11738 if (!!ParamAttr.Alignment) 11739 Out << 'a' << ParamAttr.Alignment; 11740 } 11741 11742 return std::string(Out.str()); 11743 } 11744 11745 // Function used to add the attribute. The parameter `VLEN` is 11746 // templated to allow the use of "x" when targeting scalable functions 11747 // for SVE. 11748 template <typename T> 11749 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 11750 char ISA, StringRef ParSeq, 11751 StringRef MangledName, bool OutputBecomesInput, 11752 llvm::Function *Fn) { 11753 SmallString<256> Buffer; 11754 llvm::raw_svector_ostream Out(Buffer); 11755 Out << Prefix << ISA << LMask << VLEN; 11756 if (OutputBecomesInput) 11757 Out << "v"; 11758 Out << ParSeq << "_" << MangledName; 11759 Fn->addFnAttr(Out.str()); 11760 } 11761 11762 // Helper function to generate the Advanced SIMD names depending on 11763 // the value of the NDS when simdlen is not present. 11764 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 11765 StringRef Prefix, char ISA, 11766 StringRef ParSeq, StringRef MangledName, 11767 bool OutputBecomesInput, 11768 llvm::Function *Fn) { 11769 switch (NDS) { 11770 case 8: 11771 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11772 OutputBecomesInput, Fn); 11773 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 11774 OutputBecomesInput, Fn); 11775 break; 11776 case 16: 11777 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11778 OutputBecomesInput, Fn); 11779 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11780 OutputBecomesInput, Fn); 11781 break; 11782 case 32: 11783 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11784 OutputBecomesInput, Fn); 11785 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11786 OutputBecomesInput, Fn); 11787 break; 11788 case 64: 11789 case 128: 11790 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11791 OutputBecomesInput, Fn); 11792 break; 11793 default: 11794 llvm_unreachable("Scalar type is too wide."); 11795 } 11796 } 11797 11798 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 11799 static void emitAArch64DeclareSimdFunction( 11800 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 11801 ArrayRef<ParamAttrTy> ParamAttrs, 11802 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 11803 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 11804 11805 // Get basic data for building the vector signature. 11806 const auto Data = getNDSWDS(FD, ParamAttrs); 11807 const unsigned NDS = std::get<0>(Data); 11808 const unsigned WDS = std::get<1>(Data); 11809 const bool OutputBecomesInput = std::get<2>(Data); 11810 11811 // Check the values provided via `simdlen` by the user. 11812 // 1. A `simdlen(1)` doesn't produce vector signatures, 11813 if (UserVLEN == 1) { 11814 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11815 DiagnosticsEngine::Warning, 11816 "The clause simdlen(1) has no effect when targeting aarch64."); 11817 CGM.getDiags().Report(SLoc, DiagID); 11818 return; 11819 } 11820 11821 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 11822 // Advanced SIMD output. 11823 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 11824 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11825 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 11826 "power of 2 when targeting Advanced SIMD."); 11827 CGM.getDiags().Report(SLoc, DiagID); 11828 return; 11829 } 11830 11831 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 11832 // limits. 11833 if (ISA == 's' && UserVLEN != 0) { 11834 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 11835 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11836 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 11837 "lanes in the architectural constraints " 11838 "for SVE (min is 128-bit, max is " 11839 "2048-bit, by steps of 128-bit)"); 11840 CGM.getDiags().Report(SLoc, DiagID) << WDS; 11841 return; 11842 } 11843 } 11844 11845 // Sort out parameter sequence. 11846 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 11847 StringRef Prefix = "_ZGV"; 11848 // Generate simdlen from user input (if any). 11849 if (UserVLEN) { 11850 if (ISA == 's') { 11851 // SVE generates only a masked function. 11852 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11853 OutputBecomesInput, Fn); 11854 } else { 11855 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11856 // Advanced SIMD generates one or two functions, depending on 11857 // the `[not]inbranch` clause. 11858 switch (State) { 11859 case OMPDeclareSimdDeclAttr::BS_Undefined: 11860 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11861 OutputBecomesInput, Fn); 11862 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11863 OutputBecomesInput, Fn); 11864 break; 11865 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11866 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11867 OutputBecomesInput, Fn); 11868 break; 11869 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11870 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11871 OutputBecomesInput, Fn); 11872 break; 11873 } 11874 } 11875 } else { 11876 // If no user simdlen is provided, follow the AAVFABI rules for 11877 // generating the vector length. 11878 if (ISA == 's') { 11879 // SVE, section 3.4.1, item 1. 11880 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 11881 OutputBecomesInput, Fn); 11882 } else { 11883 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11884 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 11885 // two vector names depending on the use of the clause 11886 // `[not]inbranch`. 11887 switch (State) { 11888 case OMPDeclareSimdDeclAttr::BS_Undefined: 11889 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11890 OutputBecomesInput, Fn); 11891 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11892 OutputBecomesInput, Fn); 11893 break; 11894 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11895 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11896 OutputBecomesInput, Fn); 11897 break; 11898 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11899 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11900 OutputBecomesInput, Fn); 11901 break; 11902 } 11903 } 11904 } 11905 } 11906 11907 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 11908 llvm::Function *Fn) { 11909 ASTContext &C = CGM.getContext(); 11910 FD = FD->getMostRecentDecl(); 11911 // Map params to their positions in function decl. 11912 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 11913 if (isa<CXXMethodDecl>(FD)) 11914 ParamPositions.try_emplace(FD, 0); 11915 unsigned ParamPos = ParamPositions.size(); 11916 for (const ParmVarDecl *P : FD->parameters()) { 11917 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 11918 ++ParamPos; 11919 } 11920 while (FD) { 11921 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 11922 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 11923 // Mark uniform parameters. 11924 for (const Expr *E : Attr->uniforms()) { 11925 E = E->IgnoreParenImpCasts(); 11926 unsigned Pos; 11927 if (isa<CXXThisExpr>(E)) { 11928 Pos = ParamPositions[FD]; 11929 } else { 11930 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11931 ->getCanonicalDecl(); 11932 Pos = ParamPositions[PVD]; 11933 } 11934 ParamAttrs[Pos].Kind = Uniform; 11935 } 11936 // Get alignment info. 11937 auto NI = Attr->alignments_begin(); 11938 for (const Expr *E : Attr->aligneds()) { 11939 E = E->IgnoreParenImpCasts(); 11940 unsigned Pos; 11941 QualType ParmTy; 11942 if (isa<CXXThisExpr>(E)) { 11943 Pos = ParamPositions[FD]; 11944 ParmTy = E->getType(); 11945 } else { 11946 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11947 ->getCanonicalDecl(); 11948 Pos = ParamPositions[PVD]; 11949 ParmTy = PVD->getType(); 11950 } 11951 ParamAttrs[Pos].Alignment = 11952 (*NI) 11953 ? (*NI)->EvaluateKnownConstInt(C) 11954 : llvm::APSInt::getUnsigned( 11955 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 11956 .getQuantity()); 11957 ++NI; 11958 } 11959 // Mark linear parameters. 11960 auto SI = Attr->steps_begin(); 11961 auto MI = Attr->modifiers_begin(); 11962 for (const Expr *E : Attr->linears()) { 11963 E = E->IgnoreParenImpCasts(); 11964 unsigned Pos; 11965 // Rescaling factor needed to compute the linear parameter 11966 // value in the mangled name. 11967 unsigned PtrRescalingFactor = 1; 11968 if (isa<CXXThisExpr>(E)) { 11969 Pos = ParamPositions[FD]; 11970 } else { 11971 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11972 ->getCanonicalDecl(); 11973 Pos = ParamPositions[PVD]; 11974 if (auto *P = dyn_cast<PointerType>(PVD->getType())) 11975 PtrRescalingFactor = CGM.getContext() 11976 .getTypeSizeInChars(P->getPointeeType()) 11977 .getQuantity(); 11978 } 11979 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 11980 ParamAttr.Kind = Linear; 11981 // Assuming a stride of 1, for `linear` without modifiers. 11982 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1); 11983 if (*SI) { 11984 Expr::EvalResult Result; 11985 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 11986 if (const auto *DRE = 11987 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 11988 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 11989 ParamAttr.Kind = LinearWithVarStride; 11990 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 11991 ParamPositions[StridePVD->getCanonicalDecl()]); 11992 } 11993 } 11994 } else { 11995 ParamAttr.StrideOrArg = Result.Val.getInt(); 11996 } 11997 } 11998 // If we are using a linear clause on a pointer, we need to 11999 // rescale the value of linear_step with the byte size of the 12000 // pointee type. 12001 if (Linear == ParamAttr.Kind) 12002 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor; 12003 ++SI; 12004 ++MI; 12005 } 12006 llvm::APSInt VLENVal; 12007 SourceLocation ExprLoc; 12008 const Expr *VLENExpr = Attr->getSimdlen(); 12009 if (VLENExpr) { 12010 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 12011 ExprLoc = VLENExpr->getExprLoc(); 12012 } 12013 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 12014 if (CGM.getTriple().isX86()) { 12015 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 12016 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 12017 unsigned VLEN = VLENVal.getExtValue(); 12018 StringRef MangledName = Fn->getName(); 12019 if (CGM.getTarget().hasFeature("sve")) 12020 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 12021 MangledName, 's', 128, Fn, ExprLoc); 12022 if (CGM.getTarget().hasFeature("neon")) 12023 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 12024 MangledName, 'n', 128, Fn, ExprLoc); 12025 } 12026 } 12027 FD = FD->getPreviousDecl(); 12028 } 12029 } 12030 12031 namespace { 12032 /// Cleanup action for doacross support. 12033 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 12034 public: 12035 static const int DoacrossFinArgs = 2; 12036 12037 private: 12038 llvm::FunctionCallee RTLFn; 12039 llvm::Value *Args[DoacrossFinArgs]; 12040 12041 public: 12042 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 12043 ArrayRef<llvm::Value *> CallArgs) 12044 : RTLFn(RTLFn) { 12045 assert(CallArgs.size() == DoacrossFinArgs); 12046 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 12047 } 12048 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 12049 if (!CGF.HaveInsertPoint()) 12050 return; 12051 CGF.EmitRuntimeCall(RTLFn, Args); 12052 } 12053 }; 12054 } // namespace 12055 12056 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12057 const OMPLoopDirective &D, 12058 ArrayRef<Expr *> NumIterations) { 12059 if (!CGF.HaveInsertPoint()) 12060 return; 12061 12062 ASTContext &C = CGM.getContext(); 12063 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 12064 RecordDecl *RD; 12065 if (KmpDimTy.isNull()) { 12066 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 12067 // kmp_int64 lo; // lower 12068 // kmp_int64 up; // upper 12069 // kmp_int64 st; // stride 12070 // }; 12071 RD = C.buildImplicitRecord("kmp_dim"); 12072 RD->startDefinition(); 12073 addFieldToRecordDecl(C, RD, Int64Ty); 12074 addFieldToRecordDecl(C, RD, Int64Ty); 12075 addFieldToRecordDecl(C, RD, Int64Ty); 12076 RD->completeDefinition(); 12077 KmpDimTy = C.getRecordType(RD); 12078 } else { 12079 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 12080 } 12081 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 12082 QualType ArrayTy = 12083 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 12084 12085 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 12086 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 12087 enum { LowerFD = 0, UpperFD, StrideFD }; 12088 // Fill dims with data. 12089 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 12090 LValue DimsLVal = CGF.MakeAddrLValue( 12091 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 12092 // dims.upper = num_iterations; 12093 LValue UpperLVal = CGF.EmitLValueForField( 12094 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 12095 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 12096 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(), 12097 Int64Ty, NumIterations[I]->getExprLoc()); 12098 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 12099 // dims.stride = 1; 12100 LValue StrideLVal = CGF.EmitLValueForField( 12101 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 12102 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 12103 StrideLVal); 12104 } 12105 12106 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 12107 // kmp_int32 num_dims, struct kmp_dim * dims); 12108 llvm::Value *Args[] = { 12109 emitUpdateLocation(CGF, D.getBeginLoc()), 12110 getThreadID(CGF, D.getBeginLoc()), 12111 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 12112 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12113 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 12114 CGM.VoidPtrTy)}; 12115 12116 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12117 CGM.getModule(), OMPRTL___kmpc_doacross_init); 12118 CGF.EmitRuntimeCall(RTLFn, Args); 12119 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 12120 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 12121 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12122 CGM.getModule(), OMPRTL___kmpc_doacross_fini); 12123 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 12124 llvm::makeArrayRef(FiniArgs)); 12125 } 12126 12127 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12128 const OMPDependClause *C) { 12129 QualType Int64Ty = 12130 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 12131 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 12132 QualType ArrayTy = CGM.getContext().getConstantArrayType( 12133 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 12134 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 12135 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 12136 const Expr *CounterVal = C->getLoopData(I); 12137 assert(CounterVal); 12138 llvm::Value *CntVal = CGF.EmitScalarConversion( 12139 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 12140 CounterVal->getExprLoc()); 12141 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 12142 /*Volatile=*/false, Int64Ty); 12143 } 12144 llvm::Value *Args[] = { 12145 emitUpdateLocation(CGF, C->getBeginLoc()), 12146 getThreadID(CGF, C->getBeginLoc()), 12147 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 12148 llvm::FunctionCallee RTLFn; 12149 if (C->getDependencyKind() == OMPC_DEPEND_source) { 12150 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 12151 OMPRTL___kmpc_doacross_post); 12152 } else { 12153 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 12154 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 12155 OMPRTL___kmpc_doacross_wait); 12156 } 12157 CGF.EmitRuntimeCall(RTLFn, Args); 12158 } 12159 12160 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 12161 llvm::FunctionCallee Callee, 12162 ArrayRef<llvm::Value *> Args) const { 12163 assert(Loc.isValid() && "Outlined function call location must be valid."); 12164 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 12165 12166 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 12167 if (Fn->doesNotThrow()) { 12168 CGF.EmitNounwindRuntimeCall(Fn, Args); 12169 return; 12170 } 12171 } 12172 CGF.EmitRuntimeCall(Callee, Args); 12173 } 12174 12175 void CGOpenMPRuntime::emitOutlinedFunctionCall( 12176 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 12177 ArrayRef<llvm::Value *> Args) const { 12178 emitCall(CGF, Loc, OutlinedFn, Args); 12179 } 12180 12181 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 12182 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 12183 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 12184 HasEmittedDeclareTargetRegion = true; 12185 } 12186 12187 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 12188 const VarDecl *NativeParam, 12189 const VarDecl *TargetParam) const { 12190 return CGF.GetAddrOfLocalVar(NativeParam); 12191 } 12192 12193 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 12194 const VarDecl *VD) { 12195 if (!VD) 12196 return Address::invalid(); 12197 Address UntiedAddr = Address::invalid(); 12198 Address UntiedRealAddr = Address::invalid(); 12199 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 12200 if (It != FunctionToUntiedTaskStackMap.end()) { 12201 const UntiedLocalVarsAddressesMap &UntiedData = 12202 UntiedLocalVarsStack[It->second]; 12203 auto I = UntiedData.find(VD); 12204 if (I != UntiedData.end()) { 12205 UntiedAddr = I->second.first; 12206 UntiedRealAddr = I->second.second; 12207 } 12208 } 12209 const VarDecl *CVD = VD->getCanonicalDecl(); 12210 if (CVD->hasAttr<OMPAllocateDeclAttr>()) { 12211 // Use the default allocation. 12212 if (!isAllocatableDecl(VD)) 12213 return UntiedAddr; 12214 llvm::Value *Size; 12215 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 12216 if (CVD->getType()->isVariablyModifiedType()) { 12217 Size = CGF.getTypeSize(CVD->getType()); 12218 // Align the size: ((size + align - 1) / align) * align 12219 Size = CGF.Builder.CreateNUWAdd( 12220 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 12221 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 12222 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 12223 } else { 12224 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 12225 Size = CGM.getSize(Sz.alignTo(Align)); 12226 } 12227 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 12228 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 12229 assert(AA->getAllocator() && 12230 "Expected allocator expression for non-default allocator."); 12231 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 12232 // According to the standard, the original allocator type is a enum 12233 // (integer). Convert to pointer type, if required. 12234 Allocator = CGF.EmitScalarConversion( 12235 Allocator, AA->getAllocator()->getType(), CGF.getContext().VoidPtrTy, 12236 AA->getAllocator()->getExprLoc()); 12237 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 12238 12239 llvm::Value *Addr = 12240 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 12241 CGM.getModule(), OMPRTL___kmpc_alloc), 12242 Args, getName({CVD->getName(), ".void.addr"})); 12243 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12244 CGM.getModule(), OMPRTL___kmpc_free); 12245 QualType Ty = CGM.getContext().getPointerType(CVD->getType()); 12246 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12247 Addr, CGF.ConvertTypeForMem(Ty), getName({CVD->getName(), ".addr"})); 12248 if (UntiedAddr.isValid()) 12249 CGF.EmitStoreOfScalar(Addr, UntiedAddr, /*Volatile=*/false, Ty); 12250 12251 // Cleanup action for allocate support. 12252 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 12253 llvm::FunctionCallee RTLFn; 12254 SourceLocation::UIntTy LocEncoding; 12255 Address Addr; 12256 const Expr *Allocator; 12257 12258 public: 12259 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 12260 SourceLocation::UIntTy LocEncoding, Address Addr, 12261 const Expr *Allocator) 12262 : RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr), 12263 Allocator(Allocator) {} 12264 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 12265 if (!CGF.HaveInsertPoint()) 12266 return; 12267 llvm::Value *Args[3]; 12268 Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( 12269 CGF, SourceLocation::getFromRawEncoding(LocEncoding)); 12270 Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12271 Addr.getPointer(), CGF.VoidPtrTy); 12272 llvm::Value *AllocVal = CGF.EmitScalarExpr(Allocator); 12273 // According to the standard, the original allocator type is a enum 12274 // (integer). Convert to pointer type, if required. 12275 AllocVal = CGF.EmitScalarConversion(AllocVal, Allocator->getType(), 12276 CGF.getContext().VoidPtrTy, 12277 Allocator->getExprLoc()); 12278 Args[2] = AllocVal; 12279 12280 CGF.EmitRuntimeCall(RTLFn, Args); 12281 } 12282 }; 12283 Address VDAddr = 12284 UntiedRealAddr.isValid() ? UntiedRealAddr : Address(Addr, Align); 12285 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>( 12286 NormalAndEHCleanup, FiniRTLFn, CVD->getLocation().getRawEncoding(), 12287 VDAddr, AA->getAllocator()); 12288 if (UntiedRealAddr.isValid()) 12289 if (auto *Region = 12290 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 12291 Region->emitUntiedSwitch(CGF); 12292 return VDAddr; 12293 } 12294 return UntiedAddr; 12295 } 12296 12297 bool CGOpenMPRuntime::isLocalVarInUntiedTask(CodeGenFunction &CGF, 12298 const VarDecl *VD) const { 12299 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 12300 if (It == FunctionToUntiedTaskStackMap.end()) 12301 return false; 12302 return UntiedLocalVarsStack[It->second].count(VD) > 0; 12303 } 12304 12305 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 12306 CodeGenModule &CGM, const OMPLoopDirective &S) 12307 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 12308 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12309 if (!NeedToPush) 12310 return; 12311 NontemporalDeclsSet &DS = 12312 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 12313 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 12314 for (const Stmt *Ref : C->private_refs()) { 12315 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 12316 const ValueDecl *VD; 12317 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 12318 VD = DRE->getDecl(); 12319 } else { 12320 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 12321 assert((ME->isImplicitCXXThis() || 12322 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 12323 "Expected member of current class."); 12324 VD = ME->getMemberDecl(); 12325 } 12326 DS.insert(VD); 12327 } 12328 } 12329 } 12330 12331 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 12332 if (!NeedToPush) 12333 return; 12334 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 12335 } 12336 12337 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII( 12338 CodeGenFunction &CGF, 12339 const llvm::MapVector<CanonicalDeclPtr<const VarDecl>, 12340 std::pair<Address, Address>> &LocalVars) 12341 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) { 12342 if (!NeedToPush) 12343 return; 12344 CGM.getOpenMPRuntime().FunctionToUntiedTaskStackMap.try_emplace( 12345 CGF.CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size()); 12346 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars); 12347 } 12348 12349 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::~UntiedTaskLocalDeclsRAII() { 12350 if (!NeedToPush) 12351 return; 12352 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back(); 12353 } 12354 12355 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 12356 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12357 12358 return llvm::any_of( 12359 CGM.getOpenMPRuntime().NontemporalDeclsStack, 12360 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 12361 } 12362 12363 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 12364 const OMPExecutableDirective &S, 12365 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 12366 const { 12367 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 12368 // Vars in target/task regions must be excluded completely. 12369 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 12370 isOpenMPTaskingDirective(S.getDirectiveKind())) { 12371 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12372 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 12373 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 12374 for (const CapturedStmt::Capture &Cap : CS->captures()) { 12375 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 12376 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 12377 } 12378 } 12379 // Exclude vars in private clauses. 12380 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 12381 for (const Expr *Ref : C->varlists()) { 12382 if (!Ref->getType()->isScalarType()) 12383 continue; 12384 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12385 if (!DRE) 12386 continue; 12387 NeedToCheckForLPCs.insert(DRE->getDecl()); 12388 } 12389 } 12390 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 12391 for (const Expr *Ref : C->varlists()) { 12392 if (!Ref->getType()->isScalarType()) 12393 continue; 12394 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12395 if (!DRE) 12396 continue; 12397 NeedToCheckForLPCs.insert(DRE->getDecl()); 12398 } 12399 } 12400 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12401 for (const Expr *Ref : C->varlists()) { 12402 if (!Ref->getType()->isScalarType()) 12403 continue; 12404 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12405 if (!DRE) 12406 continue; 12407 NeedToCheckForLPCs.insert(DRE->getDecl()); 12408 } 12409 } 12410 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 12411 for (const Expr *Ref : C->varlists()) { 12412 if (!Ref->getType()->isScalarType()) 12413 continue; 12414 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12415 if (!DRE) 12416 continue; 12417 NeedToCheckForLPCs.insert(DRE->getDecl()); 12418 } 12419 } 12420 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 12421 for (const Expr *Ref : C->varlists()) { 12422 if (!Ref->getType()->isScalarType()) 12423 continue; 12424 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12425 if (!DRE) 12426 continue; 12427 NeedToCheckForLPCs.insert(DRE->getDecl()); 12428 } 12429 } 12430 for (const Decl *VD : NeedToCheckForLPCs) { 12431 for (const LastprivateConditionalData &Data : 12432 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 12433 if (Data.DeclToUniqueName.count(VD) > 0) { 12434 if (!Data.Disabled) 12435 NeedToAddForLPCsAsDisabled.insert(VD); 12436 break; 12437 } 12438 } 12439 } 12440 } 12441 12442 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12443 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 12444 : CGM(CGF.CGM), 12445 Action((CGM.getLangOpts().OpenMP >= 50 && 12446 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 12447 [](const OMPLastprivateClause *C) { 12448 return C->getKind() == 12449 OMPC_LASTPRIVATE_conditional; 12450 })) 12451 ? ActionToDo::PushAsLastprivateConditional 12452 : ActionToDo::DoNotPush) { 12453 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12454 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 12455 return; 12456 assert(Action == ActionToDo::PushAsLastprivateConditional && 12457 "Expected a push action."); 12458 LastprivateConditionalData &Data = 12459 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12460 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12461 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 12462 continue; 12463 12464 for (const Expr *Ref : C->varlists()) { 12465 Data.DeclToUniqueName.insert(std::make_pair( 12466 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 12467 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 12468 } 12469 } 12470 Data.IVLVal = IVLVal; 12471 Data.Fn = CGF.CurFn; 12472 } 12473 12474 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12475 CodeGenFunction &CGF, const OMPExecutableDirective &S) 12476 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 12477 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12478 if (CGM.getLangOpts().OpenMP < 50) 12479 return; 12480 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 12481 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 12482 if (!NeedToAddForLPCsAsDisabled.empty()) { 12483 Action = ActionToDo::DisableLastprivateConditional; 12484 LastprivateConditionalData &Data = 12485 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12486 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 12487 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 12488 Data.Fn = CGF.CurFn; 12489 Data.Disabled = true; 12490 } 12491 } 12492 12493 CGOpenMPRuntime::LastprivateConditionalRAII 12494 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 12495 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 12496 return LastprivateConditionalRAII(CGF, S); 12497 } 12498 12499 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 12500 if (CGM.getLangOpts().OpenMP < 50) 12501 return; 12502 if (Action == ActionToDo::DisableLastprivateConditional) { 12503 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12504 "Expected list of disabled private vars."); 12505 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12506 } 12507 if (Action == ActionToDo::PushAsLastprivateConditional) { 12508 assert( 12509 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12510 "Expected list of lastprivate conditional vars."); 12511 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12512 } 12513 } 12514 12515 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 12516 const VarDecl *VD) { 12517 ASTContext &C = CGM.getContext(); 12518 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 12519 if (I == LastprivateConditionalToTypes.end()) 12520 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 12521 QualType NewType; 12522 const FieldDecl *VDField; 12523 const FieldDecl *FiredField; 12524 LValue BaseLVal; 12525 auto VI = I->getSecond().find(VD); 12526 if (VI == I->getSecond().end()) { 12527 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 12528 RD->startDefinition(); 12529 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 12530 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 12531 RD->completeDefinition(); 12532 NewType = C.getRecordType(RD); 12533 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 12534 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 12535 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 12536 } else { 12537 NewType = std::get<0>(VI->getSecond()); 12538 VDField = std::get<1>(VI->getSecond()); 12539 FiredField = std::get<2>(VI->getSecond()); 12540 BaseLVal = std::get<3>(VI->getSecond()); 12541 } 12542 LValue FiredLVal = 12543 CGF.EmitLValueForField(BaseLVal, FiredField); 12544 CGF.EmitStoreOfScalar( 12545 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 12546 FiredLVal); 12547 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 12548 } 12549 12550 namespace { 12551 /// Checks if the lastprivate conditional variable is referenced in LHS. 12552 class LastprivateConditionalRefChecker final 12553 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 12554 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 12555 const Expr *FoundE = nullptr; 12556 const Decl *FoundD = nullptr; 12557 StringRef UniqueDeclName; 12558 LValue IVLVal; 12559 llvm::Function *FoundFn = nullptr; 12560 SourceLocation Loc; 12561 12562 public: 12563 bool VisitDeclRefExpr(const DeclRefExpr *E) { 12564 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12565 llvm::reverse(LPM)) { 12566 auto It = D.DeclToUniqueName.find(E->getDecl()); 12567 if (It == D.DeclToUniqueName.end()) 12568 continue; 12569 if (D.Disabled) 12570 return false; 12571 FoundE = E; 12572 FoundD = E->getDecl()->getCanonicalDecl(); 12573 UniqueDeclName = It->second; 12574 IVLVal = D.IVLVal; 12575 FoundFn = D.Fn; 12576 break; 12577 } 12578 return FoundE == E; 12579 } 12580 bool VisitMemberExpr(const MemberExpr *E) { 12581 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 12582 return false; 12583 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12584 llvm::reverse(LPM)) { 12585 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 12586 if (It == D.DeclToUniqueName.end()) 12587 continue; 12588 if (D.Disabled) 12589 return false; 12590 FoundE = E; 12591 FoundD = E->getMemberDecl()->getCanonicalDecl(); 12592 UniqueDeclName = It->second; 12593 IVLVal = D.IVLVal; 12594 FoundFn = D.Fn; 12595 break; 12596 } 12597 return FoundE == E; 12598 } 12599 bool VisitStmt(const Stmt *S) { 12600 for (const Stmt *Child : S->children()) { 12601 if (!Child) 12602 continue; 12603 if (const auto *E = dyn_cast<Expr>(Child)) 12604 if (!E->isGLValue()) 12605 continue; 12606 if (Visit(Child)) 12607 return true; 12608 } 12609 return false; 12610 } 12611 explicit LastprivateConditionalRefChecker( 12612 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 12613 : LPM(LPM) {} 12614 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 12615 getFoundData() const { 12616 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 12617 } 12618 }; 12619 } // namespace 12620 12621 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 12622 LValue IVLVal, 12623 StringRef UniqueDeclName, 12624 LValue LVal, 12625 SourceLocation Loc) { 12626 // Last updated loop counter for the lastprivate conditional var. 12627 // int<xx> last_iv = 0; 12628 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 12629 llvm::Constant *LastIV = 12630 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 12631 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 12632 IVLVal.getAlignment().getAsAlign()); 12633 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 12634 12635 // Last value of the lastprivate conditional. 12636 // decltype(priv_a) last_a; 12637 llvm::Constant *Last = getOrCreateInternalVariable( 12638 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 12639 cast<llvm::GlobalVariable>(Last)->setAlignment( 12640 LVal.getAlignment().getAsAlign()); 12641 LValue LastLVal = 12642 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 12643 12644 // Global loop counter. Required to handle inner parallel-for regions. 12645 // iv 12646 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 12647 12648 // #pragma omp critical(a) 12649 // if (last_iv <= iv) { 12650 // last_iv = iv; 12651 // last_a = priv_a; 12652 // } 12653 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 12654 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 12655 Action.Enter(CGF); 12656 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 12657 // (last_iv <= iv) ? Check if the variable is updated and store new 12658 // value in global var. 12659 llvm::Value *CmpRes; 12660 if (IVLVal.getType()->isSignedIntegerType()) { 12661 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 12662 } else { 12663 assert(IVLVal.getType()->isUnsignedIntegerType() && 12664 "Loop iteration variable must be integer."); 12665 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 12666 } 12667 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 12668 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 12669 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 12670 // { 12671 CGF.EmitBlock(ThenBB); 12672 12673 // last_iv = iv; 12674 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 12675 12676 // last_a = priv_a; 12677 switch (CGF.getEvaluationKind(LVal.getType())) { 12678 case TEK_Scalar: { 12679 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 12680 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 12681 break; 12682 } 12683 case TEK_Complex: { 12684 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 12685 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 12686 break; 12687 } 12688 case TEK_Aggregate: 12689 llvm_unreachable( 12690 "Aggregates are not supported in lastprivate conditional."); 12691 } 12692 // } 12693 CGF.EmitBranch(ExitBB); 12694 // There is no need to emit line number for unconditional branch. 12695 (void)ApplyDebugLocation::CreateEmpty(CGF); 12696 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 12697 }; 12698 12699 if (CGM.getLangOpts().OpenMPSimd) { 12700 // Do not emit as a critical region as no parallel region could be emitted. 12701 RegionCodeGenTy ThenRCG(CodeGen); 12702 ThenRCG(CGF); 12703 } else { 12704 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 12705 } 12706 } 12707 12708 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 12709 const Expr *LHS) { 12710 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12711 return; 12712 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 12713 if (!Checker.Visit(LHS)) 12714 return; 12715 const Expr *FoundE; 12716 const Decl *FoundD; 12717 StringRef UniqueDeclName; 12718 LValue IVLVal; 12719 llvm::Function *FoundFn; 12720 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 12721 Checker.getFoundData(); 12722 if (FoundFn != CGF.CurFn) { 12723 // Special codegen for inner parallel regions. 12724 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 12725 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 12726 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 12727 "Lastprivate conditional is not found in outer region."); 12728 QualType StructTy = std::get<0>(It->getSecond()); 12729 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 12730 LValue PrivLVal = CGF.EmitLValue(FoundE); 12731 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12732 PrivLVal.getAddress(CGF), 12733 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 12734 LValue BaseLVal = 12735 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 12736 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 12737 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 12738 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 12739 FiredLVal, llvm::AtomicOrdering::Unordered, 12740 /*IsVolatile=*/true, /*isInit=*/false); 12741 return; 12742 } 12743 12744 // Private address of the lastprivate conditional in the current context. 12745 // priv_a 12746 LValue LVal = CGF.EmitLValue(FoundE); 12747 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 12748 FoundE->getExprLoc()); 12749 } 12750 12751 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 12752 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12753 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 12754 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12755 return; 12756 auto Range = llvm::reverse(LastprivateConditionalStack); 12757 auto It = llvm::find_if( 12758 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 12759 if (It == Range.end() || It->Fn != CGF.CurFn) 12760 return; 12761 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 12762 assert(LPCI != LastprivateConditionalToTypes.end() && 12763 "Lastprivates must be registered already."); 12764 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12765 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 12766 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 12767 for (const auto &Pair : It->DeclToUniqueName) { 12768 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 12769 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 12770 continue; 12771 auto I = LPCI->getSecond().find(Pair.first); 12772 assert(I != LPCI->getSecond().end() && 12773 "Lastprivate must be rehistered already."); 12774 // bool Cmp = priv_a.Fired != 0; 12775 LValue BaseLVal = std::get<3>(I->getSecond()); 12776 LValue FiredLVal = 12777 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 12778 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 12779 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 12780 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 12781 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 12782 // if (Cmp) { 12783 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 12784 CGF.EmitBlock(ThenBB); 12785 Address Addr = CGF.GetAddrOfLocalVar(VD); 12786 LValue LVal; 12787 if (VD->getType()->isReferenceType()) 12788 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 12789 AlignmentSource::Decl); 12790 else 12791 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 12792 AlignmentSource::Decl); 12793 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 12794 D.getBeginLoc()); 12795 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 12796 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 12797 // } 12798 } 12799 } 12800 12801 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 12802 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 12803 SourceLocation Loc) { 12804 if (CGF.getLangOpts().OpenMP < 50) 12805 return; 12806 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 12807 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 12808 "Unknown lastprivate conditional variable."); 12809 StringRef UniqueName = It->second; 12810 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 12811 // The variable was not updated in the region - exit. 12812 if (!GV) 12813 return; 12814 LValue LPLVal = CGF.MakeAddrLValue( 12815 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 12816 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 12817 CGF.EmitStoreOfScalar(Res, PrivLVal); 12818 } 12819 12820 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 12821 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12822 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12823 llvm_unreachable("Not supported in SIMD-only mode"); 12824 } 12825 12826 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 12827 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12828 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12829 llvm_unreachable("Not supported in SIMD-only mode"); 12830 } 12831 12832 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 12833 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12834 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 12835 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 12836 bool Tied, unsigned &NumberOfParts) { 12837 llvm_unreachable("Not supported in SIMD-only mode"); 12838 } 12839 12840 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 12841 SourceLocation Loc, 12842 llvm::Function *OutlinedFn, 12843 ArrayRef<llvm::Value *> CapturedVars, 12844 const Expr *IfCond) { 12845 llvm_unreachable("Not supported in SIMD-only mode"); 12846 } 12847 12848 void CGOpenMPSIMDRuntime::emitCriticalRegion( 12849 CodeGenFunction &CGF, StringRef CriticalName, 12850 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 12851 const Expr *Hint) { 12852 llvm_unreachable("Not supported in SIMD-only mode"); 12853 } 12854 12855 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 12856 const RegionCodeGenTy &MasterOpGen, 12857 SourceLocation Loc) { 12858 llvm_unreachable("Not supported in SIMD-only mode"); 12859 } 12860 12861 void CGOpenMPSIMDRuntime::emitMaskedRegion(CodeGenFunction &CGF, 12862 const RegionCodeGenTy &MasterOpGen, 12863 SourceLocation Loc, 12864 const Expr *Filter) { 12865 llvm_unreachable("Not supported in SIMD-only mode"); 12866 } 12867 12868 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 12869 SourceLocation Loc) { 12870 llvm_unreachable("Not supported in SIMD-only mode"); 12871 } 12872 12873 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 12874 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 12875 SourceLocation Loc) { 12876 llvm_unreachable("Not supported in SIMD-only mode"); 12877 } 12878 12879 void CGOpenMPSIMDRuntime::emitSingleRegion( 12880 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 12881 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 12882 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 12883 ArrayRef<const Expr *> AssignmentOps) { 12884 llvm_unreachable("Not supported in SIMD-only mode"); 12885 } 12886 12887 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 12888 const RegionCodeGenTy &OrderedOpGen, 12889 SourceLocation Loc, 12890 bool IsThreads) { 12891 llvm_unreachable("Not supported in SIMD-only mode"); 12892 } 12893 12894 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 12895 SourceLocation Loc, 12896 OpenMPDirectiveKind Kind, 12897 bool EmitChecks, 12898 bool ForceSimpleCall) { 12899 llvm_unreachable("Not supported in SIMD-only mode"); 12900 } 12901 12902 void CGOpenMPSIMDRuntime::emitForDispatchInit( 12903 CodeGenFunction &CGF, SourceLocation Loc, 12904 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 12905 bool Ordered, const DispatchRTInput &DispatchValues) { 12906 llvm_unreachable("Not supported in SIMD-only mode"); 12907 } 12908 12909 void CGOpenMPSIMDRuntime::emitForStaticInit( 12910 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 12911 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 12912 llvm_unreachable("Not supported in SIMD-only mode"); 12913 } 12914 12915 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 12916 CodeGenFunction &CGF, SourceLocation Loc, 12917 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 12918 llvm_unreachable("Not supported in SIMD-only mode"); 12919 } 12920 12921 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 12922 SourceLocation Loc, 12923 unsigned IVSize, 12924 bool IVSigned) { 12925 llvm_unreachable("Not supported in SIMD-only mode"); 12926 } 12927 12928 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 12929 SourceLocation Loc, 12930 OpenMPDirectiveKind DKind) { 12931 llvm_unreachable("Not supported in SIMD-only mode"); 12932 } 12933 12934 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 12935 SourceLocation Loc, 12936 unsigned IVSize, bool IVSigned, 12937 Address IL, Address LB, 12938 Address UB, Address ST) { 12939 llvm_unreachable("Not supported in SIMD-only mode"); 12940 } 12941 12942 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 12943 llvm::Value *NumThreads, 12944 SourceLocation Loc) { 12945 llvm_unreachable("Not supported in SIMD-only mode"); 12946 } 12947 12948 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 12949 ProcBindKind ProcBind, 12950 SourceLocation Loc) { 12951 llvm_unreachable("Not supported in SIMD-only mode"); 12952 } 12953 12954 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 12955 const VarDecl *VD, 12956 Address VDAddr, 12957 SourceLocation Loc) { 12958 llvm_unreachable("Not supported in SIMD-only mode"); 12959 } 12960 12961 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 12962 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 12963 CodeGenFunction *CGF) { 12964 llvm_unreachable("Not supported in SIMD-only mode"); 12965 } 12966 12967 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 12968 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 12969 llvm_unreachable("Not supported in SIMD-only mode"); 12970 } 12971 12972 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 12973 ArrayRef<const Expr *> Vars, 12974 SourceLocation Loc, 12975 llvm::AtomicOrdering AO) { 12976 llvm_unreachable("Not supported in SIMD-only mode"); 12977 } 12978 12979 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 12980 const OMPExecutableDirective &D, 12981 llvm::Function *TaskFunction, 12982 QualType SharedsTy, Address Shareds, 12983 const Expr *IfCond, 12984 const OMPTaskDataTy &Data) { 12985 llvm_unreachable("Not supported in SIMD-only mode"); 12986 } 12987 12988 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 12989 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 12990 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 12991 const Expr *IfCond, const OMPTaskDataTy &Data) { 12992 llvm_unreachable("Not supported in SIMD-only mode"); 12993 } 12994 12995 void CGOpenMPSIMDRuntime::emitReduction( 12996 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 12997 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 12998 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 12999 assert(Options.SimpleReduction && "Only simple reduction is expected."); 13000 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 13001 ReductionOps, Options); 13002 } 13003 13004 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 13005 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 13006 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 13007 llvm_unreachable("Not supported in SIMD-only mode"); 13008 } 13009 13010 void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 13011 SourceLocation Loc, 13012 bool IsWorksharingReduction) { 13013 llvm_unreachable("Not supported in SIMD-only mode"); 13014 } 13015 13016 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 13017 SourceLocation Loc, 13018 ReductionCodeGen &RCG, 13019 unsigned N) { 13020 llvm_unreachable("Not supported in SIMD-only mode"); 13021 } 13022 13023 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 13024 SourceLocation Loc, 13025 llvm::Value *ReductionsPtr, 13026 LValue SharedLVal) { 13027 llvm_unreachable("Not supported in SIMD-only mode"); 13028 } 13029 13030 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 13031 SourceLocation Loc) { 13032 llvm_unreachable("Not supported in SIMD-only mode"); 13033 } 13034 13035 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 13036 CodeGenFunction &CGF, SourceLocation Loc, 13037 OpenMPDirectiveKind CancelRegion) { 13038 llvm_unreachable("Not supported in SIMD-only mode"); 13039 } 13040 13041 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 13042 SourceLocation Loc, const Expr *IfCond, 13043 OpenMPDirectiveKind CancelRegion) { 13044 llvm_unreachable("Not supported in SIMD-only mode"); 13045 } 13046 13047 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 13048 const OMPExecutableDirective &D, StringRef ParentName, 13049 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 13050 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 13051 llvm_unreachable("Not supported in SIMD-only mode"); 13052 } 13053 13054 void CGOpenMPSIMDRuntime::emitTargetCall( 13055 CodeGenFunction &CGF, const OMPExecutableDirective &D, 13056 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 13057 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 13058 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 13059 const OMPLoopDirective &D)> 13060 SizeEmitter) { 13061 llvm_unreachable("Not supported in SIMD-only mode"); 13062 } 13063 13064 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 13065 llvm_unreachable("Not supported in SIMD-only mode"); 13066 } 13067 13068 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 13069 llvm_unreachable("Not supported in SIMD-only mode"); 13070 } 13071 13072 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 13073 return false; 13074 } 13075 13076 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 13077 const OMPExecutableDirective &D, 13078 SourceLocation Loc, 13079 llvm::Function *OutlinedFn, 13080 ArrayRef<llvm::Value *> CapturedVars) { 13081 llvm_unreachable("Not supported in SIMD-only mode"); 13082 } 13083 13084 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 13085 const Expr *NumTeams, 13086 const Expr *ThreadLimit, 13087 SourceLocation Loc) { 13088 llvm_unreachable("Not supported in SIMD-only mode"); 13089 } 13090 13091 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 13092 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 13093 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 13094 llvm_unreachable("Not supported in SIMD-only mode"); 13095 } 13096 13097 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 13098 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 13099 const Expr *Device) { 13100 llvm_unreachable("Not supported in SIMD-only mode"); 13101 } 13102 13103 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 13104 const OMPLoopDirective &D, 13105 ArrayRef<Expr *> NumIterations) { 13106 llvm_unreachable("Not supported in SIMD-only mode"); 13107 } 13108 13109 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 13110 const OMPDependClause *C) { 13111 llvm_unreachable("Not supported in SIMD-only mode"); 13112 } 13113 13114 const VarDecl * 13115 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 13116 const VarDecl *NativeParam) const { 13117 llvm_unreachable("Not supported in SIMD-only mode"); 13118 } 13119 13120 Address 13121 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 13122 const VarDecl *NativeParam, 13123 const VarDecl *TargetParam) const { 13124 llvm_unreachable("Not supported in SIMD-only mode"); 13125 } 13126