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_RValue); 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 = CGF.Builder.CreateGEP(DestBegin, NumElements); 702 // The basic structure here is a while-do loop. 703 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 704 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 705 llvm::Value *IsEmpty = 706 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 707 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 708 709 // Enter the loop body, making that address the current address. 710 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 711 CGF.EmitBlock(BodyBB); 712 713 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 714 715 llvm::PHINode *SrcElementPHI = nullptr; 716 Address SrcElementCurrent = Address::invalid(); 717 if (DRD) { 718 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 719 "omp.arraycpy.srcElementPast"); 720 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 721 SrcElementCurrent = 722 Address(SrcElementPHI, 723 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 724 } 725 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 726 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 727 DestElementPHI->addIncoming(DestBegin, EntryBB); 728 Address DestElementCurrent = 729 Address(DestElementPHI, 730 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 731 732 // Emit copy. 733 { 734 CodeGenFunction::RunCleanupsScope InitScope(CGF); 735 if (EmitDeclareReductionInit) { 736 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 737 SrcElementCurrent, ElementTy); 738 } else 739 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 740 /*IsInitializer=*/false); 741 } 742 743 if (DRD) { 744 // Shift the address forward by one element. 745 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 746 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 747 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 748 } 749 750 // Shift the address forward by one element. 751 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 752 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 753 // Check whether we've reached the end. 754 llvm::Value *Done = 755 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 756 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 757 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 758 759 // Done. 760 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 761 } 762 763 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 764 return CGF.EmitOMPSharedLValue(E); 765 } 766 767 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 768 const Expr *E) { 769 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 770 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 771 return LValue(); 772 } 773 774 void ReductionCodeGen::emitAggregateInitialization( 775 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 776 const OMPDeclareReductionDecl *DRD) { 777 // Emit VarDecl with copy init for arrays. 778 // Get the address of the original variable captured in current 779 // captured region. 780 const auto *PrivateVD = 781 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 782 bool EmitDeclareReductionInit = 783 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 784 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 785 EmitDeclareReductionInit, 786 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 787 : PrivateVD->getInit(), 788 DRD, SharedLVal.getAddress(CGF)); 789 } 790 791 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 792 ArrayRef<const Expr *> Origs, 793 ArrayRef<const Expr *> Privates, 794 ArrayRef<const Expr *> ReductionOps) { 795 ClausesData.reserve(Shareds.size()); 796 SharedAddresses.reserve(Shareds.size()); 797 Sizes.reserve(Shareds.size()); 798 BaseDecls.reserve(Shareds.size()); 799 const auto *IOrig = Origs.begin(); 800 const auto *IPriv = Privates.begin(); 801 const auto *IRed = ReductionOps.begin(); 802 for (const Expr *Ref : Shareds) { 803 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed); 804 std::advance(IOrig, 1); 805 std::advance(IPriv, 1); 806 std::advance(IRed, 1); 807 } 808 } 809 810 void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) { 811 assert(SharedAddresses.size() == N && OrigAddresses.size() == N && 812 "Number of generated lvalues must be exactly N."); 813 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared); 814 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared); 815 SharedAddresses.emplace_back(First, Second); 816 if (ClausesData[N].Shared == ClausesData[N].Ref) { 817 OrigAddresses.emplace_back(First, Second); 818 } else { 819 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 820 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 821 OrigAddresses.emplace_back(First, Second); 822 } 823 } 824 825 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 826 const auto *PrivateVD = 827 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 828 QualType PrivateType = PrivateVD->getType(); 829 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 830 if (!PrivateType->isVariablyModifiedType()) { 831 Sizes.emplace_back( 832 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()), 833 nullptr); 834 return; 835 } 836 llvm::Value *Size; 837 llvm::Value *SizeInChars; 838 auto *ElemType = 839 cast<llvm::PointerType>(OrigAddresses[N].first.getPointer(CGF)->getType()) 840 ->getElementType(); 841 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 842 if (AsArraySection) { 843 Size = CGF.Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF), 844 OrigAddresses[N].first.getPointer(CGF)); 845 Size = CGF.Builder.CreateNUWAdd( 846 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 847 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 848 } else { 849 SizeInChars = 850 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()); 851 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 852 } 853 Sizes.emplace_back(SizeInChars, Size); 854 CodeGenFunction::OpaqueValueMapping OpaqueMap( 855 CGF, 856 cast<OpaqueValueExpr>( 857 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 858 RValue::get(Size)); 859 CGF.EmitVariablyModifiedType(PrivateType); 860 } 861 862 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 863 llvm::Value *Size) { 864 const auto *PrivateVD = 865 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 866 QualType PrivateType = PrivateVD->getType(); 867 if (!PrivateType->isVariablyModifiedType()) { 868 assert(!Size && !Sizes[N].second && 869 "Size should be nullptr for non-variably modified reduction " 870 "items."); 871 return; 872 } 873 CodeGenFunction::OpaqueValueMapping OpaqueMap( 874 CGF, 875 cast<OpaqueValueExpr>( 876 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 877 RValue::get(Size)); 878 CGF.EmitVariablyModifiedType(PrivateType); 879 } 880 881 void ReductionCodeGen::emitInitialization( 882 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 883 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 884 assert(SharedAddresses.size() > N && "No variable was generated"); 885 const auto *PrivateVD = 886 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 887 const OMPDeclareReductionDecl *DRD = 888 getReductionInit(ClausesData[N].ReductionOp); 889 QualType PrivateType = PrivateVD->getType(); 890 PrivateAddr = CGF.Builder.CreateElementBitCast( 891 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 892 QualType SharedType = SharedAddresses[N].first.getType(); 893 SharedLVal = CGF.MakeAddrLValue( 894 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 895 CGF.ConvertTypeForMem(SharedType)), 896 SharedType, SharedAddresses[N].first.getBaseInfo(), 897 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 898 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 899 if (DRD && DRD->getInitializer()) 900 (void)DefaultInit(CGF); 901 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 902 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 903 (void)DefaultInit(CGF); 904 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 905 PrivateAddr, SharedLVal.getAddress(CGF), 906 SharedLVal.getType()); 907 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 908 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 909 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 910 PrivateVD->getType().getQualifiers(), 911 /*IsInitializer=*/false); 912 } 913 } 914 915 bool ReductionCodeGen::needCleanups(unsigned N) { 916 const auto *PrivateVD = 917 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 918 QualType PrivateType = PrivateVD->getType(); 919 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 920 return DTorKind != QualType::DK_none; 921 } 922 923 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 924 Address PrivateAddr) { 925 const auto *PrivateVD = 926 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 927 QualType PrivateType = PrivateVD->getType(); 928 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 929 if (needCleanups(N)) { 930 PrivateAddr = CGF.Builder.CreateElementBitCast( 931 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 932 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 933 } 934 } 935 936 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 937 LValue BaseLV) { 938 BaseTy = BaseTy.getNonReferenceType(); 939 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 940 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 941 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 942 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 943 } else { 944 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 945 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 946 } 947 BaseTy = BaseTy->getPointeeType(); 948 } 949 return CGF.MakeAddrLValue( 950 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 951 CGF.ConvertTypeForMem(ElTy)), 952 BaseLV.getType(), BaseLV.getBaseInfo(), 953 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 954 } 955 956 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 957 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 958 llvm::Value *Addr) { 959 Address Tmp = Address::invalid(); 960 Address TopTmp = Address::invalid(); 961 Address MostTopTmp = Address::invalid(); 962 BaseTy = BaseTy.getNonReferenceType(); 963 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 964 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 965 Tmp = CGF.CreateMemTemp(BaseTy); 966 if (TopTmp.isValid()) 967 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 968 else 969 MostTopTmp = Tmp; 970 TopTmp = Tmp; 971 BaseTy = BaseTy->getPointeeType(); 972 } 973 llvm::Type *Ty = BaseLVType; 974 if (Tmp.isValid()) 975 Ty = Tmp.getElementType(); 976 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 977 if (Tmp.isValid()) { 978 CGF.Builder.CreateStore(Addr, Tmp); 979 return MostTopTmp; 980 } 981 return Address(Addr, BaseLVAlignment); 982 } 983 984 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 985 const VarDecl *OrigVD = nullptr; 986 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 987 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 988 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 989 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 990 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 991 Base = TempASE->getBase()->IgnoreParenImpCasts(); 992 DE = cast<DeclRefExpr>(Base); 993 OrigVD = cast<VarDecl>(DE->getDecl()); 994 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 995 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 996 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 997 Base = TempASE->getBase()->IgnoreParenImpCasts(); 998 DE = cast<DeclRefExpr>(Base); 999 OrigVD = cast<VarDecl>(DE->getDecl()); 1000 } 1001 return OrigVD; 1002 } 1003 1004 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1005 Address PrivateAddr) { 1006 const DeclRefExpr *DE; 1007 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1008 BaseDecls.emplace_back(OrigVD); 1009 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1010 LValue BaseLValue = 1011 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1012 OriginalBaseLValue); 1013 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1014 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1015 llvm::Value *PrivatePointer = 1016 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1017 PrivateAddr.getPointer(), 1018 SharedAddresses[N].first.getAddress(CGF).getType()); 1019 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1020 return castToBase(CGF, OrigVD->getType(), 1021 SharedAddresses[N].first.getType(), 1022 OriginalBaseLValue.getAddress(CGF).getType(), 1023 OriginalBaseLValue.getAlignment(), Ptr); 1024 } 1025 BaseDecls.emplace_back( 1026 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1027 return PrivateAddr; 1028 } 1029 1030 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1031 const OMPDeclareReductionDecl *DRD = 1032 getReductionInit(ClausesData[N].ReductionOp); 1033 return DRD && DRD->getInitializer(); 1034 } 1035 1036 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1037 return CGF.EmitLoadOfPointerLValue( 1038 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1039 getThreadIDVariable()->getType()->castAs<PointerType>()); 1040 } 1041 1042 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt *S) { 1043 if (!CGF.HaveInsertPoint()) 1044 return; 1045 // 1.2.2 OpenMP Language Terminology 1046 // Structured block - An executable statement with a single entry at the 1047 // top and a single exit at the bottom. 1048 // The point of exit cannot be a branch out of the structured block. 1049 // longjmp() and throw() must not violate the entry/exit criteria. 1050 CGF.EHStack.pushTerminate(); 1051 if (S) 1052 CGF.incrementProfileCounter(S); 1053 CodeGen(CGF); 1054 CGF.EHStack.popTerminate(); 1055 } 1056 1057 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1058 CodeGenFunction &CGF) { 1059 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1060 getThreadIDVariable()->getType(), 1061 AlignmentSource::Decl); 1062 } 1063 1064 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1065 QualType FieldTy) { 1066 auto *Field = FieldDecl::Create( 1067 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1068 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1069 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1070 Field->setAccess(AS_public); 1071 DC->addDecl(Field); 1072 return Field; 1073 } 1074 1075 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1076 StringRef Separator) 1077 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1078 OMPBuilder(CGM.getModule()), OffloadEntriesInfoManager(CGM) { 1079 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1080 1081 // Initialize Types used in OpenMPIRBuilder from OMPKinds.def 1082 OMPBuilder.initialize(); 1083 loadOffloadInfoMetadata(); 1084 } 1085 1086 void CGOpenMPRuntime::clear() { 1087 InternalVars.clear(); 1088 // Clean non-target variable declarations possibly used only in debug info. 1089 for (const auto &Data : EmittedNonTargetVariables) { 1090 if (!Data.getValue().pointsToAliveValue()) 1091 continue; 1092 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1093 if (!GV) 1094 continue; 1095 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1096 continue; 1097 GV->eraseFromParent(); 1098 } 1099 } 1100 1101 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1102 SmallString<128> Buffer; 1103 llvm::raw_svector_ostream OS(Buffer); 1104 StringRef Sep = FirstSeparator; 1105 for (StringRef Part : Parts) { 1106 OS << Sep << Part; 1107 Sep = Separator; 1108 } 1109 return std::string(OS.str()); 1110 } 1111 1112 static llvm::Function * 1113 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1114 const Expr *CombinerInitializer, const VarDecl *In, 1115 const VarDecl *Out, bool IsCombiner) { 1116 // void .omp_combiner.(Ty *in, Ty *out); 1117 ASTContext &C = CGM.getContext(); 1118 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1119 FunctionArgList Args; 1120 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1121 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1122 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1123 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1124 Args.push_back(&OmpOutParm); 1125 Args.push_back(&OmpInParm); 1126 const CGFunctionInfo &FnInfo = 1127 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1128 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1129 std::string Name = CGM.getOpenMPRuntime().getName( 1130 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1131 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1132 Name, &CGM.getModule()); 1133 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1134 if (CGM.getLangOpts().Optimize) { 1135 Fn->removeFnAttr(llvm::Attribute::NoInline); 1136 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1137 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1138 } 1139 CodeGenFunction CGF(CGM); 1140 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1141 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1142 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1143 Out->getLocation()); 1144 CodeGenFunction::OMPPrivateScope Scope(CGF); 1145 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1146 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1147 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1148 .getAddress(CGF); 1149 }); 1150 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1151 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1152 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1153 .getAddress(CGF); 1154 }); 1155 (void)Scope.Privatize(); 1156 if (!IsCombiner && Out->hasInit() && 1157 !CGF.isTrivialInitializer(Out->getInit())) { 1158 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1159 Out->getType().getQualifiers(), 1160 /*IsInitializer=*/true); 1161 } 1162 if (CombinerInitializer) 1163 CGF.EmitIgnoredExpr(CombinerInitializer); 1164 Scope.ForceCleanup(); 1165 CGF.FinishFunction(); 1166 return Fn; 1167 } 1168 1169 void CGOpenMPRuntime::emitUserDefinedReduction( 1170 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1171 if (UDRMap.count(D) > 0) 1172 return; 1173 llvm::Function *Combiner = emitCombinerOrInitializer( 1174 CGM, D->getType(), D->getCombiner(), 1175 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1176 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1177 /*IsCombiner=*/true); 1178 llvm::Function *Initializer = nullptr; 1179 if (const Expr *Init = D->getInitializer()) { 1180 Initializer = emitCombinerOrInitializer( 1181 CGM, D->getType(), 1182 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1183 : nullptr, 1184 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1185 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1186 /*IsCombiner=*/false); 1187 } 1188 UDRMap.try_emplace(D, Combiner, Initializer); 1189 if (CGF) { 1190 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1191 Decls.second.push_back(D); 1192 } 1193 } 1194 1195 std::pair<llvm::Function *, llvm::Function *> 1196 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1197 auto I = UDRMap.find(D); 1198 if (I != UDRMap.end()) 1199 return I->second; 1200 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1201 return UDRMap.lookup(D); 1202 } 1203 1204 namespace { 1205 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1206 // Builder if one is present. 1207 struct PushAndPopStackRAII { 1208 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1209 bool HasCancel, llvm::omp::Directive Kind) 1210 : OMPBuilder(OMPBuilder) { 1211 if (!OMPBuilder) 1212 return; 1213 1214 // The following callback is the crucial part of clangs cleanup process. 1215 // 1216 // NOTE: 1217 // Once the OpenMPIRBuilder is used to create parallel regions (and 1218 // similar), the cancellation destination (Dest below) is determined via 1219 // IP. That means if we have variables to finalize we split the block at IP, 1220 // use the new block (=BB) as destination to build a JumpDest (via 1221 // getJumpDestInCurrentScope(BB)) which then is fed to 1222 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1223 // to push & pop an FinalizationInfo object. 1224 // The FiniCB will still be needed but at the point where the 1225 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1226 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1227 assert(IP.getBlock()->end() == IP.getPoint() && 1228 "Clang CG should cause non-terminated block!"); 1229 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1230 CGF.Builder.restoreIP(IP); 1231 CodeGenFunction::JumpDest Dest = 1232 CGF.getOMPCancelDestination(OMPD_parallel); 1233 CGF.EmitBranchThroughCleanup(Dest); 1234 }; 1235 1236 // TODO: Remove this once we emit parallel regions through the 1237 // OpenMPIRBuilder as it can do this setup internally. 1238 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel}); 1239 OMPBuilder->pushFinalizationCB(std::move(FI)); 1240 } 1241 ~PushAndPopStackRAII() { 1242 if (OMPBuilder) 1243 OMPBuilder->popFinalizationCB(); 1244 } 1245 llvm::OpenMPIRBuilder *OMPBuilder; 1246 }; 1247 } // namespace 1248 1249 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1250 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1251 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1252 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1253 assert(ThreadIDVar->getType()->isPointerType() && 1254 "thread id variable must be of type kmp_int32 *"); 1255 CodeGenFunction CGF(CGM, true); 1256 bool HasCancel = false; 1257 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1258 HasCancel = OPD->hasCancel(); 1259 else if (const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D)) 1260 HasCancel = OPD->hasCancel(); 1261 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1262 HasCancel = OPSD->hasCancel(); 1263 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1264 HasCancel = OPFD->hasCancel(); 1265 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1266 HasCancel = OPFD->hasCancel(); 1267 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1268 HasCancel = OPFD->hasCancel(); 1269 else if (const auto *OPFD = 1270 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1271 HasCancel = OPFD->hasCancel(); 1272 else if (const auto *OPFD = 1273 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1274 HasCancel = OPFD->hasCancel(); 1275 1276 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1277 // parallel region to make cancellation barriers work properly. 1278 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); 1279 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind); 1280 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1281 HasCancel, OutlinedHelperName); 1282 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1283 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1284 } 1285 1286 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1287 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1288 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1289 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1290 return emitParallelOrTeamsOutlinedFunction( 1291 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1292 } 1293 1294 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1295 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1296 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1297 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1298 return emitParallelOrTeamsOutlinedFunction( 1299 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1300 } 1301 1302 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1303 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1304 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1305 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1306 bool Tied, unsigned &NumberOfParts) { 1307 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1308 PrePostActionTy &) { 1309 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1310 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1311 llvm::Value *TaskArgs[] = { 1312 UpLoc, ThreadID, 1313 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1314 TaskTVar->getType()->castAs<PointerType>()) 1315 .getPointer(CGF)}; 1316 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1317 CGM.getModule(), OMPRTL___kmpc_omp_task), 1318 TaskArgs); 1319 }; 1320 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1321 UntiedCodeGen); 1322 CodeGen.setAction(Action); 1323 assert(!ThreadIDVar->getType()->isPointerType() && 1324 "thread id variable must be of type kmp_int32 for tasks"); 1325 const OpenMPDirectiveKind Region = 1326 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1327 : OMPD_task; 1328 const CapturedStmt *CS = D.getCapturedStmt(Region); 1329 bool HasCancel = false; 1330 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1331 HasCancel = TD->hasCancel(); 1332 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1333 HasCancel = TD->hasCancel(); 1334 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1335 HasCancel = TD->hasCancel(); 1336 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1337 HasCancel = TD->hasCancel(); 1338 1339 CodeGenFunction CGF(CGM, true); 1340 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1341 InnermostKind, HasCancel, Action); 1342 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1343 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1344 if (!Tied) 1345 NumberOfParts = Action.getNumberOfParts(); 1346 return Res; 1347 } 1348 1349 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1350 const RecordDecl *RD, const CGRecordLayout &RL, 1351 ArrayRef<llvm::Constant *> Data) { 1352 llvm::StructType *StructTy = RL.getLLVMType(); 1353 unsigned PrevIdx = 0; 1354 ConstantInitBuilder CIBuilder(CGM); 1355 auto DI = Data.begin(); 1356 for (const FieldDecl *FD : RD->fields()) { 1357 unsigned Idx = RL.getLLVMFieldNo(FD); 1358 // Fill the alignment. 1359 for (unsigned I = PrevIdx; I < Idx; ++I) 1360 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1361 PrevIdx = Idx + 1; 1362 Fields.add(*DI); 1363 ++DI; 1364 } 1365 } 1366 1367 template <class... As> 1368 static llvm::GlobalVariable * 1369 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1370 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1371 As &&... Args) { 1372 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1373 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1374 ConstantInitBuilder CIBuilder(CGM); 1375 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1376 buildStructValue(Fields, CGM, RD, RL, Data); 1377 return Fields.finishAndCreateGlobal( 1378 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1379 std::forward<As>(Args)...); 1380 } 1381 1382 template <typename T> 1383 static void 1384 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1385 ArrayRef<llvm::Constant *> Data, 1386 T &Parent) { 1387 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1388 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1389 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1390 buildStructValue(Fields, CGM, RD, RL, Data); 1391 Fields.finishAndAddTo(Parent); 1392 } 1393 1394 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1395 bool AtCurrentPoint) { 1396 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1397 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1398 1399 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1400 if (AtCurrentPoint) { 1401 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1402 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1403 } else { 1404 Elem.second.ServiceInsertPt = 1405 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1406 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1407 } 1408 } 1409 1410 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1411 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1412 if (Elem.second.ServiceInsertPt) { 1413 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1414 Elem.second.ServiceInsertPt = nullptr; 1415 Ptr->eraseFromParent(); 1416 } 1417 } 1418 1419 static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, 1420 SourceLocation Loc, 1421 SmallString<128> &Buffer) { 1422 llvm::raw_svector_ostream OS(Buffer); 1423 // Build debug location 1424 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1425 OS << ";" << PLoc.getFilename() << ";"; 1426 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1427 OS << FD->getQualifiedNameAsString(); 1428 OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1429 return OS.str(); 1430 } 1431 1432 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1433 SourceLocation Loc, 1434 unsigned Flags) { 1435 llvm::Constant *SrcLocStr; 1436 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1437 Loc.isInvalid()) { 1438 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(); 1439 } else { 1440 std::string FunctionName = ""; 1441 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1442 FunctionName = FD->getQualifiedNameAsString(); 1443 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1444 const char *FileName = PLoc.getFilename(); 1445 unsigned Line = PLoc.getLine(); 1446 unsigned Column = PLoc.getColumn(); 1447 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FunctionName.c_str(), FileName, 1448 Line, Column); 1449 } 1450 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1451 return OMPBuilder.getOrCreateIdent(SrcLocStr, llvm::omp::IdentFlag(Flags), 1452 Reserved2Flags); 1453 } 1454 1455 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1456 SourceLocation Loc) { 1457 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1458 // If the OpenMPIRBuilder is used we need to use it for all thread id calls as 1459 // the clang invariants used below might be broken. 1460 if (CGM.getLangOpts().OpenMPIRBuilder) { 1461 SmallString<128> Buffer; 1462 OMPBuilder.updateToLocation(CGF.Builder.saveIP()); 1463 auto *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr( 1464 getIdentStringFromSourceLocation(CGF, Loc, Buffer)); 1465 return OMPBuilder.getOrCreateThreadID( 1466 OMPBuilder.getOrCreateIdent(SrcLocStr)); 1467 } 1468 1469 llvm::Value *ThreadID = nullptr; 1470 // Check whether we've already cached a load of the thread id in this 1471 // function. 1472 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1473 if (I != OpenMPLocThreadIDMap.end()) { 1474 ThreadID = I->second.ThreadID; 1475 if (ThreadID != nullptr) 1476 return ThreadID; 1477 } 1478 // If exceptions are enabled, do not use parameter to avoid possible crash. 1479 if (auto *OMPRegionInfo = 1480 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1481 if (OMPRegionInfo->getThreadIDVariable()) { 1482 // Check if this an outlined function with thread id passed as argument. 1483 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1484 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1485 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1486 !CGF.getLangOpts().CXXExceptions || 1487 CGF.Builder.GetInsertBlock() == TopBlock || 1488 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1489 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1490 TopBlock || 1491 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1492 CGF.Builder.GetInsertBlock()) { 1493 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1494 // If value loaded in entry block, cache it and use it everywhere in 1495 // function. 1496 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1497 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1498 Elem.second.ThreadID = ThreadID; 1499 } 1500 return ThreadID; 1501 } 1502 } 1503 } 1504 1505 // This is not an outlined function region - need to call __kmpc_int32 1506 // kmpc_global_thread_num(ident_t *loc). 1507 // Generate thread id value and cache this value for use across the 1508 // function. 1509 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1510 if (!Elem.second.ServiceInsertPt) 1511 setLocThreadIdInsertPt(CGF); 1512 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1513 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1514 llvm::CallInst *Call = CGF.Builder.CreateCall( 1515 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 1516 OMPRTL___kmpc_global_thread_num), 1517 emitUpdateLocation(CGF, Loc)); 1518 Call->setCallingConv(CGF.getRuntimeCC()); 1519 Elem.second.ThreadID = Call; 1520 return Call; 1521 } 1522 1523 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1524 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1525 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1526 clearLocThreadIdInsertPt(CGF); 1527 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1528 } 1529 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1530 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1531 UDRMap.erase(D); 1532 FunctionUDRMap.erase(CGF.CurFn); 1533 } 1534 auto I = FunctionUDMMap.find(CGF.CurFn); 1535 if (I != FunctionUDMMap.end()) { 1536 for(const auto *D : I->second) 1537 UDMMap.erase(D); 1538 FunctionUDMMap.erase(I); 1539 } 1540 LastprivateConditionalToTypes.erase(CGF.CurFn); 1541 FunctionToUntiedTaskStackMap.erase(CGF.CurFn); 1542 } 1543 1544 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1545 return OMPBuilder.IdentPtr; 1546 } 1547 1548 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1549 if (!Kmpc_MicroTy) { 1550 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1551 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1552 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1553 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1554 } 1555 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1556 } 1557 1558 llvm::FunctionCallee 1559 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 1560 assert((IVSize == 32 || IVSize == 64) && 1561 "IV size is not compatible with the omp runtime"); 1562 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 1563 : "__kmpc_for_static_init_4u") 1564 : (IVSigned ? "__kmpc_for_static_init_8" 1565 : "__kmpc_for_static_init_8u"); 1566 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1567 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1568 llvm::Type *TypeParams[] = { 1569 getIdentTyPointerTy(), // loc 1570 CGM.Int32Ty, // tid 1571 CGM.Int32Ty, // schedtype 1572 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1573 PtrTy, // p_lower 1574 PtrTy, // p_upper 1575 PtrTy, // p_stride 1576 ITy, // incr 1577 ITy // chunk 1578 }; 1579 auto *FnTy = 1580 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1581 return CGM.CreateRuntimeFunction(FnTy, Name); 1582 } 1583 1584 llvm::FunctionCallee 1585 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 1586 assert((IVSize == 32 || IVSize == 64) && 1587 "IV size is not compatible with the omp runtime"); 1588 StringRef Name = 1589 IVSize == 32 1590 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 1591 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 1592 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1593 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 1594 CGM.Int32Ty, // tid 1595 CGM.Int32Ty, // schedtype 1596 ITy, // lower 1597 ITy, // upper 1598 ITy, // stride 1599 ITy // chunk 1600 }; 1601 auto *FnTy = 1602 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1603 return CGM.CreateRuntimeFunction(FnTy, Name); 1604 } 1605 1606 llvm::FunctionCallee 1607 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 1608 assert((IVSize == 32 || IVSize == 64) && 1609 "IV size is not compatible with the omp runtime"); 1610 StringRef Name = 1611 IVSize == 32 1612 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 1613 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 1614 llvm::Type *TypeParams[] = { 1615 getIdentTyPointerTy(), // loc 1616 CGM.Int32Ty, // tid 1617 }; 1618 auto *FnTy = 1619 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1620 return CGM.CreateRuntimeFunction(FnTy, Name); 1621 } 1622 1623 llvm::FunctionCallee 1624 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 1625 assert((IVSize == 32 || IVSize == 64) && 1626 "IV size is not compatible with the omp runtime"); 1627 StringRef Name = 1628 IVSize == 32 1629 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 1630 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 1631 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1632 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1633 llvm::Type *TypeParams[] = { 1634 getIdentTyPointerTy(), // loc 1635 CGM.Int32Ty, // tid 1636 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1637 PtrTy, // p_lower 1638 PtrTy, // p_upper 1639 PtrTy // p_stride 1640 }; 1641 auto *FnTy = 1642 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1643 return CGM.CreateRuntimeFunction(FnTy, Name); 1644 } 1645 1646 /// Obtain information that uniquely identifies a target entry. This 1647 /// consists of the file and device IDs as well as line number associated with 1648 /// the relevant entry source location. 1649 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 1650 unsigned &DeviceID, unsigned &FileID, 1651 unsigned &LineNum) { 1652 SourceManager &SM = C.getSourceManager(); 1653 1654 // The loc should be always valid and have a file ID (the user cannot use 1655 // #pragma directives in macros) 1656 1657 assert(Loc.isValid() && "Source location is expected to be always valid."); 1658 1659 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 1660 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1661 1662 llvm::sys::fs::UniqueID ID; 1663 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) { 1664 PLoc = SM.getPresumedLoc(Loc, /*UseLineDirectives=*/false); 1665 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1666 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 1667 SM.getDiagnostics().Report(diag::err_cannot_open_file) 1668 << PLoc.getFilename() << EC.message(); 1669 } 1670 1671 DeviceID = ID.getDevice(); 1672 FileID = ID.getFile(); 1673 LineNum = PLoc.getLine(); 1674 } 1675 1676 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 1677 if (CGM.getLangOpts().OpenMPSimd) 1678 return Address::invalid(); 1679 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1680 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1681 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 1682 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1683 HasRequiresUnifiedSharedMemory))) { 1684 SmallString<64> PtrName; 1685 { 1686 llvm::raw_svector_ostream OS(PtrName); 1687 OS << CGM.getMangledName(GlobalDecl(VD)); 1688 if (!VD->isExternallyVisible()) { 1689 unsigned DeviceID, FileID, Line; 1690 getTargetEntryUniqueInfo(CGM.getContext(), 1691 VD->getCanonicalDecl()->getBeginLoc(), 1692 DeviceID, FileID, Line); 1693 OS << llvm::format("_%x", FileID); 1694 } 1695 OS << "_decl_tgt_ref_ptr"; 1696 } 1697 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 1698 if (!Ptr) { 1699 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 1700 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 1701 PtrName); 1702 1703 auto *GV = cast<llvm::GlobalVariable>(Ptr); 1704 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 1705 1706 if (!CGM.getLangOpts().OpenMPIsDevice) 1707 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 1708 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 1709 } 1710 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 1711 } 1712 return Address::invalid(); 1713 } 1714 1715 llvm::Constant * 1716 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 1717 assert(!CGM.getLangOpts().OpenMPUseTLS || 1718 !CGM.getContext().getTargetInfo().isTLSSupported()); 1719 // Lookup the entry, lazily creating it if necessary. 1720 std::string Suffix = getName({"cache", ""}); 1721 return getOrCreateInternalVariable( 1722 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 1723 } 1724 1725 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 1726 const VarDecl *VD, 1727 Address VDAddr, 1728 SourceLocation Loc) { 1729 if (CGM.getLangOpts().OpenMPUseTLS && 1730 CGM.getContext().getTargetInfo().isTLSSupported()) 1731 return VDAddr; 1732 1733 llvm::Type *VarTy = VDAddr.getElementType(); 1734 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1735 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1736 CGM.Int8PtrTy), 1737 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 1738 getOrCreateThreadPrivateCache(VD)}; 1739 return Address(CGF.EmitRuntimeCall( 1740 OMPBuilder.getOrCreateRuntimeFunction( 1741 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 1742 Args), 1743 VDAddr.getAlignment()); 1744 } 1745 1746 void CGOpenMPRuntime::emitThreadPrivateVarInit( 1747 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 1748 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 1749 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 1750 // library. 1751 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 1752 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1753 CGM.getModule(), OMPRTL___kmpc_global_thread_num), 1754 OMPLoc); 1755 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 1756 // to register constructor/destructor for variable. 1757 llvm::Value *Args[] = { 1758 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 1759 Ctor, CopyCtor, Dtor}; 1760 CGF.EmitRuntimeCall( 1761 OMPBuilder.getOrCreateRuntimeFunction( 1762 CGM.getModule(), OMPRTL___kmpc_threadprivate_register), 1763 Args); 1764 } 1765 1766 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 1767 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 1768 bool PerformInit, CodeGenFunction *CGF) { 1769 if (CGM.getLangOpts().OpenMPUseTLS && 1770 CGM.getContext().getTargetInfo().isTLSSupported()) 1771 return nullptr; 1772 1773 VD = VD->getDefinition(CGM.getContext()); 1774 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 1775 QualType ASTTy = VD->getType(); 1776 1777 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 1778 const Expr *Init = VD->getAnyInitializer(); 1779 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1780 // Generate function that re-emits the declaration's initializer into the 1781 // threadprivate copy of the variable VD 1782 CodeGenFunction CtorCGF(CGM); 1783 FunctionArgList Args; 1784 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1785 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1786 ImplicitParamDecl::Other); 1787 Args.push_back(&Dst); 1788 1789 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1790 CGM.getContext().VoidPtrTy, Args); 1791 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1792 std::string Name = getName({"__kmpc_global_ctor_", ""}); 1793 llvm::Function *Fn = 1794 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1795 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 1796 Args, Loc, Loc); 1797 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 1798 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1799 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1800 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 1801 Arg = CtorCGF.Builder.CreateElementBitCast( 1802 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 1803 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1804 /*IsInitializer=*/true); 1805 ArgVal = CtorCGF.EmitLoadOfScalar( 1806 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1807 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1808 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1809 CtorCGF.FinishFunction(); 1810 Ctor = Fn; 1811 } 1812 if (VD->getType().isDestructedType() != QualType::DK_none) { 1813 // Generate function that emits destructor call for the threadprivate copy 1814 // of the variable VD 1815 CodeGenFunction DtorCGF(CGM); 1816 FunctionArgList Args; 1817 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1818 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1819 ImplicitParamDecl::Other); 1820 Args.push_back(&Dst); 1821 1822 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1823 CGM.getContext().VoidTy, Args); 1824 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1825 std::string Name = getName({"__kmpc_global_dtor_", ""}); 1826 llvm::Function *Fn = 1827 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1828 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1829 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1830 Loc, Loc); 1831 // Create a scope with an artificial location for the body of this function. 1832 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1833 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 1834 DtorCGF.GetAddrOfLocalVar(&Dst), 1835 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 1836 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 1837 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1838 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1839 DtorCGF.FinishFunction(); 1840 Dtor = Fn; 1841 } 1842 // Do not emit init function if it is not required. 1843 if (!Ctor && !Dtor) 1844 return nullptr; 1845 1846 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1847 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1848 /*isVarArg=*/false) 1849 ->getPointerTo(); 1850 // Copying constructor for the threadprivate variable. 1851 // Must be NULL - reserved by runtime, but currently it requires that this 1852 // parameter is always NULL. Otherwise it fires assertion. 1853 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1854 if (Ctor == nullptr) { 1855 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1856 /*isVarArg=*/false) 1857 ->getPointerTo(); 1858 Ctor = llvm::Constant::getNullValue(CtorTy); 1859 } 1860 if (Dtor == nullptr) { 1861 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1862 /*isVarArg=*/false) 1863 ->getPointerTo(); 1864 Dtor = llvm::Constant::getNullValue(DtorTy); 1865 } 1866 if (!CGF) { 1867 auto *InitFunctionTy = 1868 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1869 std::string Name = getName({"__omp_threadprivate_init_", ""}); 1870 llvm::Function *InitFunction = CGM.CreateGlobalInitOrCleanUpFunction( 1871 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 1872 CodeGenFunction InitCGF(CGM); 1873 FunctionArgList ArgList; 1874 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1875 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1876 Loc, Loc); 1877 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1878 InitCGF.FinishFunction(); 1879 return InitFunction; 1880 } 1881 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1882 } 1883 return nullptr; 1884 } 1885 1886 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 1887 llvm::GlobalVariable *Addr, 1888 bool PerformInit) { 1889 if (CGM.getLangOpts().OMPTargetTriples.empty() && 1890 !CGM.getLangOpts().OpenMPIsDevice) 1891 return false; 1892 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1893 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1894 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 1895 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1896 HasRequiresUnifiedSharedMemory)) 1897 return CGM.getLangOpts().OpenMPIsDevice; 1898 VD = VD->getDefinition(CGM.getContext()); 1899 assert(VD && "Unknown VarDecl"); 1900 1901 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 1902 return CGM.getLangOpts().OpenMPIsDevice; 1903 1904 QualType ASTTy = VD->getType(); 1905 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 1906 1907 // Produce the unique prefix to identify the new target regions. We use 1908 // the source location of the variable declaration which we know to not 1909 // conflict with any target region. 1910 unsigned DeviceID; 1911 unsigned FileID; 1912 unsigned Line; 1913 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 1914 SmallString<128> Buffer, Out; 1915 { 1916 llvm::raw_svector_ostream OS(Buffer); 1917 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 1918 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 1919 } 1920 1921 const Expr *Init = VD->getAnyInitializer(); 1922 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1923 llvm::Constant *Ctor; 1924 llvm::Constant *ID; 1925 if (CGM.getLangOpts().OpenMPIsDevice) { 1926 // Generate function that re-emits the declaration's initializer into 1927 // the threadprivate copy of the variable VD 1928 CodeGenFunction CtorCGF(CGM); 1929 1930 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1931 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1932 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1933 FTy, Twine(Buffer, "_ctor"), FI, Loc); 1934 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 1935 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1936 FunctionArgList(), Loc, Loc); 1937 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 1938 CtorCGF.EmitAnyExprToMem(Init, 1939 Address(Addr, CGM.getContext().getDeclAlign(VD)), 1940 Init->getType().getQualifiers(), 1941 /*IsInitializer=*/true); 1942 CtorCGF.FinishFunction(); 1943 Ctor = Fn; 1944 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1945 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 1946 } else { 1947 Ctor = new llvm::GlobalVariable( 1948 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1949 llvm::GlobalValue::PrivateLinkage, 1950 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 1951 ID = Ctor; 1952 } 1953 1954 // Register the information for the entry associated with the constructor. 1955 Out.clear(); 1956 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 1957 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 1958 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 1959 } 1960 if (VD->getType().isDestructedType() != QualType::DK_none) { 1961 llvm::Constant *Dtor; 1962 llvm::Constant *ID; 1963 if (CGM.getLangOpts().OpenMPIsDevice) { 1964 // Generate function that emits destructor call for the threadprivate 1965 // copy of the variable VD 1966 CodeGenFunction DtorCGF(CGM); 1967 1968 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1969 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1970 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1971 FTy, Twine(Buffer, "_dtor"), FI, Loc); 1972 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1973 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1974 FunctionArgList(), Loc, Loc); 1975 // Create a scope with an artificial location for the body of this 1976 // function. 1977 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1978 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 1979 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1980 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1981 DtorCGF.FinishFunction(); 1982 Dtor = Fn; 1983 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1984 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 1985 } else { 1986 Dtor = new llvm::GlobalVariable( 1987 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1988 llvm::GlobalValue::PrivateLinkage, 1989 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 1990 ID = Dtor; 1991 } 1992 // Register the information for the entry associated with the destructor. 1993 Out.clear(); 1994 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 1995 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 1996 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 1997 } 1998 return CGM.getLangOpts().OpenMPIsDevice; 1999 } 2000 2001 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2002 QualType VarType, 2003 StringRef Name) { 2004 std::string Suffix = getName({"artificial", ""}); 2005 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2006 llvm::Value *GAddr = 2007 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2008 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 2009 CGM.getTarget().isTLSSupported()) { 2010 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 2011 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 2012 } 2013 std::string CacheSuffix = getName({"cache", ""}); 2014 llvm::Value *Args[] = { 2015 emitUpdateLocation(CGF, SourceLocation()), 2016 getThreadID(CGF, SourceLocation()), 2017 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2018 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2019 /*isSigned=*/false), 2020 getOrCreateInternalVariable( 2021 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2022 return Address( 2023 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2024 CGF.EmitRuntimeCall( 2025 OMPBuilder.getOrCreateRuntimeFunction( 2026 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 2027 Args), 2028 VarLVType->getPointerTo(/*AddrSpace=*/0)), 2029 CGM.getContext().getTypeAlignInChars(VarType)); 2030 } 2031 2032 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 2033 const RegionCodeGenTy &ThenGen, 2034 const RegionCodeGenTy &ElseGen) { 2035 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 2036 2037 // If the condition constant folds and can be elided, try to avoid emitting 2038 // the condition and the dead arm of the if/else. 2039 bool CondConstant; 2040 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 2041 if (CondConstant) 2042 ThenGen(CGF); 2043 else 2044 ElseGen(CGF); 2045 return; 2046 } 2047 2048 // Otherwise, the condition did not fold, or we couldn't elide it. Just 2049 // emit the conditional branch. 2050 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2051 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 2052 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 2053 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 2054 2055 // Emit the 'then' code. 2056 CGF.EmitBlock(ThenBlock); 2057 ThenGen(CGF); 2058 CGF.EmitBranch(ContBlock); 2059 // Emit the 'else' code if present. 2060 // There is no need to emit line number for unconditional branch. 2061 (void)ApplyDebugLocation::CreateEmpty(CGF); 2062 CGF.EmitBlock(ElseBlock); 2063 ElseGen(CGF); 2064 // There is no need to emit line number for unconditional branch. 2065 (void)ApplyDebugLocation::CreateEmpty(CGF); 2066 CGF.EmitBranch(ContBlock); 2067 // Emit the continuation block for code after the if. 2068 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 2069 } 2070 2071 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 2072 llvm::Function *OutlinedFn, 2073 ArrayRef<llvm::Value *> CapturedVars, 2074 const Expr *IfCond) { 2075 if (!CGF.HaveInsertPoint()) 2076 return; 2077 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 2078 auto &M = CGM.getModule(); 2079 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc, 2080 this](CodeGenFunction &CGF, PrePostActionTy &) { 2081 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 2082 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2083 llvm::Value *Args[] = { 2084 RTLoc, 2085 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 2086 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 2087 llvm::SmallVector<llvm::Value *, 16> RealArgs; 2088 RealArgs.append(std::begin(Args), std::end(Args)); 2089 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 2090 2091 llvm::FunctionCallee RTLFn = 2092 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call); 2093 CGF.EmitRuntimeCall(RTLFn, RealArgs); 2094 }; 2095 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc, 2096 this](CodeGenFunction &CGF, PrePostActionTy &) { 2097 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2098 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 2099 // Build calls: 2100 // __kmpc_serialized_parallel(&Loc, GTid); 2101 llvm::Value *Args[] = {RTLoc, ThreadID}; 2102 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2103 M, OMPRTL___kmpc_serialized_parallel), 2104 Args); 2105 2106 // OutlinedFn(>id, &zero_bound, CapturedStruct); 2107 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 2108 Address ZeroAddrBound = 2109 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 2110 /*Name=*/".bound.zero.addr"); 2111 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 2112 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 2113 // ThreadId for serialized parallels is 0. 2114 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 2115 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 2116 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 2117 2118 // Ensure we do not inline the function. This is trivially true for the ones 2119 // passed to __kmpc_fork_call but the ones calles in serialized regions 2120 // could be inlined. This is not a perfect but it is closer to the invariant 2121 // we want, namely, every data environment starts with a new function. 2122 // TODO: We should pass the if condition to the runtime function and do the 2123 // handling there. Much cleaner code. 2124 OutlinedFn->addFnAttr(llvm::Attribute::NoInline); 2125 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 2126 2127 // __kmpc_end_serialized_parallel(&Loc, GTid); 2128 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 2129 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2130 M, OMPRTL___kmpc_end_serialized_parallel), 2131 EndArgs); 2132 }; 2133 if (IfCond) { 2134 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 2135 } else { 2136 RegionCodeGenTy ThenRCG(ThenGen); 2137 ThenRCG(CGF); 2138 } 2139 } 2140 2141 // If we're inside an (outlined) parallel region, use the region info's 2142 // thread-ID variable (it is passed in a first argument of the outlined function 2143 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 2144 // regular serial code region, get thread ID by calling kmp_int32 2145 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 2146 // return the address of that temp. 2147 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 2148 SourceLocation Loc) { 2149 if (auto *OMPRegionInfo = 2150 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2151 if (OMPRegionInfo->getThreadIDVariable()) 2152 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 2153 2154 llvm::Value *ThreadID = getThreadID(CGF, Loc); 2155 QualType Int32Ty = 2156 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 2157 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 2158 CGF.EmitStoreOfScalar(ThreadID, 2159 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 2160 2161 return ThreadIDTemp; 2162 } 2163 2164 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 2165 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 2166 SmallString<256> Buffer; 2167 llvm::raw_svector_ostream Out(Buffer); 2168 Out << Name; 2169 StringRef RuntimeName = Out.str(); 2170 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 2171 if (Elem.second) { 2172 assert(Elem.second->getType()->getPointerElementType() == Ty && 2173 "OMP internal variable has different type than requested"); 2174 return &*Elem.second; 2175 } 2176 2177 return Elem.second = new llvm::GlobalVariable( 2178 CGM.getModule(), Ty, /*IsConstant*/ false, 2179 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 2180 Elem.first(), /*InsertBefore=*/nullptr, 2181 llvm::GlobalValue::NotThreadLocal, AddressSpace); 2182 } 2183 2184 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 2185 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 2186 std::string Name = getName({Prefix, "var"}); 2187 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 2188 } 2189 2190 namespace { 2191 /// Common pre(post)-action for different OpenMP constructs. 2192 class CommonActionTy final : public PrePostActionTy { 2193 llvm::FunctionCallee EnterCallee; 2194 ArrayRef<llvm::Value *> EnterArgs; 2195 llvm::FunctionCallee ExitCallee; 2196 ArrayRef<llvm::Value *> ExitArgs; 2197 bool Conditional; 2198 llvm::BasicBlock *ContBlock = nullptr; 2199 2200 public: 2201 CommonActionTy(llvm::FunctionCallee EnterCallee, 2202 ArrayRef<llvm::Value *> EnterArgs, 2203 llvm::FunctionCallee ExitCallee, 2204 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 2205 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 2206 ExitArgs(ExitArgs), Conditional(Conditional) {} 2207 void Enter(CodeGenFunction &CGF) override { 2208 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 2209 if (Conditional) { 2210 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 2211 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2212 ContBlock = CGF.createBasicBlock("omp_if.end"); 2213 // Generate the branch (If-stmt) 2214 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 2215 CGF.EmitBlock(ThenBlock); 2216 } 2217 } 2218 void Done(CodeGenFunction &CGF) { 2219 // Emit the rest of blocks/branches 2220 CGF.EmitBranch(ContBlock); 2221 CGF.EmitBlock(ContBlock, true); 2222 } 2223 void Exit(CodeGenFunction &CGF) override { 2224 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 2225 } 2226 }; 2227 } // anonymous namespace 2228 2229 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 2230 StringRef CriticalName, 2231 const RegionCodeGenTy &CriticalOpGen, 2232 SourceLocation Loc, const Expr *Hint) { 2233 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 2234 // CriticalOpGen(); 2235 // __kmpc_end_critical(ident_t *, gtid, Lock); 2236 // Prepare arguments and build a call to __kmpc_critical 2237 if (!CGF.HaveInsertPoint()) 2238 return; 2239 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2240 getCriticalRegionLock(CriticalName)}; 2241 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 2242 std::end(Args)); 2243 if (Hint) { 2244 EnterArgs.push_back(CGF.Builder.CreateIntCast( 2245 CGF.EmitScalarExpr(Hint), CGM.Int32Ty, /*isSigned=*/false)); 2246 } 2247 CommonActionTy Action( 2248 OMPBuilder.getOrCreateRuntimeFunction( 2249 CGM.getModule(), 2250 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical), 2251 EnterArgs, 2252 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2253 OMPRTL___kmpc_end_critical), 2254 Args); 2255 CriticalOpGen.setAction(Action); 2256 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 2257 } 2258 2259 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 2260 const RegionCodeGenTy &MasterOpGen, 2261 SourceLocation Loc) { 2262 if (!CGF.HaveInsertPoint()) 2263 return; 2264 // if(__kmpc_master(ident_t *, gtid)) { 2265 // MasterOpGen(); 2266 // __kmpc_end_master(ident_t *, gtid); 2267 // } 2268 // Prepare arguments and build a call to __kmpc_master 2269 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2270 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2271 CGM.getModule(), OMPRTL___kmpc_master), 2272 Args, 2273 OMPBuilder.getOrCreateRuntimeFunction( 2274 CGM.getModule(), OMPRTL___kmpc_end_master), 2275 Args, 2276 /*Conditional=*/true); 2277 MasterOpGen.setAction(Action); 2278 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 2279 Action.Done(CGF); 2280 } 2281 2282 void CGOpenMPRuntime::emitMaskedRegion(CodeGenFunction &CGF, 2283 const RegionCodeGenTy &MaskedOpGen, 2284 SourceLocation Loc, const Expr *Filter) { 2285 if (!CGF.HaveInsertPoint()) 2286 return; 2287 // if(__kmpc_masked(ident_t *, gtid, filter)) { 2288 // MaskedOpGen(); 2289 // __kmpc_end_masked(iden_t *, gtid); 2290 // } 2291 // Prepare arguments and build a call to __kmpc_masked 2292 llvm::Value *FilterVal = Filter 2293 ? CGF.EmitScalarExpr(Filter, CGF.Int32Ty) 2294 : llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/0); 2295 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2296 FilterVal}; 2297 llvm::Value *ArgsEnd[] = {emitUpdateLocation(CGF, Loc), 2298 getThreadID(CGF, Loc)}; 2299 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2300 CGM.getModule(), OMPRTL___kmpc_masked), 2301 Args, 2302 OMPBuilder.getOrCreateRuntimeFunction( 2303 CGM.getModule(), OMPRTL___kmpc_end_masked), 2304 ArgsEnd, 2305 /*Conditional=*/true); 2306 MaskedOpGen.setAction(Action); 2307 emitInlinedDirective(CGF, OMPD_masked, MaskedOpGen); 2308 Action.Done(CGF); 2309 } 2310 2311 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 2312 SourceLocation Loc) { 2313 if (!CGF.HaveInsertPoint()) 2314 return; 2315 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2316 OMPBuilder.createTaskyield(CGF.Builder); 2317 } else { 2318 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 2319 llvm::Value *Args[] = { 2320 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2321 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 2322 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2323 CGM.getModule(), OMPRTL___kmpc_omp_taskyield), 2324 Args); 2325 } 2326 2327 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2328 Region->emitUntiedSwitch(CGF); 2329 } 2330 2331 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 2332 const RegionCodeGenTy &TaskgroupOpGen, 2333 SourceLocation Loc) { 2334 if (!CGF.HaveInsertPoint()) 2335 return; 2336 // __kmpc_taskgroup(ident_t *, gtid); 2337 // TaskgroupOpGen(); 2338 // __kmpc_end_taskgroup(ident_t *, gtid); 2339 // Prepare arguments and build a call to __kmpc_taskgroup 2340 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2341 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2342 CGM.getModule(), OMPRTL___kmpc_taskgroup), 2343 Args, 2344 OMPBuilder.getOrCreateRuntimeFunction( 2345 CGM.getModule(), OMPRTL___kmpc_end_taskgroup), 2346 Args); 2347 TaskgroupOpGen.setAction(Action); 2348 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 2349 } 2350 2351 /// Given an array of pointers to variables, project the address of a 2352 /// given variable. 2353 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 2354 unsigned Index, const VarDecl *Var) { 2355 // Pull out the pointer to the variable. 2356 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 2357 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 2358 2359 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 2360 Addr = CGF.Builder.CreateElementBitCast( 2361 Addr, CGF.ConvertTypeForMem(Var->getType())); 2362 return Addr; 2363 } 2364 2365 static llvm::Value *emitCopyprivateCopyFunction( 2366 CodeGenModule &CGM, llvm::Type *ArgsType, 2367 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 2368 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 2369 SourceLocation Loc) { 2370 ASTContext &C = CGM.getContext(); 2371 // void copy_func(void *LHSArg, void *RHSArg); 2372 FunctionArgList Args; 2373 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2374 ImplicitParamDecl::Other); 2375 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2376 ImplicitParamDecl::Other); 2377 Args.push_back(&LHSArg); 2378 Args.push_back(&RHSArg); 2379 const auto &CGFI = 2380 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2381 std::string Name = 2382 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 2383 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 2384 llvm::GlobalValue::InternalLinkage, Name, 2385 &CGM.getModule()); 2386 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 2387 Fn->setDoesNotRecurse(); 2388 CodeGenFunction CGF(CGM); 2389 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 2390 // Dest = (void*[n])(LHSArg); 2391 // Src = (void*[n])(RHSArg); 2392 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2393 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 2394 ArgsType), CGF.getPointerAlign()); 2395 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2396 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 2397 ArgsType), CGF.getPointerAlign()); 2398 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 2399 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 2400 // ... 2401 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 2402 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 2403 const auto *DestVar = 2404 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 2405 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 2406 2407 const auto *SrcVar = 2408 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 2409 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 2410 2411 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 2412 QualType Type = VD->getType(); 2413 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 2414 } 2415 CGF.FinishFunction(); 2416 return Fn; 2417 } 2418 2419 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 2420 const RegionCodeGenTy &SingleOpGen, 2421 SourceLocation Loc, 2422 ArrayRef<const Expr *> CopyprivateVars, 2423 ArrayRef<const Expr *> SrcExprs, 2424 ArrayRef<const Expr *> DstExprs, 2425 ArrayRef<const Expr *> AssignmentOps) { 2426 if (!CGF.HaveInsertPoint()) 2427 return; 2428 assert(CopyprivateVars.size() == SrcExprs.size() && 2429 CopyprivateVars.size() == DstExprs.size() && 2430 CopyprivateVars.size() == AssignmentOps.size()); 2431 ASTContext &C = CGM.getContext(); 2432 // int32 did_it = 0; 2433 // if(__kmpc_single(ident_t *, gtid)) { 2434 // SingleOpGen(); 2435 // __kmpc_end_single(ident_t *, gtid); 2436 // did_it = 1; 2437 // } 2438 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2439 // <copy_func>, did_it); 2440 2441 Address DidIt = Address::invalid(); 2442 if (!CopyprivateVars.empty()) { 2443 // int32 did_it = 0; 2444 QualType KmpInt32Ty = 2445 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2446 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 2447 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 2448 } 2449 // Prepare arguments and build a call to __kmpc_single 2450 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2451 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2452 CGM.getModule(), OMPRTL___kmpc_single), 2453 Args, 2454 OMPBuilder.getOrCreateRuntimeFunction( 2455 CGM.getModule(), OMPRTL___kmpc_end_single), 2456 Args, 2457 /*Conditional=*/true); 2458 SingleOpGen.setAction(Action); 2459 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 2460 if (DidIt.isValid()) { 2461 // did_it = 1; 2462 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 2463 } 2464 Action.Done(CGF); 2465 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2466 // <copy_func>, did_it); 2467 if (DidIt.isValid()) { 2468 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 2469 QualType CopyprivateArrayTy = C.getConstantArrayType( 2470 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 2471 /*IndexTypeQuals=*/0); 2472 // Create a list of all private variables for copyprivate. 2473 Address CopyprivateList = 2474 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 2475 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 2476 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 2477 CGF.Builder.CreateStore( 2478 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2479 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 2480 CGF.VoidPtrTy), 2481 Elem); 2482 } 2483 // Build function that copies private values from single region to all other 2484 // threads in the corresponding parallel region. 2485 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 2486 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 2487 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 2488 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 2489 Address CL = 2490 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 2491 CGF.VoidPtrTy); 2492 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 2493 llvm::Value *Args[] = { 2494 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 2495 getThreadID(CGF, Loc), // i32 <gtid> 2496 BufSize, // size_t <buf_size> 2497 CL.getPointer(), // void *<copyprivate list> 2498 CpyFn, // void (*) (void *, void *) <copy_func> 2499 DidItVal // i32 did_it 2500 }; 2501 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2502 CGM.getModule(), OMPRTL___kmpc_copyprivate), 2503 Args); 2504 } 2505 } 2506 2507 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 2508 const RegionCodeGenTy &OrderedOpGen, 2509 SourceLocation Loc, bool IsThreads) { 2510 if (!CGF.HaveInsertPoint()) 2511 return; 2512 // __kmpc_ordered(ident_t *, gtid); 2513 // OrderedOpGen(); 2514 // __kmpc_end_ordered(ident_t *, gtid); 2515 // Prepare arguments and build a call to __kmpc_ordered 2516 if (IsThreads) { 2517 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2518 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2519 CGM.getModule(), OMPRTL___kmpc_ordered), 2520 Args, 2521 OMPBuilder.getOrCreateRuntimeFunction( 2522 CGM.getModule(), OMPRTL___kmpc_end_ordered), 2523 Args); 2524 OrderedOpGen.setAction(Action); 2525 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2526 return; 2527 } 2528 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2529 } 2530 2531 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 2532 unsigned Flags; 2533 if (Kind == OMPD_for) 2534 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 2535 else if (Kind == OMPD_sections) 2536 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 2537 else if (Kind == OMPD_single) 2538 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 2539 else if (Kind == OMPD_barrier) 2540 Flags = OMP_IDENT_BARRIER_EXPL; 2541 else 2542 Flags = OMP_IDENT_BARRIER_IMPL; 2543 return Flags; 2544 } 2545 2546 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 2547 CodeGenFunction &CGF, const OMPLoopDirective &S, 2548 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 2549 // Check if the loop directive is actually a doacross loop directive. In this 2550 // case choose static, 1 schedule. 2551 if (llvm::any_of( 2552 S.getClausesOfKind<OMPOrderedClause>(), 2553 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 2554 ScheduleKind = OMPC_SCHEDULE_static; 2555 // Chunk size is 1 in this case. 2556 llvm::APInt ChunkSize(32, 1); 2557 ChunkExpr = IntegerLiteral::Create( 2558 CGF.getContext(), ChunkSize, 2559 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 2560 SourceLocation()); 2561 } 2562 } 2563 2564 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 2565 OpenMPDirectiveKind Kind, bool EmitChecks, 2566 bool ForceSimpleCall) { 2567 // Check if we should use the OMPBuilder 2568 auto *OMPRegionInfo = 2569 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 2570 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2571 CGF.Builder.restoreIP(OMPBuilder.createBarrier( 2572 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 2573 return; 2574 } 2575 2576 if (!CGF.HaveInsertPoint()) 2577 return; 2578 // Build call __kmpc_cancel_barrier(loc, thread_id); 2579 // Build call __kmpc_barrier(loc, thread_id); 2580 unsigned Flags = getDefaultFlagsForBarriers(Kind); 2581 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 2582 // thread_id); 2583 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 2584 getThreadID(CGF, Loc)}; 2585 if (OMPRegionInfo) { 2586 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 2587 llvm::Value *Result = CGF.EmitRuntimeCall( 2588 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2589 OMPRTL___kmpc_cancel_barrier), 2590 Args); 2591 if (EmitChecks) { 2592 // if (__kmpc_cancel_barrier()) { 2593 // exit from construct; 2594 // } 2595 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2596 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 2597 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 2598 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2599 CGF.EmitBlock(ExitBB); 2600 // exit from construct; 2601 CodeGenFunction::JumpDest CancelDestination = 2602 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2603 CGF.EmitBranchThroughCleanup(CancelDestination); 2604 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2605 } 2606 return; 2607 } 2608 } 2609 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2610 CGM.getModule(), OMPRTL___kmpc_barrier), 2611 Args); 2612 } 2613 2614 /// Map the OpenMP loop schedule to the runtime enumeration. 2615 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 2616 bool Chunked, bool Ordered) { 2617 switch (ScheduleKind) { 2618 case OMPC_SCHEDULE_static: 2619 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 2620 : (Ordered ? OMP_ord_static : OMP_sch_static); 2621 case OMPC_SCHEDULE_dynamic: 2622 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 2623 case OMPC_SCHEDULE_guided: 2624 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 2625 case OMPC_SCHEDULE_runtime: 2626 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 2627 case OMPC_SCHEDULE_auto: 2628 return Ordered ? OMP_ord_auto : OMP_sch_auto; 2629 case OMPC_SCHEDULE_unknown: 2630 assert(!Chunked && "chunk was specified but schedule kind not known"); 2631 return Ordered ? OMP_ord_static : OMP_sch_static; 2632 } 2633 llvm_unreachable("Unexpected runtime schedule"); 2634 } 2635 2636 /// Map the OpenMP distribute schedule to the runtime enumeration. 2637 static OpenMPSchedType 2638 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 2639 // only static is allowed for dist_schedule 2640 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 2641 } 2642 2643 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 2644 bool Chunked) const { 2645 OpenMPSchedType Schedule = 2646 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2647 return Schedule == OMP_sch_static; 2648 } 2649 2650 bool CGOpenMPRuntime::isStaticNonchunked( 2651 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2652 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2653 return Schedule == OMP_dist_sch_static; 2654 } 2655 2656 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 2657 bool Chunked) const { 2658 OpenMPSchedType Schedule = 2659 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2660 return Schedule == OMP_sch_static_chunked; 2661 } 2662 2663 bool CGOpenMPRuntime::isStaticChunked( 2664 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2665 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2666 return Schedule == OMP_dist_sch_static_chunked; 2667 } 2668 2669 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 2670 OpenMPSchedType Schedule = 2671 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 2672 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 2673 return Schedule != OMP_sch_static; 2674 } 2675 2676 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 2677 OpenMPScheduleClauseModifier M1, 2678 OpenMPScheduleClauseModifier M2) { 2679 int Modifier = 0; 2680 switch (M1) { 2681 case OMPC_SCHEDULE_MODIFIER_monotonic: 2682 Modifier = OMP_sch_modifier_monotonic; 2683 break; 2684 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2685 Modifier = OMP_sch_modifier_nonmonotonic; 2686 break; 2687 case OMPC_SCHEDULE_MODIFIER_simd: 2688 if (Schedule == OMP_sch_static_chunked) 2689 Schedule = OMP_sch_static_balanced_chunked; 2690 break; 2691 case OMPC_SCHEDULE_MODIFIER_last: 2692 case OMPC_SCHEDULE_MODIFIER_unknown: 2693 break; 2694 } 2695 switch (M2) { 2696 case OMPC_SCHEDULE_MODIFIER_monotonic: 2697 Modifier = OMP_sch_modifier_monotonic; 2698 break; 2699 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2700 Modifier = OMP_sch_modifier_nonmonotonic; 2701 break; 2702 case OMPC_SCHEDULE_MODIFIER_simd: 2703 if (Schedule == OMP_sch_static_chunked) 2704 Schedule = OMP_sch_static_balanced_chunked; 2705 break; 2706 case OMPC_SCHEDULE_MODIFIER_last: 2707 case OMPC_SCHEDULE_MODIFIER_unknown: 2708 break; 2709 } 2710 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 2711 // If the static schedule kind is specified or if the ordered clause is 2712 // specified, and if the nonmonotonic modifier is not specified, the effect is 2713 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 2714 // modifier is specified, the effect is as if the nonmonotonic modifier is 2715 // specified. 2716 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 2717 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 2718 Schedule == OMP_sch_static_balanced_chunked || 2719 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 2720 Schedule == OMP_dist_sch_static_chunked || 2721 Schedule == OMP_dist_sch_static)) 2722 Modifier = OMP_sch_modifier_nonmonotonic; 2723 } 2724 return Schedule | Modifier; 2725 } 2726 2727 void CGOpenMPRuntime::emitForDispatchInit( 2728 CodeGenFunction &CGF, SourceLocation Loc, 2729 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 2730 bool Ordered, const DispatchRTInput &DispatchValues) { 2731 if (!CGF.HaveInsertPoint()) 2732 return; 2733 OpenMPSchedType Schedule = getRuntimeSchedule( 2734 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 2735 assert(Ordered || 2736 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 2737 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 2738 Schedule != OMP_sch_static_balanced_chunked)); 2739 // Call __kmpc_dispatch_init( 2740 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 2741 // kmp_int[32|64] lower, kmp_int[32|64] upper, 2742 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 2743 2744 // If the Chunk was not specified in the clause - use default value 1. 2745 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 2746 : CGF.Builder.getIntN(IVSize, 1); 2747 llvm::Value *Args[] = { 2748 emitUpdateLocation(CGF, Loc), 2749 getThreadID(CGF, Loc), 2750 CGF.Builder.getInt32(addMonoNonMonoModifier( 2751 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 2752 DispatchValues.LB, // Lower 2753 DispatchValues.UB, // Upper 2754 CGF.Builder.getIntN(IVSize, 1), // Stride 2755 Chunk // Chunk 2756 }; 2757 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 2758 } 2759 2760 static void emitForStaticInitCall( 2761 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 2762 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 2763 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 2764 const CGOpenMPRuntime::StaticRTInput &Values) { 2765 if (!CGF.HaveInsertPoint()) 2766 return; 2767 2768 assert(!Values.Ordered); 2769 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 2770 Schedule == OMP_sch_static_balanced_chunked || 2771 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 2772 Schedule == OMP_dist_sch_static || 2773 Schedule == OMP_dist_sch_static_chunked); 2774 2775 // Call __kmpc_for_static_init( 2776 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 2777 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 2778 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 2779 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 2780 llvm::Value *Chunk = Values.Chunk; 2781 if (Chunk == nullptr) { 2782 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 2783 Schedule == OMP_dist_sch_static) && 2784 "expected static non-chunked schedule"); 2785 // If the Chunk was not specified in the clause - use default value 1. 2786 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 2787 } else { 2788 assert((Schedule == OMP_sch_static_chunked || 2789 Schedule == OMP_sch_static_balanced_chunked || 2790 Schedule == OMP_ord_static_chunked || 2791 Schedule == OMP_dist_sch_static_chunked) && 2792 "expected static chunked schedule"); 2793 } 2794 llvm::Value *Args[] = { 2795 UpdateLocation, 2796 ThreadId, 2797 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 2798 M2)), // Schedule type 2799 Values.IL.getPointer(), // &isLastIter 2800 Values.LB.getPointer(), // &LB 2801 Values.UB.getPointer(), // &UB 2802 Values.ST.getPointer(), // &Stride 2803 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 2804 Chunk // Chunk 2805 }; 2806 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 2807 } 2808 2809 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 2810 SourceLocation Loc, 2811 OpenMPDirectiveKind DKind, 2812 const OpenMPScheduleTy &ScheduleKind, 2813 const StaticRTInput &Values) { 2814 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 2815 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 2816 assert(isOpenMPWorksharingDirective(DKind) && 2817 "Expected loop-based or sections-based directive."); 2818 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 2819 isOpenMPLoopDirective(DKind) 2820 ? OMP_IDENT_WORK_LOOP 2821 : OMP_IDENT_WORK_SECTIONS); 2822 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2823 llvm::FunctionCallee StaticInitFunction = 2824 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 2825 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2826 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2827 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 2828 } 2829 2830 void CGOpenMPRuntime::emitDistributeStaticInit( 2831 CodeGenFunction &CGF, SourceLocation Loc, 2832 OpenMPDistScheduleClauseKind SchedKind, 2833 const CGOpenMPRuntime::StaticRTInput &Values) { 2834 OpenMPSchedType ScheduleNum = 2835 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 2836 llvm::Value *UpdatedLocation = 2837 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 2838 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2839 llvm::FunctionCallee StaticInitFunction = 2840 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 2841 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2842 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 2843 OMPC_SCHEDULE_MODIFIER_unknown, Values); 2844 } 2845 2846 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 2847 SourceLocation Loc, 2848 OpenMPDirectiveKind DKind) { 2849 if (!CGF.HaveInsertPoint()) 2850 return; 2851 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 2852 llvm::Value *Args[] = { 2853 emitUpdateLocation(CGF, Loc, 2854 isOpenMPDistributeDirective(DKind) 2855 ? OMP_IDENT_WORK_DISTRIBUTE 2856 : isOpenMPLoopDirective(DKind) 2857 ? OMP_IDENT_WORK_LOOP 2858 : OMP_IDENT_WORK_SECTIONS), 2859 getThreadID(CGF, Loc)}; 2860 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2861 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2862 CGM.getModule(), OMPRTL___kmpc_for_static_fini), 2863 Args); 2864 } 2865 2866 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 2867 SourceLocation Loc, 2868 unsigned IVSize, 2869 bool IVSigned) { 2870 if (!CGF.HaveInsertPoint()) 2871 return; 2872 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 2873 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2874 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 2875 } 2876 2877 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 2878 SourceLocation Loc, unsigned IVSize, 2879 bool IVSigned, Address IL, 2880 Address LB, Address UB, 2881 Address ST) { 2882 // Call __kmpc_dispatch_next( 2883 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 2884 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 2885 // kmp_int[32|64] *p_stride); 2886 llvm::Value *Args[] = { 2887 emitUpdateLocation(CGF, Loc), 2888 getThreadID(CGF, Loc), 2889 IL.getPointer(), // &isLastIter 2890 LB.getPointer(), // &Lower 2891 UB.getPointer(), // &Upper 2892 ST.getPointer() // &Stride 2893 }; 2894 llvm::Value *Call = 2895 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 2896 return CGF.EmitScalarConversion( 2897 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 2898 CGF.getContext().BoolTy, Loc); 2899 } 2900 2901 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 2902 llvm::Value *NumThreads, 2903 SourceLocation Loc) { 2904 if (!CGF.HaveInsertPoint()) 2905 return; 2906 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 2907 llvm::Value *Args[] = { 2908 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2909 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 2910 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2911 CGM.getModule(), OMPRTL___kmpc_push_num_threads), 2912 Args); 2913 } 2914 2915 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 2916 ProcBindKind ProcBind, 2917 SourceLocation Loc) { 2918 if (!CGF.HaveInsertPoint()) 2919 return; 2920 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 2921 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 2922 llvm::Value *Args[] = { 2923 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2924 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 2925 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2926 CGM.getModule(), OMPRTL___kmpc_push_proc_bind), 2927 Args); 2928 } 2929 2930 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 2931 SourceLocation Loc, llvm::AtomicOrdering AO) { 2932 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2933 OMPBuilder.createFlush(CGF.Builder); 2934 } else { 2935 if (!CGF.HaveInsertPoint()) 2936 return; 2937 // Build call void __kmpc_flush(ident_t *loc) 2938 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2939 CGM.getModule(), OMPRTL___kmpc_flush), 2940 emitUpdateLocation(CGF, Loc)); 2941 } 2942 } 2943 2944 namespace { 2945 /// Indexes of fields for type kmp_task_t. 2946 enum KmpTaskTFields { 2947 /// List of shared variables. 2948 KmpTaskTShareds, 2949 /// Task routine. 2950 KmpTaskTRoutine, 2951 /// Partition id for the untied tasks. 2952 KmpTaskTPartId, 2953 /// Function with call of destructors for private variables. 2954 Data1, 2955 /// Task priority. 2956 Data2, 2957 /// (Taskloops only) Lower bound. 2958 KmpTaskTLowerBound, 2959 /// (Taskloops only) Upper bound. 2960 KmpTaskTUpperBound, 2961 /// (Taskloops only) Stride. 2962 KmpTaskTStride, 2963 /// (Taskloops only) Is last iteration flag. 2964 KmpTaskTLastIter, 2965 /// (Taskloops only) Reduction data. 2966 KmpTaskTReductions, 2967 }; 2968 } // anonymous namespace 2969 2970 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 2971 return OffloadEntriesTargetRegion.empty() && 2972 OffloadEntriesDeviceGlobalVar.empty(); 2973 } 2974 2975 /// Initialize target region entry. 2976 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2977 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2978 StringRef ParentName, unsigned LineNum, 2979 unsigned Order) { 2980 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 2981 "only required for the device " 2982 "code generation."); 2983 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 2984 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 2985 OMPTargetRegionEntryTargetRegion); 2986 ++OffloadingEntriesNum; 2987 } 2988 2989 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2990 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2991 StringRef ParentName, unsigned LineNum, 2992 llvm::Constant *Addr, llvm::Constant *ID, 2993 OMPTargetRegionEntryKind Flags) { 2994 // If we are emitting code for a target, the entry is already initialized, 2995 // only has to be registered. 2996 if (CGM.getLangOpts().OpenMPIsDevice) { 2997 // This could happen if the device compilation is invoked standalone. 2998 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) 2999 return; 3000 auto &Entry = 3001 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3002 Entry.setAddress(Addr); 3003 Entry.setID(ID); 3004 Entry.setFlags(Flags); 3005 } else { 3006 if (Flags == 3007 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion && 3008 hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum, 3009 /*IgnoreAddressId*/ true)) 3010 return; 3011 assert(!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) && 3012 "Target region entry already registered!"); 3013 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3014 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3015 ++OffloadingEntriesNum; 3016 } 3017 } 3018 3019 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3020 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum, 3021 bool IgnoreAddressId) const { 3022 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3023 if (PerDevice == OffloadEntriesTargetRegion.end()) 3024 return false; 3025 auto PerFile = PerDevice->second.find(FileID); 3026 if (PerFile == PerDevice->second.end()) 3027 return false; 3028 auto PerParentName = PerFile->second.find(ParentName); 3029 if (PerParentName == PerFile->second.end()) 3030 return false; 3031 auto PerLine = PerParentName->second.find(LineNum); 3032 if (PerLine == PerParentName->second.end()) 3033 return false; 3034 // Fail if this entry is already registered. 3035 if (!IgnoreAddressId && 3036 (PerLine->second.getAddress() || PerLine->second.getID())) 3037 return false; 3038 return true; 3039 } 3040 3041 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3042 const OffloadTargetRegionEntryInfoActTy &Action) { 3043 // Scan all target region entries and perform the provided action. 3044 for (const auto &D : OffloadEntriesTargetRegion) 3045 for (const auto &F : D.second) 3046 for (const auto &P : F.second) 3047 for (const auto &L : P.second) 3048 Action(D.first, F.first, P.first(), L.first, L.second); 3049 } 3050 3051 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3052 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3053 OMPTargetGlobalVarEntryKind Flags, 3054 unsigned Order) { 3055 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3056 "only required for the device " 3057 "code generation."); 3058 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3059 ++OffloadingEntriesNum; 3060 } 3061 3062 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3063 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3064 CharUnits VarSize, 3065 OMPTargetGlobalVarEntryKind Flags, 3066 llvm::GlobalValue::LinkageTypes Linkage) { 3067 if (CGM.getLangOpts().OpenMPIsDevice) { 3068 // This could happen if the device compilation is invoked standalone. 3069 if (!hasDeviceGlobalVarEntryInfo(VarName)) 3070 return; 3071 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3072 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3073 if (Entry.getVarSize().isZero()) { 3074 Entry.setVarSize(VarSize); 3075 Entry.setLinkage(Linkage); 3076 } 3077 return; 3078 } 3079 Entry.setVarSize(VarSize); 3080 Entry.setLinkage(Linkage); 3081 Entry.setAddress(Addr); 3082 } else { 3083 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3084 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3085 assert(Entry.isValid() && Entry.getFlags() == Flags && 3086 "Entry not initialized!"); 3087 if (Entry.getVarSize().isZero()) { 3088 Entry.setVarSize(VarSize); 3089 Entry.setLinkage(Linkage); 3090 } 3091 return; 3092 } 3093 OffloadEntriesDeviceGlobalVar.try_emplace( 3094 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3095 ++OffloadingEntriesNum; 3096 } 3097 } 3098 3099 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3100 actOnDeviceGlobalVarEntriesInfo( 3101 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 3102 // Scan all target region entries and perform the provided action. 3103 for (const auto &E : OffloadEntriesDeviceGlobalVar) 3104 Action(E.getKey(), E.getValue()); 3105 } 3106 3107 void CGOpenMPRuntime::createOffloadEntry( 3108 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 3109 llvm::GlobalValue::LinkageTypes Linkage) { 3110 StringRef Name = Addr->getName(); 3111 llvm::Module &M = CGM.getModule(); 3112 llvm::LLVMContext &C = M.getContext(); 3113 3114 // Create constant string with the name. 3115 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 3116 3117 std::string StringName = getName({"omp_offloading", "entry_name"}); 3118 auto *Str = new llvm::GlobalVariable( 3119 M, StrPtrInit->getType(), /*isConstant=*/true, 3120 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 3121 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 3122 3123 llvm::Constant *Data[] = { 3124 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(ID, CGM.VoidPtrTy), 3125 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, CGM.Int8PtrTy), 3126 llvm::ConstantInt::get(CGM.SizeTy, Size), 3127 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 3128 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 3129 std::string EntryName = getName({"omp_offloading", "entry", ""}); 3130 llvm::GlobalVariable *Entry = createGlobalStruct( 3131 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 3132 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 3133 3134 // The entry has to be created in the section the linker expects it to be. 3135 Entry->setSection("omp_offloading_entries"); 3136 } 3137 3138 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 3139 // Emit the offloading entries and metadata so that the device codegen side 3140 // can easily figure out what to emit. The produced metadata looks like 3141 // this: 3142 // 3143 // !omp_offload.info = !{!1, ...} 3144 // 3145 // Right now we only generate metadata for function that contain target 3146 // regions. 3147 3148 // If we are in simd mode or there are no entries, we don't need to do 3149 // anything. 3150 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 3151 return; 3152 3153 llvm::Module &M = CGM.getModule(); 3154 llvm::LLVMContext &C = M.getContext(); 3155 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 3156 SourceLocation, StringRef>, 3157 16> 3158 OrderedEntries(OffloadEntriesInfoManager.size()); 3159 llvm::SmallVector<StringRef, 16> ParentFunctions( 3160 OffloadEntriesInfoManager.size()); 3161 3162 // Auxiliary methods to create metadata values and strings. 3163 auto &&GetMDInt = [this](unsigned V) { 3164 return llvm::ConstantAsMetadata::get( 3165 llvm::ConstantInt::get(CGM.Int32Ty, V)); 3166 }; 3167 3168 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 3169 3170 // Create the offloading info metadata node. 3171 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 3172 3173 // Create function that emits metadata for each target region entry; 3174 auto &&TargetRegionMetadataEmitter = 3175 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 3176 &GetMDString]( 3177 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3178 unsigned Line, 3179 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 3180 // Generate metadata for target regions. Each entry of this metadata 3181 // contains: 3182 // - Entry 0 -> Kind of this type of metadata (0). 3183 // - Entry 1 -> Device ID of the file where the entry was identified. 3184 // - Entry 2 -> File ID of the file where the entry was identified. 3185 // - Entry 3 -> Mangled name of the function where the entry was 3186 // identified. 3187 // - Entry 4 -> Line in the file where the entry was identified. 3188 // - Entry 5 -> Order the entry was created. 3189 // The first element of the metadata node is the kind. 3190 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 3191 GetMDInt(FileID), GetMDString(ParentName), 3192 GetMDInt(Line), GetMDInt(E.getOrder())}; 3193 3194 SourceLocation Loc; 3195 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 3196 E = CGM.getContext().getSourceManager().fileinfo_end(); 3197 I != E; ++I) { 3198 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 3199 I->getFirst()->getUniqueID().getFile() == FileID) { 3200 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 3201 I->getFirst(), Line, 1); 3202 break; 3203 } 3204 } 3205 // Save this entry in the right position of the ordered entries array. 3206 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 3207 ParentFunctions[E.getOrder()] = ParentName; 3208 3209 // Add metadata to the named metadata node. 3210 MD->addOperand(llvm::MDNode::get(C, Ops)); 3211 }; 3212 3213 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 3214 TargetRegionMetadataEmitter); 3215 3216 // Create function that emits metadata for each device global variable entry; 3217 auto &&DeviceGlobalVarMetadataEmitter = 3218 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 3219 MD](StringRef MangledName, 3220 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 3221 &E) { 3222 // Generate metadata for global variables. Each entry of this metadata 3223 // contains: 3224 // - Entry 0 -> Kind of this type of metadata (1). 3225 // - Entry 1 -> Mangled name of the variable. 3226 // - Entry 2 -> Declare target kind. 3227 // - Entry 3 -> Order the entry was created. 3228 // The first element of the metadata node is the kind. 3229 llvm::Metadata *Ops[] = { 3230 GetMDInt(E.getKind()), GetMDString(MangledName), 3231 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 3232 3233 // Save this entry in the right position of the ordered entries array. 3234 OrderedEntries[E.getOrder()] = 3235 std::make_tuple(&E, SourceLocation(), MangledName); 3236 3237 // Add metadata to the named metadata node. 3238 MD->addOperand(llvm::MDNode::get(C, Ops)); 3239 }; 3240 3241 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 3242 DeviceGlobalVarMetadataEmitter); 3243 3244 for (const auto &E : OrderedEntries) { 3245 assert(std::get<0>(E) && "All ordered entries must exist!"); 3246 if (const auto *CE = 3247 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 3248 std::get<0>(E))) { 3249 if (!CE->getID() || !CE->getAddress()) { 3250 // Do not blame the entry if the parent funtion is not emitted. 3251 StringRef FnName = ParentFunctions[CE->getOrder()]; 3252 if (!CGM.GetGlobalValue(FnName)) 3253 continue; 3254 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3255 DiagnosticsEngine::Error, 3256 "Offloading entry for target region in %0 is incorrect: either the " 3257 "address or the ID is invalid."); 3258 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 3259 continue; 3260 } 3261 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 3262 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 3263 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 3264 OffloadEntryInfoDeviceGlobalVar>( 3265 std::get<0>(E))) { 3266 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 3267 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3268 CE->getFlags()); 3269 switch (Flags) { 3270 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 3271 if (CGM.getLangOpts().OpenMPIsDevice && 3272 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 3273 continue; 3274 if (!CE->getAddress()) { 3275 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3276 DiagnosticsEngine::Error, "Offloading entry for declare target " 3277 "variable %0 is incorrect: the " 3278 "address is invalid."); 3279 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 3280 continue; 3281 } 3282 // The vaiable has no definition - no need to add the entry. 3283 if (CE->getVarSize().isZero()) 3284 continue; 3285 break; 3286 } 3287 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 3288 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 3289 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 3290 "Declaret target link address is set."); 3291 if (CGM.getLangOpts().OpenMPIsDevice) 3292 continue; 3293 if (!CE->getAddress()) { 3294 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3295 DiagnosticsEngine::Error, 3296 "Offloading entry for declare target variable is incorrect: the " 3297 "address is invalid."); 3298 CGM.getDiags().Report(DiagID); 3299 continue; 3300 } 3301 break; 3302 } 3303 createOffloadEntry(CE->getAddress(), CE->getAddress(), 3304 CE->getVarSize().getQuantity(), Flags, 3305 CE->getLinkage()); 3306 } else { 3307 llvm_unreachable("Unsupported entry kind."); 3308 } 3309 } 3310 } 3311 3312 /// Loads all the offload entries information from the host IR 3313 /// metadata. 3314 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 3315 // If we are in target mode, load the metadata from the host IR. This code has 3316 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 3317 3318 if (!CGM.getLangOpts().OpenMPIsDevice) 3319 return; 3320 3321 if (CGM.getLangOpts().OMPHostIRFile.empty()) 3322 return; 3323 3324 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 3325 if (auto EC = Buf.getError()) { 3326 CGM.getDiags().Report(diag::err_cannot_open_file) 3327 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3328 return; 3329 } 3330 3331 llvm::LLVMContext C; 3332 auto ME = expectedToErrorOrAndEmitErrors( 3333 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 3334 3335 if (auto EC = ME.getError()) { 3336 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3337 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 3338 CGM.getDiags().Report(DiagID) 3339 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3340 return; 3341 } 3342 3343 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 3344 if (!MD) 3345 return; 3346 3347 for (llvm::MDNode *MN : MD->operands()) { 3348 auto &&GetMDInt = [MN](unsigned Idx) { 3349 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 3350 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 3351 }; 3352 3353 auto &&GetMDString = [MN](unsigned Idx) { 3354 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 3355 return V->getString(); 3356 }; 3357 3358 switch (GetMDInt(0)) { 3359 default: 3360 llvm_unreachable("Unexpected metadata!"); 3361 break; 3362 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3363 OffloadingEntryInfoTargetRegion: 3364 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 3365 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 3366 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 3367 /*Order=*/GetMDInt(5)); 3368 break; 3369 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3370 OffloadingEntryInfoDeviceGlobalVar: 3371 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 3372 /*MangledName=*/GetMDString(1), 3373 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3374 /*Flags=*/GetMDInt(2)), 3375 /*Order=*/GetMDInt(3)); 3376 break; 3377 } 3378 } 3379 } 3380 3381 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 3382 if (!KmpRoutineEntryPtrTy) { 3383 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 3384 ASTContext &C = CGM.getContext(); 3385 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 3386 FunctionProtoType::ExtProtoInfo EPI; 3387 KmpRoutineEntryPtrQTy = C.getPointerType( 3388 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 3389 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 3390 } 3391 } 3392 3393 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 3394 // Make sure the type of the entry is already created. This is the type we 3395 // have to create: 3396 // struct __tgt_offload_entry{ 3397 // void *addr; // Pointer to the offload entry info. 3398 // // (function or global) 3399 // char *name; // Name of the function or global. 3400 // size_t size; // Size of the entry info (0 if it a function). 3401 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 3402 // int32_t reserved; // Reserved, to use by the runtime library. 3403 // }; 3404 if (TgtOffloadEntryQTy.isNull()) { 3405 ASTContext &C = CGM.getContext(); 3406 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 3407 RD->startDefinition(); 3408 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3409 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 3410 addFieldToRecordDecl(C, RD, C.getSizeType()); 3411 addFieldToRecordDecl( 3412 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3413 addFieldToRecordDecl( 3414 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3415 RD->completeDefinition(); 3416 RD->addAttr(PackedAttr::CreateImplicit(C)); 3417 TgtOffloadEntryQTy = C.getRecordType(RD); 3418 } 3419 return TgtOffloadEntryQTy; 3420 } 3421 3422 namespace { 3423 struct PrivateHelpersTy { 3424 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original, 3425 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit) 3426 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy), 3427 PrivateElemInit(PrivateElemInit) {} 3428 PrivateHelpersTy(const VarDecl *Original) : Original(Original) {} 3429 const Expr *OriginalRef = nullptr; 3430 const VarDecl *Original = nullptr; 3431 const VarDecl *PrivateCopy = nullptr; 3432 const VarDecl *PrivateElemInit = nullptr; 3433 bool isLocalPrivate() const { 3434 return !OriginalRef && !PrivateCopy && !PrivateElemInit; 3435 } 3436 }; 3437 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 3438 } // anonymous namespace 3439 3440 static bool isAllocatableDecl(const VarDecl *VD) { 3441 const VarDecl *CVD = VD->getCanonicalDecl(); 3442 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 3443 return false; 3444 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 3445 // Use the default allocation. 3446 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc || 3447 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) && 3448 !AA->getAllocator()); 3449 } 3450 3451 static RecordDecl * 3452 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 3453 if (!Privates.empty()) { 3454 ASTContext &C = CGM.getContext(); 3455 // Build struct .kmp_privates_t. { 3456 // /* private vars */ 3457 // }; 3458 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 3459 RD->startDefinition(); 3460 for (const auto &Pair : Privates) { 3461 const VarDecl *VD = Pair.second.Original; 3462 QualType Type = VD->getType().getNonReferenceType(); 3463 // If the private variable is a local variable with lvalue ref type, 3464 // allocate the pointer instead of the pointee type. 3465 if (Pair.second.isLocalPrivate()) { 3466 if (VD->getType()->isLValueReferenceType()) 3467 Type = C.getPointerType(Type); 3468 if (isAllocatableDecl(VD)) 3469 Type = C.getPointerType(Type); 3470 } 3471 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 3472 if (VD->hasAttrs()) { 3473 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 3474 E(VD->getAttrs().end()); 3475 I != E; ++I) 3476 FD->addAttr(*I); 3477 } 3478 } 3479 RD->completeDefinition(); 3480 return RD; 3481 } 3482 return nullptr; 3483 } 3484 3485 static RecordDecl * 3486 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 3487 QualType KmpInt32Ty, 3488 QualType KmpRoutineEntryPointerQTy) { 3489 ASTContext &C = CGM.getContext(); 3490 // Build struct kmp_task_t { 3491 // void * shareds; 3492 // kmp_routine_entry_t routine; 3493 // kmp_int32 part_id; 3494 // kmp_cmplrdata_t data1; 3495 // kmp_cmplrdata_t data2; 3496 // For taskloops additional fields: 3497 // kmp_uint64 lb; 3498 // kmp_uint64 ub; 3499 // kmp_int64 st; 3500 // kmp_int32 liter; 3501 // void * reductions; 3502 // }; 3503 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 3504 UD->startDefinition(); 3505 addFieldToRecordDecl(C, UD, KmpInt32Ty); 3506 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 3507 UD->completeDefinition(); 3508 QualType KmpCmplrdataTy = C.getRecordType(UD); 3509 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 3510 RD->startDefinition(); 3511 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3512 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 3513 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3514 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3515 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3516 if (isOpenMPTaskLoopDirective(Kind)) { 3517 QualType KmpUInt64Ty = 3518 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 3519 QualType KmpInt64Ty = 3520 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 3521 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3522 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3523 addFieldToRecordDecl(C, RD, KmpInt64Ty); 3524 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3525 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3526 } 3527 RD->completeDefinition(); 3528 return RD; 3529 } 3530 3531 static RecordDecl * 3532 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 3533 ArrayRef<PrivateDataTy> Privates) { 3534 ASTContext &C = CGM.getContext(); 3535 // Build struct kmp_task_t_with_privates { 3536 // kmp_task_t task_data; 3537 // .kmp_privates_t. privates; 3538 // }; 3539 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 3540 RD->startDefinition(); 3541 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 3542 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 3543 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 3544 RD->completeDefinition(); 3545 return RD; 3546 } 3547 3548 /// Emit a proxy function which accepts kmp_task_t as the second 3549 /// argument. 3550 /// \code 3551 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 3552 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 3553 /// For taskloops: 3554 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3555 /// tt->reductions, tt->shareds); 3556 /// return 0; 3557 /// } 3558 /// \endcode 3559 static llvm::Function * 3560 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 3561 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 3562 QualType KmpTaskTWithPrivatesPtrQTy, 3563 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 3564 QualType SharedsPtrTy, llvm::Function *TaskFunction, 3565 llvm::Value *TaskPrivatesMap) { 3566 ASTContext &C = CGM.getContext(); 3567 FunctionArgList Args; 3568 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3569 ImplicitParamDecl::Other); 3570 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3571 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3572 ImplicitParamDecl::Other); 3573 Args.push_back(&GtidArg); 3574 Args.push_back(&TaskTypeArg); 3575 const auto &TaskEntryFnInfo = 3576 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3577 llvm::FunctionType *TaskEntryTy = 3578 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 3579 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 3580 auto *TaskEntry = llvm::Function::Create( 3581 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3582 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 3583 TaskEntry->setDoesNotRecurse(); 3584 CodeGenFunction CGF(CGM); 3585 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 3586 Loc, Loc); 3587 3588 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 3589 // tt, 3590 // For taskloops: 3591 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3592 // tt->task_data.shareds); 3593 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 3594 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 3595 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3596 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3597 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3598 const auto *KmpTaskTWithPrivatesQTyRD = 3599 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3600 LValue Base = 3601 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3602 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3603 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 3604 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 3605 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 3606 3607 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 3608 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 3609 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3610 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 3611 CGF.ConvertTypeForMem(SharedsPtrTy)); 3612 3613 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 3614 llvm::Value *PrivatesParam; 3615 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 3616 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 3617 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3618 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 3619 } else { 3620 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3621 } 3622 3623 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 3624 TaskPrivatesMap, 3625 CGF.Builder 3626 .CreatePointerBitCastOrAddrSpaceCast( 3627 TDBase.getAddress(CGF), CGF.VoidPtrTy) 3628 .getPointer()}; 3629 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 3630 std::end(CommonArgs)); 3631 if (isOpenMPTaskLoopDirective(Kind)) { 3632 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 3633 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 3634 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 3635 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 3636 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 3637 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 3638 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 3639 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 3640 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 3641 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3642 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3643 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 3644 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 3645 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 3646 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 3647 CallArgs.push_back(LBParam); 3648 CallArgs.push_back(UBParam); 3649 CallArgs.push_back(StParam); 3650 CallArgs.push_back(LIParam); 3651 CallArgs.push_back(RParam); 3652 } 3653 CallArgs.push_back(SharedsParam); 3654 3655 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 3656 CallArgs); 3657 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 3658 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 3659 CGF.FinishFunction(); 3660 return TaskEntry; 3661 } 3662 3663 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 3664 SourceLocation Loc, 3665 QualType KmpInt32Ty, 3666 QualType KmpTaskTWithPrivatesPtrQTy, 3667 QualType KmpTaskTWithPrivatesQTy) { 3668 ASTContext &C = CGM.getContext(); 3669 FunctionArgList Args; 3670 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3671 ImplicitParamDecl::Other); 3672 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3673 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3674 ImplicitParamDecl::Other); 3675 Args.push_back(&GtidArg); 3676 Args.push_back(&TaskTypeArg); 3677 const auto &DestructorFnInfo = 3678 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3679 llvm::FunctionType *DestructorFnTy = 3680 CGM.getTypes().GetFunctionType(DestructorFnInfo); 3681 std::string Name = 3682 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 3683 auto *DestructorFn = 3684 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 3685 Name, &CGM.getModule()); 3686 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 3687 DestructorFnInfo); 3688 DestructorFn->setDoesNotRecurse(); 3689 CodeGenFunction CGF(CGM); 3690 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 3691 Args, Loc, Loc); 3692 3693 LValue Base = CGF.EmitLoadOfPointerLValue( 3694 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3695 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3696 const auto *KmpTaskTWithPrivatesQTyRD = 3697 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3698 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3699 Base = CGF.EmitLValueForField(Base, *FI); 3700 for (const auto *Field : 3701 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 3702 if (QualType::DestructionKind DtorKind = 3703 Field->getType().isDestructedType()) { 3704 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 3705 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 3706 } 3707 } 3708 CGF.FinishFunction(); 3709 return DestructorFn; 3710 } 3711 3712 /// Emit a privates mapping function for correct handling of private and 3713 /// firstprivate variables. 3714 /// \code 3715 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 3716 /// **noalias priv1,..., <tyn> **noalias privn) { 3717 /// *priv1 = &.privates.priv1; 3718 /// ...; 3719 /// *privn = &.privates.privn; 3720 /// } 3721 /// \endcode 3722 static llvm::Value * 3723 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 3724 const OMPTaskDataTy &Data, QualType PrivatesQTy, 3725 ArrayRef<PrivateDataTy> Privates) { 3726 ASTContext &C = CGM.getContext(); 3727 FunctionArgList Args; 3728 ImplicitParamDecl TaskPrivatesArg( 3729 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3730 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 3731 ImplicitParamDecl::Other); 3732 Args.push_back(&TaskPrivatesArg); 3733 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, unsigned> PrivateVarsPos; 3734 unsigned Counter = 1; 3735 for (const Expr *E : Data.PrivateVars) { 3736 Args.push_back(ImplicitParamDecl::Create( 3737 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3738 C.getPointerType(C.getPointerType(E->getType())) 3739 .withConst() 3740 .withRestrict(), 3741 ImplicitParamDecl::Other)); 3742 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3743 PrivateVarsPos[VD] = Counter; 3744 ++Counter; 3745 } 3746 for (const Expr *E : Data.FirstprivateVars) { 3747 Args.push_back(ImplicitParamDecl::Create( 3748 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3749 C.getPointerType(C.getPointerType(E->getType())) 3750 .withConst() 3751 .withRestrict(), 3752 ImplicitParamDecl::Other)); 3753 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3754 PrivateVarsPos[VD] = Counter; 3755 ++Counter; 3756 } 3757 for (const Expr *E : Data.LastprivateVars) { 3758 Args.push_back(ImplicitParamDecl::Create( 3759 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3760 C.getPointerType(C.getPointerType(E->getType())) 3761 .withConst() 3762 .withRestrict(), 3763 ImplicitParamDecl::Other)); 3764 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3765 PrivateVarsPos[VD] = Counter; 3766 ++Counter; 3767 } 3768 for (const VarDecl *VD : Data.PrivateLocals) { 3769 QualType Ty = VD->getType().getNonReferenceType(); 3770 if (VD->getType()->isLValueReferenceType()) 3771 Ty = C.getPointerType(Ty); 3772 if (isAllocatableDecl(VD)) 3773 Ty = C.getPointerType(Ty); 3774 Args.push_back(ImplicitParamDecl::Create( 3775 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3776 C.getPointerType(C.getPointerType(Ty)).withConst().withRestrict(), 3777 ImplicitParamDecl::Other)); 3778 PrivateVarsPos[VD] = Counter; 3779 ++Counter; 3780 } 3781 const auto &TaskPrivatesMapFnInfo = 3782 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3783 llvm::FunctionType *TaskPrivatesMapTy = 3784 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 3785 std::string Name = 3786 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 3787 auto *TaskPrivatesMap = llvm::Function::Create( 3788 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 3789 &CGM.getModule()); 3790 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 3791 TaskPrivatesMapFnInfo); 3792 if (CGM.getLangOpts().Optimize) { 3793 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 3794 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 3795 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 3796 } 3797 CodeGenFunction CGF(CGM); 3798 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 3799 TaskPrivatesMapFnInfo, Args, Loc, Loc); 3800 3801 // *privi = &.privates.privi; 3802 LValue Base = CGF.EmitLoadOfPointerLValue( 3803 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 3804 TaskPrivatesArg.getType()->castAs<PointerType>()); 3805 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 3806 Counter = 0; 3807 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 3808 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 3809 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 3810 LValue RefLVal = 3811 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 3812 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 3813 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 3814 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 3815 ++Counter; 3816 } 3817 CGF.FinishFunction(); 3818 return TaskPrivatesMap; 3819 } 3820 3821 /// Emit initialization for private variables in task-based directives. 3822 static void emitPrivatesInit(CodeGenFunction &CGF, 3823 const OMPExecutableDirective &D, 3824 Address KmpTaskSharedsPtr, LValue TDBase, 3825 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3826 QualType SharedsTy, QualType SharedsPtrTy, 3827 const OMPTaskDataTy &Data, 3828 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 3829 ASTContext &C = CGF.getContext(); 3830 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3831 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 3832 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 3833 ? OMPD_taskloop 3834 : OMPD_task; 3835 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 3836 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 3837 LValue SrcBase; 3838 bool IsTargetTask = 3839 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 3840 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 3841 // For target-based directives skip 4 firstprivate arrays BasePointersArray, 3842 // PointersArray, SizesArray, and MappersArray. The original variables for 3843 // these arrays are not captured and we get their addresses explicitly. 3844 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) || 3845 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 3846 SrcBase = CGF.MakeAddrLValue( 3847 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3848 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 3849 SharedsTy); 3850 } 3851 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 3852 for (const PrivateDataTy &Pair : Privates) { 3853 // Do not initialize private locals. 3854 if (Pair.second.isLocalPrivate()) { 3855 ++FI; 3856 continue; 3857 } 3858 const VarDecl *VD = Pair.second.PrivateCopy; 3859 const Expr *Init = VD->getAnyInitializer(); 3860 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 3861 !CGF.isTrivialInitializer(Init)))) { 3862 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 3863 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 3864 const VarDecl *OriginalVD = Pair.second.Original; 3865 // Check if the variable is the target-based BasePointersArray, 3866 // PointersArray, SizesArray, or MappersArray. 3867 LValue SharedRefLValue; 3868 QualType Type = PrivateLValue.getType(); 3869 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 3870 if (IsTargetTask && !SharedField) { 3871 assert(isa<ImplicitParamDecl>(OriginalVD) && 3872 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 3873 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3874 ->getNumParams() == 0 && 3875 isa<TranslationUnitDecl>( 3876 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3877 ->getDeclContext()) && 3878 "Expected artificial target data variable."); 3879 SharedRefLValue = 3880 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 3881 } else if (ForDup) { 3882 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 3883 SharedRefLValue = CGF.MakeAddrLValue( 3884 Address(SharedRefLValue.getPointer(CGF), 3885 C.getDeclAlign(OriginalVD)), 3886 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 3887 SharedRefLValue.getTBAAInfo()); 3888 } else if (CGF.LambdaCaptureFields.count( 3889 Pair.second.Original->getCanonicalDecl()) > 0 || 3890 dyn_cast_or_null<BlockDecl>(CGF.CurCodeDecl)) { 3891 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3892 } else { 3893 // Processing for implicitly captured variables. 3894 InlinedOpenMPRegionRAII Region( 3895 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown, 3896 /*HasCancel=*/false, /*NoInheritance=*/true); 3897 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3898 } 3899 if (Type->isArrayType()) { 3900 // Initialize firstprivate array. 3901 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 3902 // Perform simple memcpy. 3903 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 3904 } else { 3905 // Initialize firstprivate array using element-by-element 3906 // initialization. 3907 CGF.EmitOMPAggregateAssign( 3908 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 3909 Type, 3910 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 3911 Address SrcElement) { 3912 // Clean up any temporaries needed by the initialization. 3913 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3914 InitScope.addPrivate( 3915 Elem, [SrcElement]() -> Address { return SrcElement; }); 3916 (void)InitScope.Privatize(); 3917 // Emit initialization for single element. 3918 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 3919 CGF, &CapturesInfo); 3920 CGF.EmitAnyExprToMem(Init, DestElement, 3921 Init->getType().getQualifiers(), 3922 /*IsInitializer=*/false); 3923 }); 3924 } 3925 } else { 3926 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3927 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 3928 return SharedRefLValue.getAddress(CGF); 3929 }); 3930 (void)InitScope.Privatize(); 3931 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 3932 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 3933 /*capturedByInit=*/false); 3934 } 3935 } else { 3936 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 3937 } 3938 } 3939 ++FI; 3940 } 3941 } 3942 3943 /// Check if duplication function is required for taskloops. 3944 static bool checkInitIsRequired(CodeGenFunction &CGF, 3945 ArrayRef<PrivateDataTy> Privates) { 3946 bool InitRequired = false; 3947 for (const PrivateDataTy &Pair : Privates) { 3948 if (Pair.second.isLocalPrivate()) 3949 continue; 3950 const VarDecl *VD = Pair.second.PrivateCopy; 3951 const Expr *Init = VD->getAnyInitializer(); 3952 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 3953 !CGF.isTrivialInitializer(Init)); 3954 if (InitRequired) 3955 break; 3956 } 3957 return InitRequired; 3958 } 3959 3960 3961 /// Emit task_dup function (for initialization of 3962 /// private/firstprivate/lastprivate vars and last_iter flag) 3963 /// \code 3964 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 3965 /// lastpriv) { 3966 /// // setup lastprivate flag 3967 /// task_dst->last = lastpriv; 3968 /// // could be constructor calls here... 3969 /// } 3970 /// \endcode 3971 static llvm::Value * 3972 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 3973 const OMPExecutableDirective &D, 3974 QualType KmpTaskTWithPrivatesPtrQTy, 3975 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3976 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 3977 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 3978 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 3979 ASTContext &C = CGM.getContext(); 3980 FunctionArgList Args; 3981 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3982 KmpTaskTWithPrivatesPtrQTy, 3983 ImplicitParamDecl::Other); 3984 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3985 KmpTaskTWithPrivatesPtrQTy, 3986 ImplicitParamDecl::Other); 3987 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 3988 ImplicitParamDecl::Other); 3989 Args.push_back(&DstArg); 3990 Args.push_back(&SrcArg); 3991 Args.push_back(&LastprivArg); 3992 const auto &TaskDupFnInfo = 3993 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3994 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 3995 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 3996 auto *TaskDup = llvm::Function::Create( 3997 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3998 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 3999 TaskDup->setDoesNotRecurse(); 4000 CodeGenFunction CGF(CGM); 4001 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4002 Loc); 4003 4004 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4005 CGF.GetAddrOfLocalVar(&DstArg), 4006 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4007 // task_dst->liter = lastpriv; 4008 if (WithLastIter) { 4009 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4010 LValue Base = CGF.EmitLValueForField( 4011 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4012 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4013 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4014 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4015 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4016 } 4017 4018 // Emit initial values for private copies (if any). 4019 assert(!Privates.empty()); 4020 Address KmpTaskSharedsPtr = Address::invalid(); 4021 if (!Data.FirstprivateVars.empty()) { 4022 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4023 CGF.GetAddrOfLocalVar(&SrcArg), 4024 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4025 LValue Base = CGF.EmitLValueForField( 4026 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4027 KmpTaskSharedsPtr = Address( 4028 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4029 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4030 KmpTaskTShareds)), 4031 Loc), 4032 CGM.getNaturalTypeAlignment(SharedsTy)); 4033 } 4034 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4035 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4036 CGF.FinishFunction(); 4037 return TaskDup; 4038 } 4039 4040 /// Checks if destructor function is required to be generated. 4041 /// \return true if cleanups are required, false otherwise. 4042 static bool 4043 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4044 ArrayRef<PrivateDataTy> Privates) { 4045 for (const PrivateDataTy &P : Privates) { 4046 if (P.second.isLocalPrivate()) 4047 continue; 4048 QualType Ty = P.second.Original->getType().getNonReferenceType(); 4049 if (Ty.isDestructedType()) 4050 return true; 4051 } 4052 return false; 4053 } 4054 4055 namespace { 4056 /// Loop generator for OpenMP iterator expression. 4057 class OMPIteratorGeneratorScope final 4058 : public CodeGenFunction::OMPPrivateScope { 4059 CodeGenFunction &CGF; 4060 const OMPIteratorExpr *E = nullptr; 4061 SmallVector<CodeGenFunction::JumpDest, 4> ContDests; 4062 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests; 4063 OMPIteratorGeneratorScope() = delete; 4064 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete; 4065 4066 public: 4067 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E) 4068 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) { 4069 if (!E) 4070 return; 4071 SmallVector<llvm::Value *, 4> Uppers; 4072 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4073 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper)); 4074 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I)); 4075 addPrivate(VD, [&CGF, VD]() { 4076 return CGF.CreateMemTemp(VD->getType(), VD->getName()); 4077 }); 4078 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4079 addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() { 4080 return CGF.CreateMemTemp(HelperData.CounterVD->getType(), 4081 "counter.addr"); 4082 }); 4083 } 4084 Privatize(); 4085 4086 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4087 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4088 LValue CLVal = 4089 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD), 4090 HelperData.CounterVD->getType()); 4091 // Counter = 0; 4092 CGF.EmitStoreOfScalar( 4093 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0), 4094 CLVal); 4095 CodeGenFunction::JumpDest &ContDest = 4096 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont")); 4097 CodeGenFunction::JumpDest &ExitDest = 4098 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit")); 4099 // N = <number-of_iterations>; 4100 llvm::Value *N = Uppers[I]; 4101 // cont: 4102 // if (Counter < N) goto body; else goto exit; 4103 CGF.EmitBlock(ContDest.getBlock()); 4104 auto *CVal = 4105 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation()); 4106 llvm::Value *Cmp = 4107 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType() 4108 ? CGF.Builder.CreateICmpSLT(CVal, N) 4109 : CGF.Builder.CreateICmpULT(CVal, N); 4110 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body"); 4111 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock()); 4112 // body: 4113 CGF.EmitBlock(BodyBB); 4114 // Iteri = Begini + Counter * Stepi; 4115 CGF.EmitIgnoredExpr(HelperData.Update); 4116 } 4117 } 4118 ~OMPIteratorGeneratorScope() { 4119 if (!E) 4120 return; 4121 for (unsigned I = E->numOfIterators(); I > 0; --I) { 4122 // Counter = Counter + 1; 4123 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1); 4124 CGF.EmitIgnoredExpr(HelperData.CounterUpdate); 4125 // goto cont; 4126 CGF.EmitBranchThroughCleanup(ContDests[I - 1]); 4127 // exit: 4128 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1); 4129 } 4130 } 4131 }; 4132 } // namespace 4133 4134 static std::pair<llvm::Value *, llvm::Value *> 4135 getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { 4136 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E); 4137 llvm::Value *Addr; 4138 if (OASE) { 4139 const Expr *Base = OASE->getBase(); 4140 Addr = CGF.EmitScalarExpr(Base); 4141 } else { 4142 Addr = CGF.EmitLValue(E).getPointer(CGF); 4143 } 4144 llvm::Value *SizeVal; 4145 QualType Ty = E->getType(); 4146 if (OASE) { 4147 SizeVal = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType()); 4148 for (const Expr *SE : OASE->getDimensions()) { 4149 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 4150 Sz = CGF.EmitScalarConversion( 4151 Sz, SE->getType(), CGF.getContext().getSizeType(), SE->getExprLoc()); 4152 SizeVal = CGF.Builder.CreateNUWMul(SizeVal, Sz); 4153 } 4154 } else if (const auto *ASE = 4155 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 4156 LValue UpAddrLVal = 4157 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 4158 llvm::Value *UpAddr = 4159 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 4160 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); 4161 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); 4162 SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 4163 } else { 4164 SizeVal = CGF.getTypeSize(Ty); 4165 } 4166 return std::make_pair(Addr, SizeVal); 4167 } 4168 4169 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4170 static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) { 4171 QualType FlagsTy = C.getIntTypeForBitwidth(32, /*Signed=*/false); 4172 if (KmpTaskAffinityInfoTy.isNull()) { 4173 RecordDecl *KmpAffinityInfoRD = 4174 C.buildImplicitRecord("kmp_task_affinity_info_t"); 4175 KmpAffinityInfoRD->startDefinition(); 4176 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getIntPtrType()); 4177 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType()); 4178 addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy); 4179 KmpAffinityInfoRD->completeDefinition(); 4180 KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD); 4181 } 4182 } 4183 4184 CGOpenMPRuntime::TaskResultTy 4185 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4186 const OMPExecutableDirective &D, 4187 llvm::Function *TaskFunction, QualType SharedsTy, 4188 Address Shareds, const OMPTaskDataTy &Data) { 4189 ASTContext &C = CGM.getContext(); 4190 llvm::SmallVector<PrivateDataTy, 4> Privates; 4191 // Aggregate privates and sort them by the alignment. 4192 const auto *I = Data.PrivateCopies.begin(); 4193 for (const Expr *E : Data.PrivateVars) { 4194 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4195 Privates.emplace_back( 4196 C.getDeclAlign(VD), 4197 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4198 /*PrivateElemInit=*/nullptr)); 4199 ++I; 4200 } 4201 I = Data.FirstprivateCopies.begin(); 4202 const auto *IElemInitRef = Data.FirstprivateInits.begin(); 4203 for (const Expr *E : Data.FirstprivateVars) { 4204 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4205 Privates.emplace_back( 4206 C.getDeclAlign(VD), 4207 PrivateHelpersTy( 4208 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4209 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4210 ++I; 4211 ++IElemInitRef; 4212 } 4213 I = Data.LastprivateCopies.begin(); 4214 for (const Expr *E : Data.LastprivateVars) { 4215 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4216 Privates.emplace_back( 4217 C.getDeclAlign(VD), 4218 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4219 /*PrivateElemInit=*/nullptr)); 4220 ++I; 4221 } 4222 for (const VarDecl *VD : Data.PrivateLocals) { 4223 if (isAllocatableDecl(VD)) 4224 Privates.emplace_back(CGM.getPointerAlign(), PrivateHelpersTy(VD)); 4225 else 4226 Privates.emplace_back(C.getDeclAlign(VD), PrivateHelpersTy(VD)); 4227 } 4228 llvm::stable_sort(Privates, 4229 [](const PrivateDataTy &L, const PrivateDataTy &R) { 4230 return L.first > R.first; 4231 }); 4232 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4233 // Build type kmp_routine_entry_t (if not built yet). 4234 emitKmpRoutineEntryT(KmpInt32Ty); 4235 // Build type kmp_task_t (if not built yet). 4236 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 4237 if (SavedKmpTaskloopTQTy.isNull()) { 4238 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4239 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4240 } 4241 KmpTaskTQTy = SavedKmpTaskloopTQTy; 4242 } else { 4243 assert((D.getDirectiveKind() == OMPD_task || 4244 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 4245 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 4246 "Expected taskloop, task or target directive"); 4247 if (SavedKmpTaskTQTy.isNull()) { 4248 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4249 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4250 } 4251 KmpTaskTQTy = SavedKmpTaskTQTy; 4252 } 4253 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4254 // Build particular struct kmp_task_t for the given task. 4255 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 4256 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 4257 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 4258 QualType KmpTaskTWithPrivatesPtrQTy = 4259 C.getPointerType(KmpTaskTWithPrivatesQTy); 4260 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 4261 llvm::Type *KmpTaskTWithPrivatesPtrTy = 4262 KmpTaskTWithPrivatesTy->getPointerTo(); 4263 llvm::Value *KmpTaskTWithPrivatesTySize = 4264 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 4265 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 4266 4267 // Emit initial values for private copies (if any). 4268 llvm::Value *TaskPrivatesMap = nullptr; 4269 llvm::Type *TaskPrivatesMapTy = 4270 std::next(TaskFunction->arg_begin(), 3)->getType(); 4271 if (!Privates.empty()) { 4272 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4273 TaskPrivatesMap = 4274 emitTaskPrivateMappingFunction(CGM, Loc, Data, FI->getType(), Privates); 4275 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4276 TaskPrivatesMap, TaskPrivatesMapTy); 4277 } else { 4278 TaskPrivatesMap = llvm::ConstantPointerNull::get( 4279 cast<llvm::PointerType>(TaskPrivatesMapTy)); 4280 } 4281 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 4282 // kmp_task_t *tt); 4283 llvm::Function *TaskEntry = emitProxyTaskFunction( 4284 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4285 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 4286 TaskPrivatesMap); 4287 4288 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 4289 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 4290 // kmp_routine_entry_t *task_entry); 4291 // Task flags. Format is taken from 4292 // https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h, 4293 // description of kmp_tasking_flags struct. 4294 enum { 4295 TiedFlag = 0x1, 4296 FinalFlag = 0x2, 4297 DestructorsFlag = 0x8, 4298 PriorityFlag = 0x20, 4299 DetachableFlag = 0x40, 4300 }; 4301 unsigned Flags = Data.Tied ? TiedFlag : 0; 4302 bool NeedsCleanup = false; 4303 if (!Privates.empty()) { 4304 NeedsCleanup = 4305 checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD, Privates); 4306 if (NeedsCleanup) 4307 Flags = Flags | DestructorsFlag; 4308 } 4309 if (Data.Priority.getInt()) 4310 Flags = Flags | PriorityFlag; 4311 if (D.hasClausesOfKind<OMPDetachClause>()) 4312 Flags = Flags | DetachableFlag; 4313 llvm::Value *TaskFlags = 4314 Data.Final.getPointer() 4315 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 4316 CGF.Builder.getInt32(FinalFlag), 4317 CGF.Builder.getInt32(/*C=*/0)) 4318 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 4319 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 4320 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 4321 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 4322 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 4323 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4324 TaskEntry, KmpRoutineEntryPtrTy)}; 4325 llvm::Value *NewTask; 4326 if (D.hasClausesOfKind<OMPNowaitClause>()) { 4327 // Check if we have any device clause associated with the directive. 4328 const Expr *Device = nullptr; 4329 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 4330 Device = C->getDevice(); 4331 // Emit device ID if any otherwise use default value. 4332 llvm::Value *DeviceID; 4333 if (Device) 4334 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 4335 CGF.Int64Ty, /*isSigned=*/true); 4336 else 4337 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 4338 AllocArgs.push_back(DeviceID); 4339 NewTask = CGF.EmitRuntimeCall( 4340 OMPBuilder.getOrCreateRuntimeFunction( 4341 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc), 4342 AllocArgs); 4343 } else { 4344 NewTask = 4345 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 4346 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc), 4347 AllocArgs); 4348 } 4349 // Emit detach clause initialization. 4350 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid, 4351 // task_descriptor); 4352 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) { 4353 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts(); 4354 LValue EvtLVal = CGF.EmitLValue(Evt); 4355 4356 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 4357 // int gtid, kmp_task_t *task); 4358 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc()); 4359 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc()); 4360 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false); 4361 llvm::Value *EvtVal = CGF.EmitRuntimeCall( 4362 OMPBuilder.getOrCreateRuntimeFunction( 4363 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event), 4364 {Loc, Tid, NewTask}); 4365 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(), 4366 Evt->getExprLoc()); 4367 CGF.EmitStoreOfScalar(EvtVal, EvtLVal); 4368 } 4369 // Process affinity clauses. 4370 if (D.hasClausesOfKind<OMPAffinityClause>()) { 4371 // Process list of affinity data. 4372 ASTContext &C = CGM.getContext(); 4373 Address AffinitiesArray = Address::invalid(); 4374 // Calculate number of elements to form the array of affinity data. 4375 llvm::Value *NumOfElements = nullptr; 4376 unsigned NumAffinities = 0; 4377 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4378 if (const Expr *Modifier = C->getModifier()) { 4379 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts()); 4380 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4381 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4382 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4383 NumOfElements = 4384 NumOfElements ? CGF.Builder.CreateNUWMul(NumOfElements, Sz) : Sz; 4385 } 4386 } else { 4387 NumAffinities += C->varlist_size(); 4388 } 4389 } 4390 getKmpAffinityType(CGM.getContext(), KmpTaskAffinityInfoTy); 4391 // Fields ids in kmp_task_affinity_info record. 4392 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags }; 4393 4394 QualType KmpTaskAffinityInfoArrayTy; 4395 if (NumOfElements) { 4396 NumOfElements = CGF.Builder.CreateNUWAdd( 4397 llvm::ConstantInt::get(CGF.SizeTy, NumAffinities), NumOfElements); 4398 OpaqueValueExpr OVE( 4399 Loc, 4400 C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0), 4401 VK_RValue); 4402 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 4403 RValue::get(NumOfElements)); 4404 KmpTaskAffinityInfoArrayTy = 4405 C.getVariableArrayType(KmpTaskAffinityInfoTy, &OVE, ArrayType::Normal, 4406 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4407 // Properly emit variable-sized array. 4408 auto *PD = ImplicitParamDecl::Create(C, KmpTaskAffinityInfoArrayTy, 4409 ImplicitParamDecl::Other); 4410 CGF.EmitVarDecl(*PD); 4411 AffinitiesArray = CGF.GetAddrOfLocalVar(PD); 4412 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4413 /*isSigned=*/false); 4414 } else { 4415 KmpTaskAffinityInfoArrayTy = C.getConstantArrayType( 4416 KmpTaskAffinityInfoTy, 4417 llvm::APInt(C.getTypeSize(C.getSizeType()), NumAffinities), nullptr, 4418 ArrayType::Normal, /*IndexTypeQuals=*/0); 4419 AffinitiesArray = 4420 CGF.CreateMemTemp(KmpTaskAffinityInfoArrayTy, ".affs.arr.addr"); 4421 AffinitiesArray = CGF.Builder.CreateConstArrayGEP(AffinitiesArray, 0); 4422 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumAffinities, 4423 /*isSigned=*/false); 4424 } 4425 4426 const auto *KmpAffinityInfoRD = KmpTaskAffinityInfoTy->getAsRecordDecl(); 4427 // Fill array by elements without iterators. 4428 unsigned Pos = 0; 4429 bool HasIterator = false; 4430 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4431 if (C->getModifier()) { 4432 HasIterator = true; 4433 continue; 4434 } 4435 for (const Expr *E : C->varlists()) { 4436 llvm::Value *Addr; 4437 llvm::Value *Size; 4438 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4439 LValue Base = 4440 CGF.MakeAddrLValue(CGF.Builder.CreateConstGEP(AffinitiesArray, Pos), 4441 KmpTaskAffinityInfoTy); 4442 // affs[i].base_addr = &<Affinities[i].second>; 4443 LValue BaseAddrLVal = CGF.EmitLValueForField( 4444 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4445 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4446 BaseAddrLVal); 4447 // affs[i].len = sizeof(<Affinities[i].second>); 4448 LValue LenLVal = CGF.EmitLValueForField( 4449 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4450 CGF.EmitStoreOfScalar(Size, LenLVal); 4451 ++Pos; 4452 } 4453 } 4454 LValue PosLVal; 4455 if (HasIterator) { 4456 PosLVal = CGF.MakeAddrLValue( 4457 CGF.CreateMemTemp(C.getSizeType(), "affs.counter.addr"), 4458 C.getSizeType()); 4459 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4460 } 4461 // Process elements with iterators. 4462 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4463 const Expr *Modifier = C->getModifier(); 4464 if (!Modifier) 4465 continue; 4466 OMPIteratorGeneratorScope IteratorScope( 4467 CGF, cast_or_null<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts())); 4468 for (const Expr *E : C->varlists()) { 4469 llvm::Value *Addr; 4470 llvm::Value *Size; 4471 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4472 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4473 LValue Base = CGF.MakeAddrLValue( 4474 Address(CGF.Builder.CreateGEP(AffinitiesArray.getPointer(), Idx), 4475 AffinitiesArray.getAlignment()), 4476 KmpTaskAffinityInfoTy); 4477 // affs[i].base_addr = &<Affinities[i].second>; 4478 LValue BaseAddrLVal = CGF.EmitLValueForField( 4479 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4480 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4481 BaseAddrLVal); 4482 // affs[i].len = sizeof(<Affinities[i].second>); 4483 LValue LenLVal = CGF.EmitLValueForField( 4484 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4485 CGF.EmitStoreOfScalar(Size, LenLVal); 4486 Idx = CGF.Builder.CreateNUWAdd( 4487 Idx, llvm::ConstantInt::get(Idx->getType(), 1)); 4488 CGF.EmitStoreOfScalar(Idx, PosLVal); 4489 } 4490 } 4491 // Call to kmp_int32 __kmpc_omp_reg_task_with_affinity(ident_t *loc_ref, 4492 // kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 4493 // naffins, kmp_task_affinity_info_t *affin_list); 4494 llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); 4495 llvm::Value *GTid = getThreadID(CGF, Loc); 4496 llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4497 AffinitiesArray.getPointer(), CGM.VoidPtrTy); 4498 // FIXME: Emit the function and ignore its result for now unless the 4499 // runtime function is properly implemented. 4500 (void)CGF.EmitRuntimeCall( 4501 OMPBuilder.getOrCreateRuntimeFunction( 4502 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity), 4503 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr}); 4504 } 4505 llvm::Value *NewTaskNewTaskTTy = 4506 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4507 NewTask, KmpTaskTWithPrivatesPtrTy); 4508 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 4509 KmpTaskTWithPrivatesQTy); 4510 LValue TDBase = 4511 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4512 // Fill the data in the resulting kmp_task_t record. 4513 // Copy shareds if there are any. 4514 Address KmpTaskSharedsPtr = Address::invalid(); 4515 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 4516 KmpTaskSharedsPtr = 4517 Address(CGF.EmitLoadOfScalar( 4518 CGF.EmitLValueForField( 4519 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 4520 KmpTaskTShareds)), 4521 Loc), 4522 CGM.getNaturalTypeAlignment(SharedsTy)); 4523 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 4524 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 4525 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 4526 } 4527 // Emit initial values for private copies (if any). 4528 TaskResultTy Result; 4529 if (!Privates.empty()) { 4530 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 4531 SharedsTy, SharedsPtrTy, Data, Privates, 4532 /*ForDup=*/false); 4533 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 4534 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 4535 Result.TaskDupFn = emitTaskDupFunction( 4536 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 4537 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 4538 /*WithLastIter=*/!Data.LastprivateVars.empty()); 4539 } 4540 } 4541 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 4542 enum { Priority = 0, Destructors = 1 }; 4543 // Provide pointer to function with destructors for privates. 4544 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 4545 const RecordDecl *KmpCmplrdataUD = 4546 (*FI)->getType()->getAsUnionType()->getDecl(); 4547 if (NeedsCleanup) { 4548 llvm::Value *DestructorFn = emitDestructorsFunction( 4549 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4550 KmpTaskTWithPrivatesQTy); 4551 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 4552 LValue DestructorsLV = CGF.EmitLValueForField( 4553 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 4554 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4555 DestructorFn, KmpRoutineEntryPtrTy), 4556 DestructorsLV); 4557 } 4558 // Set priority. 4559 if (Data.Priority.getInt()) { 4560 LValue Data2LV = CGF.EmitLValueForField( 4561 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 4562 LValue PriorityLV = CGF.EmitLValueForField( 4563 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 4564 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 4565 } 4566 Result.NewTask = NewTask; 4567 Result.TaskEntry = TaskEntry; 4568 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 4569 Result.TDBase = TDBase; 4570 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 4571 return Result; 4572 } 4573 4574 namespace { 4575 /// Dependence kind for RTL. 4576 enum RTLDependenceKindTy { 4577 DepIn = 0x01, 4578 DepInOut = 0x3, 4579 DepMutexInOutSet = 0x4 4580 }; 4581 /// Fields ids in kmp_depend_info record. 4582 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 4583 } // namespace 4584 4585 /// Translates internal dependency kind into the runtime kind. 4586 static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { 4587 RTLDependenceKindTy DepKind; 4588 switch (K) { 4589 case OMPC_DEPEND_in: 4590 DepKind = DepIn; 4591 break; 4592 // Out and InOut dependencies must use the same code. 4593 case OMPC_DEPEND_out: 4594 case OMPC_DEPEND_inout: 4595 DepKind = DepInOut; 4596 break; 4597 case OMPC_DEPEND_mutexinoutset: 4598 DepKind = DepMutexInOutSet; 4599 break; 4600 case OMPC_DEPEND_source: 4601 case OMPC_DEPEND_sink: 4602 case OMPC_DEPEND_depobj: 4603 case OMPC_DEPEND_unknown: 4604 llvm_unreachable("Unknown task dependence type"); 4605 } 4606 return DepKind; 4607 } 4608 4609 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4610 static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, 4611 QualType &FlagsTy) { 4612 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 4613 if (KmpDependInfoTy.isNull()) { 4614 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 4615 KmpDependInfoRD->startDefinition(); 4616 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 4617 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 4618 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 4619 KmpDependInfoRD->completeDefinition(); 4620 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 4621 } 4622 } 4623 4624 std::pair<llvm::Value *, LValue> 4625 CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, 4626 SourceLocation Loc) { 4627 ASTContext &C = CGM.getContext(); 4628 QualType FlagsTy; 4629 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4630 RecordDecl *KmpDependInfoRD = 4631 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4632 LValue Base = CGF.EmitLoadOfPointerLValue( 4633 DepobjLVal.getAddress(CGF), 4634 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4635 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4636 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4637 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 4638 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4639 Base.getTBAAInfo()); 4640 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4641 Addr.getPointer(), 4642 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4643 LValue NumDepsBase = CGF.MakeAddrLValue( 4644 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4645 Base.getBaseInfo(), Base.getTBAAInfo()); 4646 // NumDeps = deps[i].base_addr; 4647 LValue BaseAddrLVal = CGF.EmitLValueForField( 4648 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4649 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc); 4650 return std::make_pair(NumDeps, Base); 4651 } 4652 4653 static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4654 llvm::PointerUnion<unsigned *, LValue *> Pos, 4655 const OMPTaskDataTy::DependData &Data, 4656 Address DependenciesArray) { 4657 CodeGenModule &CGM = CGF.CGM; 4658 ASTContext &C = CGM.getContext(); 4659 QualType FlagsTy; 4660 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4661 RecordDecl *KmpDependInfoRD = 4662 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4663 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 4664 4665 OMPIteratorGeneratorScope IteratorScope( 4666 CGF, cast_or_null<OMPIteratorExpr>( 4667 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4668 : nullptr)); 4669 for (const Expr *E : Data.DepExprs) { 4670 llvm::Value *Addr; 4671 llvm::Value *Size; 4672 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4673 LValue Base; 4674 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4675 Base = CGF.MakeAddrLValue( 4676 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy); 4677 } else { 4678 LValue &PosLVal = *Pos.get<LValue *>(); 4679 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4680 Base = CGF.MakeAddrLValue( 4681 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Idx), 4682 DependenciesArray.getAlignment()), 4683 KmpDependInfoTy); 4684 } 4685 // deps[i].base_addr = &<Dependencies[i].second>; 4686 LValue BaseAddrLVal = CGF.EmitLValueForField( 4687 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4688 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4689 BaseAddrLVal); 4690 // deps[i].len = sizeof(<Dependencies[i].second>); 4691 LValue LenLVal = CGF.EmitLValueForField( 4692 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 4693 CGF.EmitStoreOfScalar(Size, LenLVal); 4694 // deps[i].flags = <Dependencies[i].first>; 4695 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind); 4696 LValue FlagsLVal = CGF.EmitLValueForField( 4697 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 4698 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 4699 FlagsLVal); 4700 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4701 ++(*P); 4702 } else { 4703 LValue &PosLVal = *Pos.get<LValue *>(); 4704 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4705 Idx = CGF.Builder.CreateNUWAdd(Idx, 4706 llvm::ConstantInt::get(Idx->getType(), 1)); 4707 CGF.EmitStoreOfScalar(Idx, PosLVal); 4708 } 4709 } 4710 } 4711 4712 static SmallVector<llvm::Value *, 4> 4713 emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4714 const OMPTaskDataTy::DependData &Data) { 4715 assert(Data.DepKind == OMPC_DEPEND_depobj && 4716 "Expected depobj dependecy kind."); 4717 SmallVector<llvm::Value *, 4> Sizes; 4718 SmallVector<LValue, 4> SizeLVals; 4719 ASTContext &C = CGF.getContext(); 4720 QualType FlagsTy; 4721 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4722 RecordDecl *KmpDependInfoRD = 4723 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4724 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4725 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4726 { 4727 OMPIteratorGeneratorScope IteratorScope( 4728 CGF, cast_or_null<OMPIteratorExpr>( 4729 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4730 : nullptr)); 4731 for (const Expr *E : Data.DepExprs) { 4732 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4733 LValue Base = CGF.EmitLoadOfPointerLValue( 4734 DepobjLVal.getAddress(CGF), 4735 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4736 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4737 Base.getAddress(CGF), KmpDependInfoPtrT); 4738 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4739 Base.getTBAAInfo()); 4740 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4741 Addr.getPointer(), 4742 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4743 LValue NumDepsBase = CGF.MakeAddrLValue( 4744 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4745 Base.getBaseInfo(), Base.getTBAAInfo()); 4746 // NumDeps = deps[i].base_addr; 4747 LValue BaseAddrLVal = CGF.EmitLValueForField( 4748 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4749 llvm::Value *NumDeps = 4750 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4751 LValue NumLVal = CGF.MakeAddrLValue( 4752 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"), 4753 C.getUIntPtrType()); 4754 CGF.InitTempAlloca(NumLVal.getAddress(CGF), 4755 llvm::ConstantInt::get(CGF.IntPtrTy, 0)); 4756 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc()); 4757 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps); 4758 CGF.EmitStoreOfScalar(Add, NumLVal); 4759 SizeLVals.push_back(NumLVal); 4760 } 4761 } 4762 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) { 4763 llvm::Value *Size = 4764 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc()); 4765 Sizes.push_back(Size); 4766 } 4767 return Sizes; 4768 } 4769 4770 static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4771 LValue PosLVal, 4772 const OMPTaskDataTy::DependData &Data, 4773 Address DependenciesArray) { 4774 assert(Data.DepKind == OMPC_DEPEND_depobj && 4775 "Expected depobj dependecy kind."); 4776 ASTContext &C = CGF.getContext(); 4777 QualType FlagsTy; 4778 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4779 RecordDecl *KmpDependInfoRD = 4780 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4781 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4782 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4783 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy); 4784 { 4785 OMPIteratorGeneratorScope IteratorScope( 4786 CGF, cast_or_null<OMPIteratorExpr>( 4787 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4788 : nullptr)); 4789 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) { 4790 const Expr *E = Data.DepExprs[I]; 4791 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4792 LValue Base = CGF.EmitLoadOfPointerLValue( 4793 DepobjLVal.getAddress(CGF), 4794 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4795 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4796 Base.getAddress(CGF), KmpDependInfoPtrT); 4797 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4798 Base.getTBAAInfo()); 4799 4800 // Get number of elements in a single depobj. 4801 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4802 Addr.getPointer(), 4803 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4804 LValue NumDepsBase = CGF.MakeAddrLValue( 4805 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4806 Base.getBaseInfo(), Base.getTBAAInfo()); 4807 // NumDeps = deps[i].base_addr; 4808 LValue BaseAddrLVal = CGF.EmitLValueForField( 4809 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4810 llvm::Value *NumDeps = 4811 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4812 4813 // memcopy dependency data. 4814 llvm::Value *Size = CGF.Builder.CreateNUWMul( 4815 ElSize, 4816 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); 4817 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4818 Address DepAddr = 4819 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Pos), 4820 DependenciesArray.getAlignment()); 4821 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); 4822 4823 // Increase pos. 4824 // pos += size; 4825 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps); 4826 CGF.EmitStoreOfScalar(Add, PosLVal); 4827 } 4828 } 4829 } 4830 4831 std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause( 4832 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies, 4833 SourceLocation Loc) { 4834 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) { 4835 return D.DepExprs.empty(); 4836 })) 4837 return std::make_pair(nullptr, Address::invalid()); 4838 // Process list of dependencies. 4839 ASTContext &C = CGM.getContext(); 4840 Address DependenciesArray = Address::invalid(); 4841 llvm::Value *NumOfElements = nullptr; 4842 unsigned NumDependencies = std::accumulate( 4843 Dependencies.begin(), Dependencies.end(), 0, 4844 [](unsigned V, const OMPTaskDataTy::DependData &D) { 4845 return D.DepKind == OMPC_DEPEND_depobj 4846 ? V 4847 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size())); 4848 }); 4849 QualType FlagsTy; 4850 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4851 bool HasDepobjDeps = false; 4852 bool HasRegularWithIterators = false; 4853 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0); 4854 llvm::Value *NumOfRegularWithIterators = 4855 llvm::ConstantInt::get(CGF.IntPtrTy, 1); 4856 // Calculate number of depobj dependecies and regular deps with the iterators. 4857 for (const OMPTaskDataTy::DependData &D : Dependencies) { 4858 if (D.DepKind == OMPC_DEPEND_depobj) { 4859 SmallVector<llvm::Value *, 4> Sizes = 4860 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D); 4861 for (llvm::Value *Size : Sizes) { 4862 NumOfDepobjElements = 4863 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size); 4864 } 4865 HasDepobjDeps = true; 4866 continue; 4867 } 4868 // Include number of iterations, if any. 4869 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) { 4870 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4871 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4872 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false); 4873 NumOfRegularWithIterators = 4874 CGF.Builder.CreateNUWMul(NumOfRegularWithIterators, Sz); 4875 } 4876 HasRegularWithIterators = true; 4877 continue; 4878 } 4879 } 4880 4881 QualType KmpDependInfoArrayTy; 4882 if (HasDepobjDeps || HasRegularWithIterators) { 4883 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies, 4884 /*isSigned=*/false); 4885 if (HasDepobjDeps) { 4886 NumOfElements = 4887 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements); 4888 } 4889 if (HasRegularWithIterators) { 4890 NumOfElements = 4891 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements); 4892 } 4893 OpaqueValueExpr OVE(Loc, 4894 C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0), 4895 VK_RValue); 4896 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 4897 RValue::get(NumOfElements)); 4898 KmpDependInfoArrayTy = 4899 C.getVariableArrayType(KmpDependInfoTy, &OVE, ArrayType::Normal, 4900 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4901 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy); 4902 // Properly emit variable-sized array. 4903 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy, 4904 ImplicitParamDecl::Other); 4905 CGF.EmitVarDecl(*PD); 4906 DependenciesArray = CGF.GetAddrOfLocalVar(PD); 4907 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4908 /*isSigned=*/false); 4909 } else { 4910 KmpDependInfoArrayTy = C.getConstantArrayType( 4911 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr, 4912 ArrayType::Normal, /*IndexTypeQuals=*/0); 4913 DependenciesArray = 4914 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 4915 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0); 4916 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 4917 /*isSigned=*/false); 4918 } 4919 unsigned Pos = 0; 4920 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4921 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4922 Dependencies[I].IteratorExpr) 4923 continue; 4924 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I], 4925 DependenciesArray); 4926 } 4927 // Copy regular dependecies with iterators. 4928 LValue PosLVal = CGF.MakeAddrLValue( 4929 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType()); 4930 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4931 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4932 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4933 !Dependencies[I].IteratorExpr) 4934 continue; 4935 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I], 4936 DependenciesArray); 4937 } 4938 // Copy final depobj arrays without iterators. 4939 if (HasDepobjDeps) { 4940 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4941 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj) 4942 continue; 4943 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I], 4944 DependenciesArray); 4945 } 4946 } 4947 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4948 DependenciesArray, CGF.VoidPtrTy); 4949 return std::make_pair(NumOfElements, DependenciesArray); 4950 } 4951 4952 Address CGOpenMPRuntime::emitDepobjDependClause( 4953 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, 4954 SourceLocation Loc) { 4955 if (Dependencies.DepExprs.empty()) 4956 return Address::invalid(); 4957 // Process list of dependencies. 4958 ASTContext &C = CGM.getContext(); 4959 Address DependenciesArray = Address::invalid(); 4960 unsigned NumDependencies = Dependencies.DepExprs.size(); 4961 QualType FlagsTy; 4962 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4963 RecordDecl *KmpDependInfoRD = 4964 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4965 4966 llvm::Value *Size; 4967 // Define type kmp_depend_info[<Dependencies.size()>]; 4968 // For depobj reserve one extra element to store the number of elements. 4969 // It is required to handle depobj(x) update(in) construct. 4970 // kmp_depend_info[<Dependencies.size()>] deps; 4971 llvm::Value *NumDepsVal; 4972 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy); 4973 if (const auto *IE = 4974 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) { 4975 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1); 4976 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4977 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4978 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4979 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz); 4980 } 4981 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1), 4982 NumDepsVal); 4983 CharUnits SizeInBytes = 4984 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align); 4985 llvm::Value *RecSize = CGM.getSize(SizeInBytes); 4986 Size = CGF.Builder.CreateNUWMul(Size, RecSize); 4987 NumDepsVal = 4988 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false); 4989 } else { 4990 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 4991 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1), 4992 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 4993 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy); 4994 Size = CGM.getSize(Sz.alignTo(Align)); 4995 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies); 4996 } 4997 // Need to allocate on the dynamic memory. 4998 llvm::Value *ThreadID = getThreadID(CGF, Loc); 4999 // Use default allocator. 5000 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5001 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 5002 5003 llvm::Value *Addr = 5004 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5005 CGM.getModule(), OMPRTL___kmpc_alloc), 5006 Args, ".dep.arr.addr"); 5007 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5008 Addr, CGF.ConvertTypeForMem(KmpDependInfoTy)->getPointerTo()); 5009 DependenciesArray = Address(Addr, Align); 5010 // Write number of elements in the first element of array for depobj. 5011 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy); 5012 // deps[i].base_addr = NumDependencies; 5013 LValue BaseAddrLVal = CGF.EmitLValueForField( 5014 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5015 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal); 5016 llvm::PointerUnion<unsigned *, LValue *> Pos; 5017 unsigned Idx = 1; 5018 LValue PosLVal; 5019 if (Dependencies.IteratorExpr) { 5020 PosLVal = CGF.MakeAddrLValue( 5021 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"), 5022 C.getSizeType()); 5023 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal, 5024 /*IsInit=*/true); 5025 Pos = &PosLVal; 5026 } else { 5027 Pos = &Idx; 5028 } 5029 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray); 5030 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5031 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy); 5032 return DependenciesArray; 5033 } 5034 5035 void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 5036 SourceLocation Loc) { 5037 ASTContext &C = CGM.getContext(); 5038 QualType FlagsTy; 5039 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5040 LValue Base = CGF.EmitLoadOfPointerLValue( 5041 DepobjLVal.getAddress(CGF), 5042 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5043 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5044 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5045 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 5046 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5047 Addr.getPointer(), 5048 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5049 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, 5050 CGF.VoidPtrTy); 5051 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5052 // Use default allocator. 5053 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5054 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator}; 5055 5056 // _kmpc_free(gtid, addr, nullptr); 5057 (void)CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5058 CGM.getModule(), OMPRTL___kmpc_free), 5059 Args); 5060 } 5061 5062 void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 5063 OpenMPDependClauseKind NewDepKind, 5064 SourceLocation Loc) { 5065 ASTContext &C = CGM.getContext(); 5066 QualType FlagsTy; 5067 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5068 RecordDecl *KmpDependInfoRD = 5069 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5070 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5071 llvm::Value *NumDeps; 5072 LValue Base; 5073 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 5074 5075 Address Begin = Base.getAddress(CGF); 5076 // Cast from pointer to array type to pointer to single element. 5077 llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps); 5078 // The basic structure here is a while-do loop. 5079 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); 5080 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); 5081 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5082 CGF.EmitBlock(BodyBB); 5083 llvm::PHINode *ElementPHI = 5084 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); 5085 ElementPHI->addIncoming(Begin.getPointer(), EntryBB); 5086 Begin = Address(ElementPHI, Begin.getAlignment()); 5087 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), 5088 Base.getTBAAInfo()); 5089 // deps[i].flags = NewDepKind; 5090 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind); 5091 LValue FlagsLVal = CGF.EmitLValueForField( 5092 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5093 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5094 FlagsLVal); 5095 5096 // Shift the address forward by one element. 5097 Address ElementNext = 5098 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); 5099 ElementPHI->addIncoming(ElementNext.getPointer(), 5100 CGF.Builder.GetInsertBlock()); 5101 llvm::Value *IsEmpty = 5102 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); 5103 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5104 // Done. 5105 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5106 } 5107 5108 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5109 const OMPExecutableDirective &D, 5110 llvm::Function *TaskFunction, 5111 QualType SharedsTy, Address Shareds, 5112 const Expr *IfCond, 5113 const OMPTaskDataTy &Data) { 5114 if (!CGF.HaveInsertPoint()) 5115 return; 5116 5117 TaskResultTy Result = 5118 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5119 llvm::Value *NewTask = Result.NewTask; 5120 llvm::Function *TaskEntry = Result.TaskEntry; 5121 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5122 LValue TDBase = Result.TDBase; 5123 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5124 // Process list of dependences. 5125 Address DependenciesArray = Address::invalid(); 5126 llvm::Value *NumOfElements; 5127 std::tie(NumOfElements, DependenciesArray) = 5128 emitDependClause(CGF, Data.Dependences, Loc); 5129 5130 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5131 // libcall. 5132 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5133 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5134 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5135 // list is not empty 5136 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5137 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5138 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5139 llvm::Value *DepTaskArgs[7]; 5140 if (!Data.Dependences.empty()) { 5141 DepTaskArgs[0] = UpLoc; 5142 DepTaskArgs[1] = ThreadID; 5143 DepTaskArgs[2] = NewTask; 5144 DepTaskArgs[3] = NumOfElements; 5145 DepTaskArgs[4] = DependenciesArray.getPointer(); 5146 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5147 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5148 } 5149 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs, 5150 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5151 if (!Data.Tied) { 5152 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5153 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5154 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5155 } 5156 if (!Data.Dependences.empty()) { 5157 CGF.EmitRuntimeCall( 5158 OMPBuilder.getOrCreateRuntimeFunction( 5159 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps), 5160 DepTaskArgs); 5161 } else { 5162 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5163 CGM.getModule(), OMPRTL___kmpc_omp_task), 5164 TaskArgs); 5165 } 5166 // Check if parent region is untied and build return for untied task; 5167 if (auto *Region = 5168 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5169 Region->emitUntiedSwitch(CGF); 5170 }; 5171 5172 llvm::Value *DepWaitTaskArgs[6]; 5173 if (!Data.Dependences.empty()) { 5174 DepWaitTaskArgs[0] = UpLoc; 5175 DepWaitTaskArgs[1] = ThreadID; 5176 DepWaitTaskArgs[2] = NumOfElements; 5177 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5178 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5179 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5180 } 5181 auto &M = CGM.getModule(); 5182 auto &&ElseCodeGen = [this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy, 5183 TaskEntry, &Data, &DepWaitTaskArgs, 5184 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5185 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5186 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5187 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5188 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5189 // is specified. 5190 if (!Data.Dependences.empty()) 5191 CGF.EmitRuntimeCall( 5192 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps), 5193 DepWaitTaskArgs); 5194 // Call proxy_task_entry(gtid, new_task); 5195 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5196 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5197 Action.Enter(CGF); 5198 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5199 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5200 OutlinedFnArgs); 5201 }; 5202 5203 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5204 // kmp_task_t *new_task); 5205 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5206 // kmp_task_t *new_task); 5207 RegionCodeGenTy RCG(CodeGen); 5208 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 5209 M, OMPRTL___kmpc_omp_task_begin_if0), 5210 TaskArgs, 5211 OMPBuilder.getOrCreateRuntimeFunction( 5212 M, OMPRTL___kmpc_omp_task_complete_if0), 5213 TaskArgs); 5214 RCG.setAction(Action); 5215 RCG(CGF); 5216 }; 5217 5218 if (IfCond) { 5219 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5220 } else { 5221 RegionCodeGenTy ThenRCG(ThenCodeGen); 5222 ThenRCG(CGF); 5223 } 5224 } 5225 5226 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5227 const OMPLoopDirective &D, 5228 llvm::Function *TaskFunction, 5229 QualType SharedsTy, Address Shareds, 5230 const Expr *IfCond, 5231 const OMPTaskDataTy &Data) { 5232 if (!CGF.HaveInsertPoint()) 5233 return; 5234 TaskResultTy Result = 5235 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5236 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5237 // libcall. 5238 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5239 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5240 // sched, kmp_uint64 grainsize, void *task_dup); 5241 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5242 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5243 llvm::Value *IfVal; 5244 if (IfCond) { 5245 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5246 /*isSigned=*/true); 5247 } else { 5248 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5249 } 5250 5251 LValue LBLVal = CGF.EmitLValueForField( 5252 Result.TDBase, 5253 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5254 const auto *LBVar = 5255 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5256 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5257 LBLVal.getQuals(), 5258 /*IsInitializer=*/true); 5259 LValue UBLVal = CGF.EmitLValueForField( 5260 Result.TDBase, 5261 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5262 const auto *UBVar = 5263 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5264 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5265 UBLVal.getQuals(), 5266 /*IsInitializer=*/true); 5267 LValue StLVal = CGF.EmitLValueForField( 5268 Result.TDBase, 5269 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5270 const auto *StVar = 5271 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5272 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5273 StLVal.getQuals(), 5274 /*IsInitializer=*/true); 5275 // Store reductions address. 5276 LValue RedLVal = CGF.EmitLValueForField( 5277 Result.TDBase, 5278 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5279 if (Data.Reductions) { 5280 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5281 } else { 5282 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5283 CGF.getContext().VoidPtrTy); 5284 } 5285 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5286 llvm::Value *TaskArgs[] = { 5287 UpLoc, 5288 ThreadID, 5289 Result.NewTask, 5290 IfVal, 5291 LBLVal.getPointer(CGF), 5292 UBLVal.getPointer(CGF), 5293 CGF.EmitLoadOfScalar(StLVal, Loc), 5294 llvm::ConstantInt::getSigned( 5295 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5296 llvm::ConstantInt::getSigned( 5297 CGF.IntTy, Data.Schedule.getPointer() 5298 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5299 : NoSchedule), 5300 Data.Schedule.getPointer() 5301 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5302 /*isSigned=*/false) 5303 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5304 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5305 Result.TaskDupFn, CGF.VoidPtrTy) 5306 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5307 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5308 CGM.getModule(), OMPRTL___kmpc_taskloop), 5309 TaskArgs); 5310 } 5311 5312 /// Emit reduction operation for each element of array (required for 5313 /// array sections) LHS op = RHS. 5314 /// \param Type Type of array. 5315 /// \param LHSVar Variable on the left side of the reduction operation 5316 /// (references element of array in original variable). 5317 /// \param RHSVar Variable on the right side of the reduction operation 5318 /// (references element of array in original variable). 5319 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5320 /// RHSVar. 5321 static void EmitOMPAggregateReduction( 5322 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5323 const VarDecl *RHSVar, 5324 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5325 const Expr *, const Expr *)> &RedOpGen, 5326 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5327 const Expr *UpExpr = nullptr) { 5328 // Perform element-by-element initialization. 5329 QualType ElementTy; 5330 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5331 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5332 5333 // Drill down to the base element type on both arrays. 5334 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5335 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5336 5337 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5338 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5339 // Cast from pointer to array type to pointer to single element. 5340 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5341 // The basic structure here is a while-do loop. 5342 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5343 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5344 llvm::Value *IsEmpty = 5345 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5346 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5347 5348 // Enter the loop body, making that address the current address. 5349 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5350 CGF.EmitBlock(BodyBB); 5351 5352 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5353 5354 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5355 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5356 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5357 Address RHSElementCurrent = 5358 Address(RHSElementPHI, 5359 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5360 5361 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5362 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5363 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5364 Address LHSElementCurrent = 5365 Address(LHSElementPHI, 5366 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5367 5368 // Emit copy. 5369 CodeGenFunction::OMPPrivateScope Scope(CGF); 5370 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5371 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5372 Scope.Privatize(); 5373 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5374 Scope.ForceCleanup(); 5375 5376 // Shift the address forward by one element. 5377 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5378 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5379 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5380 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5381 // Check whether we've reached the end. 5382 llvm::Value *Done = 5383 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5384 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5385 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5386 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5387 5388 // Done. 5389 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5390 } 5391 5392 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5393 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5394 /// UDR combiner function. 5395 static void emitReductionCombiner(CodeGenFunction &CGF, 5396 const Expr *ReductionOp) { 5397 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5398 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5399 if (const auto *DRE = 5400 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5401 if (const auto *DRD = 5402 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5403 std::pair<llvm::Function *, llvm::Function *> Reduction = 5404 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5405 RValue Func = RValue::get(Reduction.first); 5406 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5407 CGF.EmitIgnoredExpr(ReductionOp); 5408 return; 5409 } 5410 CGF.EmitIgnoredExpr(ReductionOp); 5411 } 5412 5413 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5414 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5415 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5416 ArrayRef<const Expr *> ReductionOps) { 5417 ASTContext &C = CGM.getContext(); 5418 5419 // void reduction_func(void *LHSArg, void *RHSArg); 5420 FunctionArgList Args; 5421 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5422 ImplicitParamDecl::Other); 5423 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5424 ImplicitParamDecl::Other); 5425 Args.push_back(&LHSArg); 5426 Args.push_back(&RHSArg); 5427 const auto &CGFI = 5428 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5429 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5430 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5431 llvm::GlobalValue::InternalLinkage, Name, 5432 &CGM.getModule()); 5433 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5434 Fn->setDoesNotRecurse(); 5435 CodeGenFunction CGF(CGM); 5436 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5437 5438 // Dst = (void*[n])(LHSArg); 5439 // Src = (void*[n])(RHSArg); 5440 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5441 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5442 ArgsType), CGF.getPointerAlign()); 5443 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5444 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5445 ArgsType), CGF.getPointerAlign()); 5446 5447 // ... 5448 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5449 // ... 5450 CodeGenFunction::OMPPrivateScope Scope(CGF); 5451 auto IPriv = Privates.begin(); 5452 unsigned Idx = 0; 5453 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5454 const auto *RHSVar = 5455 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5456 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5457 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5458 }); 5459 const auto *LHSVar = 5460 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5461 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5462 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5463 }); 5464 QualType PrivTy = (*IPriv)->getType(); 5465 if (PrivTy->isVariablyModifiedType()) { 5466 // Get array size and emit VLA type. 5467 ++Idx; 5468 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5469 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5470 const VariableArrayType *VLA = 5471 CGF.getContext().getAsVariableArrayType(PrivTy); 5472 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5473 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5474 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5475 CGF.EmitVariablyModifiedType(PrivTy); 5476 } 5477 } 5478 Scope.Privatize(); 5479 IPriv = Privates.begin(); 5480 auto ILHS = LHSExprs.begin(); 5481 auto IRHS = RHSExprs.begin(); 5482 for (const Expr *E : ReductionOps) { 5483 if ((*IPriv)->getType()->isArrayType()) { 5484 // Emit reduction for array section. 5485 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5486 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5487 EmitOMPAggregateReduction( 5488 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5489 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5490 emitReductionCombiner(CGF, E); 5491 }); 5492 } else { 5493 // Emit reduction for array subscript or single variable. 5494 emitReductionCombiner(CGF, E); 5495 } 5496 ++IPriv; 5497 ++ILHS; 5498 ++IRHS; 5499 } 5500 Scope.ForceCleanup(); 5501 CGF.FinishFunction(); 5502 return Fn; 5503 } 5504 5505 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5506 const Expr *ReductionOp, 5507 const Expr *PrivateRef, 5508 const DeclRefExpr *LHS, 5509 const DeclRefExpr *RHS) { 5510 if (PrivateRef->getType()->isArrayType()) { 5511 // Emit reduction for array section. 5512 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5513 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5514 EmitOMPAggregateReduction( 5515 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5516 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5517 emitReductionCombiner(CGF, ReductionOp); 5518 }); 5519 } else { 5520 // Emit reduction for array subscript or single variable. 5521 emitReductionCombiner(CGF, ReductionOp); 5522 } 5523 } 5524 5525 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5526 ArrayRef<const Expr *> Privates, 5527 ArrayRef<const Expr *> LHSExprs, 5528 ArrayRef<const Expr *> RHSExprs, 5529 ArrayRef<const Expr *> ReductionOps, 5530 ReductionOptionsTy Options) { 5531 if (!CGF.HaveInsertPoint()) 5532 return; 5533 5534 bool WithNowait = Options.WithNowait; 5535 bool SimpleReduction = Options.SimpleReduction; 5536 5537 // Next code should be emitted for reduction: 5538 // 5539 // static kmp_critical_name lock = { 0 }; 5540 // 5541 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5542 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5543 // ... 5544 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5545 // *(Type<n>-1*)rhs[<n>-1]); 5546 // } 5547 // 5548 // ... 5549 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5550 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5551 // RedList, reduce_func, &<lock>)) { 5552 // case 1: 5553 // ... 5554 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5555 // ... 5556 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5557 // break; 5558 // case 2: 5559 // ... 5560 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5561 // ... 5562 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5563 // break; 5564 // default:; 5565 // } 5566 // 5567 // if SimpleReduction is true, only the next code is generated: 5568 // ... 5569 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5570 // ... 5571 5572 ASTContext &C = CGM.getContext(); 5573 5574 if (SimpleReduction) { 5575 CodeGenFunction::RunCleanupsScope Scope(CGF); 5576 auto IPriv = Privates.begin(); 5577 auto ILHS = LHSExprs.begin(); 5578 auto IRHS = RHSExprs.begin(); 5579 for (const Expr *E : ReductionOps) { 5580 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5581 cast<DeclRefExpr>(*IRHS)); 5582 ++IPriv; 5583 ++ILHS; 5584 ++IRHS; 5585 } 5586 return; 5587 } 5588 5589 // 1. Build a list of reduction variables. 5590 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5591 auto Size = RHSExprs.size(); 5592 for (const Expr *E : Privates) { 5593 if (E->getType()->isVariablyModifiedType()) 5594 // Reserve place for array size. 5595 ++Size; 5596 } 5597 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5598 QualType ReductionArrayTy = 5599 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5600 /*IndexTypeQuals=*/0); 5601 Address ReductionList = 5602 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5603 auto IPriv = Privates.begin(); 5604 unsigned Idx = 0; 5605 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5606 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5607 CGF.Builder.CreateStore( 5608 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5609 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5610 Elem); 5611 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5612 // Store array size. 5613 ++Idx; 5614 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5615 llvm::Value *Size = CGF.Builder.CreateIntCast( 5616 CGF.getVLASize( 5617 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5618 .NumElts, 5619 CGF.SizeTy, /*isSigned=*/false); 5620 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5621 Elem); 5622 } 5623 } 5624 5625 // 2. Emit reduce_func(). 5626 llvm::Function *ReductionFn = emitReductionFunction( 5627 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5628 LHSExprs, RHSExprs, ReductionOps); 5629 5630 // 3. Create static kmp_critical_name lock = { 0 }; 5631 std::string Name = getName({"reduction"}); 5632 llvm::Value *Lock = getCriticalRegionLock(Name); 5633 5634 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5635 // RedList, reduce_func, &<lock>); 5636 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5637 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5638 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5639 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5640 ReductionList.getPointer(), CGF.VoidPtrTy); 5641 llvm::Value *Args[] = { 5642 IdentTLoc, // ident_t *<loc> 5643 ThreadId, // i32 <gtid> 5644 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5645 ReductionArrayTySize, // size_type sizeof(RedList) 5646 RL, // void *RedList 5647 ReductionFn, // void (*) (void *, void *) <reduce_func> 5648 Lock // kmp_critical_name *&<lock> 5649 }; 5650 llvm::Value *Res = CGF.EmitRuntimeCall( 5651 OMPBuilder.getOrCreateRuntimeFunction( 5652 CGM.getModule(), 5653 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce), 5654 Args); 5655 5656 // 5. Build switch(res) 5657 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5658 llvm::SwitchInst *SwInst = 5659 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5660 5661 // 6. Build case 1: 5662 // ... 5663 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5664 // ... 5665 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5666 // break; 5667 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5668 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5669 CGF.EmitBlock(Case1BB); 5670 5671 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5672 llvm::Value *EndArgs[] = { 5673 IdentTLoc, // ident_t *<loc> 5674 ThreadId, // i32 <gtid> 5675 Lock // kmp_critical_name *&<lock> 5676 }; 5677 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5678 CodeGenFunction &CGF, PrePostActionTy &Action) { 5679 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5680 auto IPriv = Privates.begin(); 5681 auto ILHS = LHSExprs.begin(); 5682 auto IRHS = RHSExprs.begin(); 5683 for (const Expr *E : ReductionOps) { 5684 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5685 cast<DeclRefExpr>(*IRHS)); 5686 ++IPriv; 5687 ++ILHS; 5688 ++IRHS; 5689 } 5690 }; 5691 RegionCodeGenTy RCG(CodeGen); 5692 CommonActionTy Action( 5693 nullptr, llvm::None, 5694 OMPBuilder.getOrCreateRuntimeFunction( 5695 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait 5696 : OMPRTL___kmpc_end_reduce), 5697 EndArgs); 5698 RCG.setAction(Action); 5699 RCG(CGF); 5700 5701 CGF.EmitBranch(DefaultBB); 5702 5703 // 7. Build case 2: 5704 // ... 5705 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5706 // ... 5707 // break; 5708 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5709 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5710 CGF.EmitBlock(Case2BB); 5711 5712 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5713 CodeGenFunction &CGF, PrePostActionTy &Action) { 5714 auto ILHS = LHSExprs.begin(); 5715 auto IRHS = RHSExprs.begin(); 5716 auto IPriv = Privates.begin(); 5717 for (const Expr *E : ReductionOps) { 5718 const Expr *XExpr = nullptr; 5719 const Expr *EExpr = nullptr; 5720 const Expr *UpExpr = nullptr; 5721 BinaryOperatorKind BO = BO_Comma; 5722 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5723 if (BO->getOpcode() == BO_Assign) { 5724 XExpr = BO->getLHS(); 5725 UpExpr = BO->getRHS(); 5726 } 5727 } 5728 // Try to emit update expression as a simple atomic. 5729 const Expr *RHSExpr = UpExpr; 5730 if (RHSExpr) { 5731 // Analyze RHS part of the whole expression. 5732 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5733 RHSExpr->IgnoreParenImpCasts())) { 5734 // If this is a conditional operator, analyze its condition for 5735 // min/max reduction operator. 5736 RHSExpr = ACO->getCond(); 5737 } 5738 if (const auto *BORHS = 5739 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5740 EExpr = BORHS->getRHS(); 5741 BO = BORHS->getOpcode(); 5742 } 5743 } 5744 if (XExpr) { 5745 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5746 auto &&AtomicRedGen = [BO, VD, 5747 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5748 const Expr *EExpr, const Expr *UpExpr) { 5749 LValue X = CGF.EmitLValue(XExpr); 5750 RValue E; 5751 if (EExpr) 5752 E = CGF.EmitAnyExpr(EExpr); 5753 CGF.EmitOMPAtomicSimpleUpdateExpr( 5754 X, E, BO, /*IsXLHSInRHSPart=*/true, 5755 llvm::AtomicOrdering::Monotonic, Loc, 5756 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5757 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5758 PrivateScope.addPrivate( 5759 VD, [&CGF, VD, XRValue, Loc]() { 5760 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5761 CGF.emitOMPSimpleStore( 5762 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5763 VD->getType().getNonReferenceType(), Loc); 5764 return LHSTemp; 5765 }); 5766 (void)PrivateScope.Privatize(); 5767 return CGF.EmitAnyExpr(UpExpr); 5768 }); 5769 }; 5770 if ((*IPriv)->getType()->isArrayType()) { 5771 // Emit atomic reduction for array section. 5772 const auto *RHSVar = 5773 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5774 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5775 AtomicRedGen, XExpr, EExpr, UpExpr); 5776 } else { 5777 // Emit atomic reduction for array subscript or single variable. 5778 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5779 } 5780 } else { 5781 // Emit as a critical region. 5782 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5783 const Expr *, const Expr *) { 5784 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5785 std::string Name = RT.getName({"atomic_reduction"}); 5786 RT.emitCriticalRegion( 5787 CGF, Name, 5788 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5789 Action.Enter(CGF); 5790 emitReductionCombiner(CGF, E); 5791 }, 5792 Loc); 5793 }; 5794 if ((*IPriv)->getType()->isArrayType()) { 5795 const auto *LHSVar = 5796 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5797 const auto *RHSVar = 5798 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5799 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5800 CritRedGen); 5801 } else { 5802 CritRedGen(CGF, nullptr, nullptr, nullptr); 5803 } 5804 } 5805 ++ILHS; 5806 ++IRHS; 5807 ++IPriv; 5808 } 5809 }; 5810 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5811 if (!WithNowait) { 5812 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5813 llvm::Value *EndArgs[] = { 5814 IdentTLoc, // ident_t *<loc> 5815 ThreadId, // i32 <gtid> 5816 Lock // kmp_critical_name *&<lock> 5817 }; 5818 CommonActionTy Action(nullptr, llvm::None, 5819 OMPBuilder.getOrCreateRuntimeFunction( 5820 CGM.getModule(), OMPRTL___kmpc_end_reduce), 5821 EndArgs); 5822 AtomicRCG.setAction(Action); 5823 AtomicRCG(CGF); 5824 } else { 5825 AtomicRCG(CGF); 5826 } 5827 5828 CGF.EmitBranch(DefaultBB); 5829 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5830 } 5831 5832 /// Generates unique name for artificial threadprivate variables. 5833 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5834 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5835 const Expr *Ref) { 5836 SmallString<256> Buffer; 5837 llvm::raw_svector_ostream Out(Buffer); 5838 const clang::DeclRefExpr *DE; 5839 const VarDecl *D = ::getBaseDecl(Ref, DE); 5840 if (!D) 5841 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5842 D = D->getCanonicalDecl(); 5843 std::string Name = CGM.getOpenMPRuntime().getName( 5844 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5845 Out << Prefix << Name << "_" 5846 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5847 return std::string(Out.str()); 5848 } 5849 5850 /// Emits reduction initializer function: 5851 /// \code 5852 /// void @.red_init(void* %arg, void* %orig) { 5853 /// %0 = bitcast void* %arg to <type>* 5854 /// store <type> <init>, <type>* %0 5855 /// ret void 5856 /// } 5857 /// \endcode 5858 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 5859 SourceLocation Loc, 5860 ReductionCodeGen &RCG, unsigned N) { 5861 ASTContext &C = CGM.getContext(); 5862 QualType VoidPtrTy = C.VoidPtrTy; 5863 VoidPtrTy.addRestrict(); 5864 FunctionArgList Args; 5865 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5866 ImplicitParamDecl::Other); 5867 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5868 ImplicitParamDecl::Other); 5869 Args.emplace_back(&Param); 5870 Args.emplace_back(&ParamOrig); 5871 const auto &FnInfo = 5872 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5873 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5874 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 5875 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5876 Name, &CGM.getModule()); 5877 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5878 Fn->setDoesNotRecurse(); 5879 CodeGenFunction CGF(CGM); 5880 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5881 Address PrivateAddr = CGF.EmitLoadOfPointer( 5882 CGF.GetAddrOfLocalVar(&Param), 5883 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5884 llvm::Value *Size = nullptr; 5885 // If the size of the reduction item is non-constant, load it from global 5886 // threadprivate variable. 5887 if (RCG.getSizes(N).second) { 5888 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5889 CGF, CGM.getContext().getSizeType(), 5890 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5891 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5892 CGM.getContext().getSizeType(), Loc); 5893 } 5894 RCG.emitAggregateType(CGF, N, Size); 5895 LValue OrigLVal; 5896 // If initializer uses initializer from declare reduction construct, emit a 5897 // pointer to the address of the original reduction item (reuired by reduction 5898 // initializer) 5899 if (RCG.usesReductionInitializer(N)) { 5900 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig); 5901 SharedAddr = CGF.EmitLoadOfPointer( 5902 SharedAddr, 5903 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 5904 OrigLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 5905 } else { 5906 OrigLVal = CGF.MakeNaturalAlignAddrLValue( 5907 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 5908 CGM.getContext().VoidPtrTy); 5909 } 5910 // Emit the initializer: 5911 // %0 = bitcast void* %arg to <type>* 5912 // store <type> <init>, <type>* %0 5913 RCG.emitInitialization(CGF, N, PrivateAddr, OrigLVal, 5914 [](CodeGenFunction &) { return false; }); 5915 CGF.FinishFunction(); 5916 return Fn; 5917 } 5918 5919 /// Emits reduction combiner function: 5920 /// \code 5921 /// void @.red_comb(void* %arg0, void* %arg1) { 5922 /// %lhs = bitcast void* %arg0 to <type>* 5923 /// %rhs = bitcast void* %arg1 to <type>* 5924 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 5925 /// store <type> %2, <type>* %lhs 5926 /// ret void 5927 /// } 5928 /// \endcode 5929 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 5930 SourceLocation Loc, 5931 ReductionCodeGen &RCG, unsigned N, 5932 const Expr *ReductionOp, 5933 const Expr *LHS, const Expr *RHS, 5934 const Expr *PrivateRef) { 5935 ASTContext &C = CGM.getContext(); 5936 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 5937 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 5938 FunctionArgList Args; 5939 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 5940 C.VoidPtrTy, ImplicitParamDecl::Other); 5941 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5942 ImplicitParamDecl::Other); 5943 Args.emplace_back(&ParamInOut); 5944 Args.emplace_back(&ParamIn); 5945 const auto &FnInfo = 5946 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5947 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5948 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 5949 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5950 Name, &CGM.getModule()); 5951 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5952 Fn->setDoesNotRecurse(); 5953 CodeGenFunction CGF(CGM); 5954 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5955 llvm::Value *Size = nullptr; 5956 // If the size of the reduction item is non-constant, load it from global 5957 // threadprivate variable. 5958 if (RCG.getSizes(N).second) { 5959 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5960 CGF, CGM.getContext().getSizeType(), 5961 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5962 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5963 CGM.getContext().getSizeType(), Loc); 5964 } 5965 RCG.emitAggregateType(CGF, N, Size); 5966 // Remap lhs and rhs variables to the addresses of the function arguments. 5967 // %lhs = bitcast void* %arg0 to <type>* 5968 // %rhs = bitcast void* %arg1 to <type>* 5969 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5970 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 5971 // Pull out the pointer to the variable. 5972 Address PtrAddr = CGF.EmitLoadOfPointer( 5973 CGF.GetAddrOfLocalVar(&ParamInOut), 5974 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5975 return CGF.Builder.CreateElementBitCast( 5976 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 5977 }); 5978 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 5979 // Pull out the pointer to the variable. 5980 Address PtrAddr = CGF.EmitLoadOfPointer( 5981 CGF.GetAddrOfLocalVar(&ParamIn), 5982 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5983 return CGF.Builder.CreateElementBitCast( 5984 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 5985 }); 5986 PrivateScope.Privatize(); 5987 // Emit the combiner body: 5988 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 5989 // store <type> %2, <type>* %lhs 5990 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 5991 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 5992 cast<DeclRefExpr>(RHS)); 5993 CGF.FinishFunction(); 5994 return Fn; 5995 } 5996 5997 /// Emits reduction finalizer function: 5998 /// \code 5999 /// void @.red_fini(void* %arg) { 6000 /// %0 = bitcast void* %arg to <type>* 6001 /// <destroy>(<type>* %0) 6002 /// ret void 6003 /// } 6004 /// \endcode 6005 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6006 SourceLocation Loc, 6007 ReductionCodeGen &RCG, unsigned N) { 6008 if (!RCG.needCleanups(N)) 6009 return nullptr; 6010 ASTContext &C = CGM.getContext(); 6011 FunctionArgList Args; 6012 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6013 ImplicitParamDecl::Other); 6014 Args.emplace_back(&Param); 6015 const auto &FnInfo = 6016 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6017 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6018 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6019 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6020 Name, &CGM.getModule()); 6021 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6022 Fn->setDoesNotRecurse(); 6023 CodeGenFunction CGF(CGM); 6024 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6025 Address PrivateAddr = CGF.EmitLoadOfPointer( 6026 CGF.GetAddrOfLocalVar(&Param), 6027 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6028 llvm::Value *Size = nullptr; 6029 // If the size of the reduction item is non-constant, load it from global 6030 // threadprivate variable. 6031 if (RCG.getSizes(N).second) { 6032 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6033 CGF, CGM.getContext().getSizeType(), 6034 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6035 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6036 CGM.getContext().getSizeType(), Loc); 6037 } 6038 RCG.emitAggregateType(CGF, N, Size); 6039 // Emit the finalizer body: 6040 // <destroy>(<type>* %0) 6041 RCG.emitCleanups(CGF, N, PrivateAddr); 6042 CGF.FinishFunction(Loc); 6043 return Fn; 6044 } 6045 6046 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6047 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6048 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6049 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6050 return nullptr; 6051 6052 // Build typedef struct: 6053 // kmp_taskred_input { 6054 // void *reduce_shar; // shared reduction item 6055 // void *reduce_orig; // original reduction item used for initialization 6056 // size_t reduce_size; // size of data item 6057 // void *reduce_init; // data initialization routine 6058 // void *reduce_fini; // data finalization routine 6059 // void *reduce_comb; // data combiner routine 6060 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6061 // } kmp_taskred_input_t; 6062 ASTContext &C = CGM.getContext(); 6063 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t"); 6064 RD->startDefinition(); 6065 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6066 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6067 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6068 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6069 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6070 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6071 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6072 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6073 RD->completeDefinition(); 6074 QualType RDType = C.getRecordType(RD); 6075 unsigned Size = Data.ReductionVars.size(); 6076 llvm::APInt ArraySize(/*numBits=*/64, Size); 6077 QualType ArrayRDType = C.getConstantArrayType( 6078 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6079 // kmp_task_red_input_t .rd_input.[Size]; 6080 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6081 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, 6082 Data.ReductionCopies, Data.ReductionOps); 6083 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6084 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6085 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6086 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6087 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6088 TaskRedInput.getPointer(), Idxs, 6089 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6090 ".rd_input.gep."); 6091 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6092 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6093 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6094 RCG.emitSharedOrigLValue(CGF, Cnt); 6095 llvm::Value *CastedShared = 6096 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6097 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6098 // ElemLVal.reduce_orig = &Origs[Cnt]; 6099 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD); 6100 llvm::Value *CastedOrig = 6101 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF)); 6102 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal); 6103 RCG.emitAggregateType(CGF, Cnt); 6104 llvm::Value *SizeValInChars; 6105 llvm::Value *SizeVal; 6106 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6107 // We use delayed creation/initialization for VLAs and array sections. It is 6108 // required because runtime does not provide the way to pass the sizes of 6109 // VLAs/array sections to initializer/combiner/finalizer functions. Instead 6110 // threadprivate global variables are used to store these values and use 6111 // them in the functions. 6112 bool DelayedCreation = !!SizeVal; 6113 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6114 /*isSigned=*/false); 6115 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6116 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6117 // ElemLVal.reduce_init = init; 6118 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6119 llvm::Value *InitAddr = 6120 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6121 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6122 // ElemLVal.reduce_fini = fini; 6123 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6124 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6125 llvm::Value *FiniAddr = Fini 6126 ? CGF.EmitCastToVoidPtr(Fini) 6127 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6128 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6129 // ElemLVal.reduce_comb = comb; 6130 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6131 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6132 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6133 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6134 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6135 // ElemLVal.flags = 0; 6136 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6137 if (DelayedCreation) { 6138 CGF.EmitStoreOfScalar( 6139 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6140 FlagsLVal); 6141 } else 6142 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6143 FlagsLVal.getType()); 6144 } 6145 if (Data.IsReductionWithTaskMod) { 6146 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6147 // is_ws, int num, void *data); 6148 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6149 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6150 CGM.IntTy, /*isSigned=*/true); 6151 llvm::Value *Args[] = { 6152 IdentTLoc, GTid, 6153 llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0, 6154 /*isSigned=*/true), 6155 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6156 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6157 TaskRedInput.getPointer(), CGM.VoidPtrTy)}; 6158 return CGF.EmitRuntimeCall( 6159 OMPBuilder.getOrCreateRuntimeFunction( 6160 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init), 6161 Args); 6162 } 6163 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data); 6164 llvm::Value *Args[] = { 6165 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6166 /*isSigned=*/true), 6167 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6168 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6169 CGM.VoidPtrTy)}; 6170 return CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6171 CGM.getModule(), OMPRTL___kmpc_taskred_init), 6172 Args); 6173 } 6174 6175 void CGOpenMPRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 6176 SourceLocation Loc, 6177 bool IsWorksharingReduction) { 6178 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6179 // is_ws, int num, void *data); 6180 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6181 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6182 CGM.IntTy, /*isSigned=*/true); 6183 llvm::Value *Args[] = {IdentTLoc, GTid, 6184 llvm::ConstantInt::get(CGM.IntTy, 6185 IsWorksharingReduction ? 1 : 0, 6186 /*isSigned=*/true)}; 6187 (void)CGF.EmitRuntimeCall( 6188 OMPBuilder.getOrCreateRuntimeFunction( 6189 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini), 6190 Args); 6191 } 6192 6193 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6194 SourceLocation Loc, 6195 ReductionCodeGen &RCG, 6196 unsigned N) { 6197 auto Sizes = RCG.getSizes(N); 6198 // Emit threadprivate global variable if the type is non-constant 6199 // (Sizes.second = nullptr). 6200 if (Sizes.second) { 6201 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6202 /*isSigned=*/false); 6203 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6204 CGF, CGM.getContext().getSizeType(), 6205 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6206 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6207 } 6208 } 6209 6210 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6211 SourceLocation Loc, 6212 llvm::Value *ReductionsPtr, 6213 LValue SharedLVal) { 6214 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6215 // *d); 6216 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6217 CGM.IntTy, 6218 /*isSigned=*/true), 6219 ReductionsPtr, 6220 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6221 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6222 return Address( 6223 CGF.EmitRuntimeCall( 6224 OMPBuilder.getOrCreateRuntimeFunction( 6225 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data), 6226 Args), 6227 SharedLVal.getAlignment()); 6228 } 6229 6230 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6231 SourceLocation Loc) { 6232 if (!CGF.HaveInsertPoint()) 6233 return; 6234 6235 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 6236 OMPBuilder.createTaskwait(CGF.Builder); 6237 } else { 6238 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6239 // global_tid); 6240 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6241 // Ignore return result until untied tasks are supported. 6242 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6243 CGM.getModule(), OMPRTL___kmpc_omp_taskwait), 6244 Args); 6245 } 6246 6247 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6248 Region->emitUntiedSwitch(CGF); 6249 } 6250 6251 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6252 OpenMPDirectiveKind InnerKind, 6253 const RegionCodeGenTy &CodeGen, 6254 bool HasCancel) { 6255 if (!CGF.HaveInsertPoint()) 6256 return; 6257 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel, 6258 InnerKind != OMPD_critical && 6259 InnerKind != OMPD_master && 6260 InnerKind != OMPD_masked); 6261 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6262 } 6263 6264 namespace { 6265 enum RTCancelKind { 6266 CancelNoreq = 0, 6267 CancelParallel = 1, 6268 CancelLoop = 2, 6269 CancelSections = 3, 6270 CancelTaskgroup = 4 6271 }; 6272 } // anonymous namespace 6273 6274 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6275 RTCancelKind CancelKind = CancelNoreq; 6276 if (CancelRegion == OMPD_parallel) 6277 CancelKind = CancelParallel; 6278 else if (CancelRegion == OMPD_for) 6279 CancelKind = CancelLoop; 6280 else if (CancelRegion == OMPD_sections) 6281 CancelKind = CancelSections; 6282 else { 6283 assert(CancelRegion == OMPD_taskgroup); 6284 CancelKind = CancelTaskgroup; 6285 } 6286 return CancelKind; 6287 } 6288 6289 void CGOpenMPRuntime::emitCancellationPointCall( 6290 CodeGenFunction &CGF, SourceLocation Loc, 6291 OpenMPDirectiveKind CancelRegion) { 6292 if (!CGF.HaveInsertPoint()) 6293 return; 6294 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6295 // global_tid, kmp_int32 cncl_kind); 6296 if (auto *OMPRegionInfo = 6297 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6298 // For 'cancellation point taskgroup', the task region info may not have a 6299 // cancel. This may instead happen in another adjacent task. 6300 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6301 llvm::Value *Args[] = { 6302 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6303 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6304 // Ignore return result until untied tasks are supported. 6305 llvm::Value *Result = CGF.EmitRuntimeCall( 6306 OMPBuilder.getOrCreateRuntimeFunction( 6307 CGM.getModule(), OMPRTL___kmpc_cancellationpoint), 6308 Args); 6309 // if (__kmpc_cancellationpoint()) { 6310 // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only 6311 // exit from construct; 6312 // } 6313 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6314 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6315 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6316 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6317 CGF.EmitBlock(ExitBB); 6318 if (CancelRegion == OMPD_parallel) 6319 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 6320 // exit from construct; 6321 CodeGenFunction::JumpDest CancelDest = 6322 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6323 CGF.EmitBranchThroughCleanup(CancelDest); 6324 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6325 } 6326 } 6327 } 6328 6329 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6330 const Expr *IfCond, 6331 OpenMPDirectiveKind CancelRegion) { 6332 if (!CGF.HaveInsertPoint()) 6333 return; 6334 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6335 // kmp_int32 cncl_kind); 6336 auto &M = CGM.getModule(); 6337 if (auto *OMPRegionInfo = 6338 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6339 auto &&ThenGen = [this, &M, Loc, CancelRegion, 6340 OMPRegionInfo](CodeGenFunction &CGF, PrePostActionTy &) { 6341 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6342 llvm::Value *Args[] = { 6343 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6344 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6345 // Ignore return result until untied tasks are supported. 6346 llvm::Value *Result = CGF.EmitRuntimeCall( 6347 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args); 6348 // if (__kmpc_cancel()) { 6349 // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only 6350 // exit from construct; 6351 // } 6352 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6353 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6354 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6355 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6356 CGF.EmitBlock(ExitBB); 6357 if (CancelRegion == OMPD_parallel) 6358 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 6359 // exit from construct; 6360 CodeGenFunction::JumpDest CancelDest = 6361 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6362 CGF.EmitBranchThroughCleanup(CancelDest); 6363 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6364 }; 6365 if (IfCond) { 6366 emitIfClause(CGF, IfCond, ThenGen, 6367 [](CodeGenFunction &, PrePostActionTy &) {}); 6368 } else { 6369 RegionCodeGenTy ThenRCG(ThenGen); 6370 ThenRCG(CGF); 6371 } 6372 } 6373 } 6374 6375 namespace { 6376 /// Cleanup action for uses_allocators support. 6377 class OMPUsesAllocatorsActionTy final : public PrePostActionTy { 6378 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators; 6379 6380 public: 6381 OMPUsesAllocatorsActionTy( 6382 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators) 6383 : Allocators(Allocators) {} 6384 void Enter(CodeGenFunction &CGF) override { 6385 if (!CGF.HaveInsertPoint()) 6386 return; 6387 for (const auto &AllocatorData : Allocators) { 6388 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsInit( 6389 CGF, AllocatorData.first, AllocatorData.second); 6390 } 6391 } 6392 void Exit(CodeGenFunction &CGF) override { 6393 if (!CGF.HaveInsertPoint()) 6394 return; 6395 for (const auto &AllocatorData : Allocators) { 6396 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsFini(CGF, 6397 AllocatorData.first); 6398 } 6399 } 6400 }; 6401 } // namespace 6402 6403 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6404 const OMPExecutableDirective &D, StringRef ParentName, 6405 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6406 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6407 assert(!ParentName.empty() && "Invalid target region parent name!"); 6408 HasEmittedTargetRegion = true; 6409 SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators; 6410 for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) { 6411 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 6412 const OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 6413 if (!D.AllocatorTraits) 6414 continue; 6415 Allocators.emplace_back(D.Allocator, D.AllocatorTraits); 6416 } 6417 } 6418 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators); 6419 CodeGen.setAction(UsesAllocatorAction); 6420 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6421 IsOffloadEntry, CodeGen); 6422 } 6423 6424 void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, 6425 const Expr *Allocator, 6426 const Expr *AllocatorTraits) { 6427 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6428 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6429 // Use default memspace handle. 6430 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 6431 llvm::Value *NumTraits = llvm::ConstantInt::get( 6432 CGF.IntTy, cast<ConstantArrayType>( 6433 AllocatorTraits->getType()->getAsArrayTypeUnsafe()) 6434 ->getSize() 6435 .getLimitedValue()); 6436 LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits); 6437 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6438 AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy); 6439 AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, 6440 AllocatorTraitsLVal.getBaseInfo(), 6441 AllocatorTraitsLVal.getTBAAInfo()); 6442 llvm::Value *Traits = 6443 CGF.EmitLoadOfScalar(AllocatorTraitsLVal, AllocatorTraits->getExprLoc()); 6444 6445 llvm::Value *AllocatorVal = 6446 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6447 CGM.getModule(), OMPRTL___kmpc_init_allocator), 6448 {ThreadId, MemSpaceHandle, NumTraits, Traits}); 6449 // Store to allocator. 6450 CGF.EmitVarDecl(*cast<VarDecl>( 6451 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl())); 6452 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6453 AllocatorVal = 6454 CGF.EmitScalarConversion(AllocatorVal, CGF.getContext().VoidPtrTy, 6455 Allocator->getType(), Allocator->getExprLoc()); 6456 CGF.EmitStoreOfScalar(AllocatorVal, AllocatorLVal); 6457 } 6458 6459 void CGOpenMPRuntime::emitUsesAllocatorsFini(CodeGenFunction &CGF, 6460 const Expr *Allocator) { 6461 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6462 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6463 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6464 llvm::Value *AllocatorVal = 6465 CGF.EmitLoadOfScalar(AllocatorLVal, Allocator->getExprLoc()); 6466 AllocatorVal = CGF.EmitScalarConversion(AllocatorVal, Allocator->getType(), 6467 CGF.getContext().VoidPtrTy, 6468 Allocator->getExprLoc()); 6469 (void)CGF.EmitRuntimeCall( 6470 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 6471 OMPRTL___kmpc_destroy_allocator), 6472 {ThreadId, AllocatorVal}); 6473 } 6474 6475 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6476 const OMPExecutableDirective &D, StringRef ParentName, 6477 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6478 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6479 // Create a unique name for the entry function using the source location 6480 // information of the current target region. The name will be something like: 6481 // 6482 // __omp_offloading_DD_FFFF_PP_lBB 6483 // 6484 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6485 // mangled name of the function that encloses the target region and BB is the 6486 // line number of the target region. 6487 6488 unsigned DeviceID; 6489 unsigned FileID; 6490 unsigned Line; 6491 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6492 Line); 6493 SmallString<64> EntryFnName; 6494 { 6495 llvm::raw_svector_ostream OS(EntryFnName); 6496 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6497 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6498 } 6499 6500 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6501 6502 CodeGenFunction CGF(CGM, true); 6503 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6504 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6505 6506 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6507 6508 // If this target outline function is not an offload entry, we don't need to 6509 // register it. 6510 if (!IsOffloadEntry) 6511 return; 6512 6513 // The target region ID is used by the runtime library to identify the current 6514 // target region, so it only has to be unique and not necessarily point to 6515 // anything. It could be the pointer to the outlined function that implements 6516 // the target region, but we aren't using that so that the compiler doesn't 6517 // need to keep that, and could therefore inline the host function if proven 6518 // worthwhile during optimization. In the other hand, if emitting code for the 6519 // device, the ID has to be the function address so that it can retrieved from 6520 // the offloading entry and launched by the runtime library. We also mark the 6521 // outlined function to have external linkage in case we are emitting code for 6522 // the device, because these functions will be entry points to the device. 6523 6524 if (CGM.getLangOpts().OpenMPIsDevice) { 6525 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6526 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6527 OutlinedFn->setDSOLocal(false); 6528 if (CGM.getTriple().isAMDGCN()) 6529 OutlinedFn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); 6530 } else { 6531 std::string Name = getName({EntryFnName, "region_id"}); 6532 OutlinedFnID = new llvm::GlobalVariable( 6533 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6534 llvm::GlobalValue::WeakAnyLinkage, 6535 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6536 } 6537 6538 // Register the information for the entry associated with this target region. 6539 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6540 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6541 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6542 } 6543 6544 /// Checks if the expression is constant or does not have non-trivial function 6545 /// calls. 6546 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6547 // We can skip constant expressions. 6548 // We can skip expressions with trivial calls or simple expressions. 6549 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6550 !E->hasNonTrivialCall(Ctx)) && 6551 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6552 } 6553 6554 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6555 const Stmt *Body) { 6556 const Stmt *Child = Body->IgnoreContainers(); 6557 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6558 Child = nullptr; 6559 for (const Stmt *S : C->body()) { 6560 if (const auto *E = dyn_cast<Expr>(S)) { 6561 if (isTrivial(Ctx, E)) 6562 continue; 6563 } 6564 // Some of the statements can be ignored. 6565 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6566 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6567 continue; 6568 // Analyze declarations. 6569 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6570 if (llvm::all_of(DS->decls(), [](const Decl *D) { 6571 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6572 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6573 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6574 isa<UsingDirectiveDecl>(D) || 6575 isa<OMPDeclareReductionDecl>(D) || 6576 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6577 return true; 6578 const auto *VD = dyn_cast<VarDecl>(D); 6579 if (!VD) 6580 return false; 6581 return VD->hasGlobalStorage() || !VD->isUsed(); 6582 })) 6583 continue; 6584 } 6585 // Found multiple children - cannot get the one child only. 6586 if (Child) 6587 return nullptr; 6588 Child = S; 6589 } 6590 if (Child) 6591 Child = Child->IgnoreContainers(); 6592 } 6593 return Child; 6594 } 6595 6596 /// Emit the number of teams for a target directive. Inspect the num_teams 6597 /// clause associated with a teams construct combined or closely nested 6598 /// with the target directive. 6599 /// 6600 /// Emit a team of size one for directives such as 'target parallel' that 6601 /// have no associated teams construct. 6602 /// 6603 /// Otherwise, return nullptr. 6604 static llvm::Value * 6605 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6606 const OMPExecutableDirective &D) { 6607 assert(!CGF.getLangOpts().OpenMPIsDevice && 6608 "Clauses associated with the teams directive expected to be emitted " 6609 "only for the host!"); 6610 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6611 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6612 "Expected target-based executable directive."); 6613 CGBuilderTy &Bld = CGF.Builder; 6614 switch (DirectiveKind) { 6615 case OMPD_target: { 6616 const auto *CS = D.getInnermostCapturedStmt(); 6617 const auto *Body = 6618 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6619 const Stmt *ChildStmt = 6620 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6621 if (const auto *NestedDir = 6622 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6623 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6624 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6625 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6626 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6627 const Expr *NumTeams = 6628 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6629 llvm::Value *NumTeamsVal = 6630 CGF.EmitScalarExpr(NumTeams, 6631 /*IgnoreResultAssign*/ true); 6632 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6633 /*isSigned=*/true); 6634 } 6635 return Bld.getInt32(0); 6636 } 6637 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6638 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6639 return Bld.getInt32(1); 6640 return Bld.getInt32(0); 6641 } 6642 return nullptr; 6643 } 6644 case OMPD_target_teams: 6645 case OMPD_target_teams_distribute: 6646 case OMPD_target_teams_distribute_simd: 6647 case OMPD_target_teams_distribute_parallel_for: 6648 case OMPD_target_teams_distribute_parallel_for_simd: { 6649 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6650 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6651 const Expr *NumTeams = 6652 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6653 llvm::Value *NumTeamsVal = 6654 CGF.EmitScalarExpr(NumTeams, 6655 /*IgnoreResultAssign*/ true); 6656 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6657 /*isSigned=*/true); 6658 } 6659 return Bld.getInt32(0); 6660 } 6661 case OMPD_target_parallel: 6662 case OMPD_target_parallel_for: 6663 case OMPD_target_parallel_for_simd: 6664 case OMPD_target_simd: 6665 return Bld.getInt32(1); 6666 case OMPD_parallel: 6667 case OMPD_for: 6668 case OMPD_parallel_for: 6669 case OMPD_parallel_master: 6670 case OMPD_parallel_sections: 6671 case OMPD_for_simd: 6672 case OMPD_parallel_for_simd: 6673 case OMPD_cancel: 6674 case OMPD_cancellation_point: 6675 case OMPD_ordered: 6676 case OMPD_threadprivate: 6677 case OMPD_allocate: 6678 case OMPD_task: 6679 case OMPD_simd: 6680 case OMPD_tile: 6681 case OMPD_sections: 6682 case OMPD_section: 6683 case OMPD_single: 6684 case OMPD_master: 6685 case OMPD_critical: 6686 case OMPD_taskyield: 6687 case OMPD_barrier: 6688 case OMPD_taskwait: 6689 case OMPD_taskgroup: 6690 case OMPD_atomic: 6691 case OMPD_flush: 6692 case OMPD_depobj: 6693 case OMPD_scan: 6694 case OMPD_teams: 6695 case OMPD_target_data: 6696 case OMPD_target_exit_data: 6697 case OMPD_target_enter_data: 6698 case OMPD_distribute: 6699 case OMPD_distribute_simd: 6700 case OMPD_distribute_parallel_for: 6701 case OMPD_distribute_parallel_for_simd: 6702 case OMPD_teams_distribute: 6703 case OMPD_teams_distribute_simd: 6704 case OMPD_teams_distribute_parallel_for: 6705 case OMPD_teams_distribute_parallel_for_simd: 6706 case OMPD_target_update: 6707 case OMPD_declare_simd: 6708 case OMPD_declare_variant: 6709 case OMPD_begin_declare_variant: 6710 case OMPD_end_declare_variant: 6711 case OMPD_declare_target: 6712 case OMPD_end_declare_target: 6713 case OMPD_declare_reduction: 6714 case OMPD_declare_mapper: 6715 case OMPD_taskloop: 6716 case OMPD_taskloop_simd: 6717 case OMPD_master_taskloop: 6718 case OMPD_master_taskloop_simd: 6719 case OMPD_parallel_master_taskloop: 6720 case OMPD_parallel_master_taskloop_simd: 6721 case OMPD_requires: 6722 case OMPD_unknown: 6723 break; 6724 default: 6725 break; 6726 } 6727 llvm_unreachable("Unexpected directive kind."); 6728 } 6729 6730 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6731 llvm::Value *DefaultThreadLimitVal) { 6732 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6733 CGF.getContext(), CS->getCapturedStmt()); 6734 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6735 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6736 llvm::Value *NumThreads = nullptr; 6737 llvm::Value *CondVal = nullptr; 6738 // Handle if clause. If if clause present, the number of threads is 6739 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6740 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6741 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6742 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6743 const OMPIfClause *IfClause = nullptr; 6744 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6745 if (C->getNameModifier() == OMPD_unknown || 6746 C->getNameModifier() == OMPD_parallel) { 6747 IfClause = C; 6748 break; 6749 } 6750 } 6751 if (IfClause) { 6752 const Expr *Cond = IfClause->getCondition(); 6753 bool Result; 6754 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6755 if (!Result) 6756 return CGF.Builder.getInt32(1); 6757 } else { 6758 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6759 if (const auto *PreInit = 6760 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6761 for (const auto *I : PreInit->decls()) { 6762 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6763 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6764 } else { 6765 CodeGenFunction::AutoVarEmission Emission = 6766 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6767 CGF.EmitAutoVarCleanups(Emission); 6768 } 6769 } 6770 } 6771 CondVal = CGF.EvaluateExprAsBool(Cond); 6772 } 6773 } 6774 } 6775 // Check the value of num_threads clause iff if clause was not specified 6776 // or is not evaluated to false. 6777 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6778 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6779 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6780 const auto *NumThreadsClause = 6781 Dir->getSingleClause<OMPNumThreadsClause>(); 6782 CodeGenFunction::LexicalScope Scope( 6783 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6784 if (const auto *PreInit = 6785 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6786 for (const auto *I : PreInit->decls()) { 6787 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6788 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6789 } else { 6790 CodeGenFunction::AutoVarEmission Emission = 6791 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6792 CGF.EmitAutoVarCleanups(Emission); 6793 } 6794 } 6795 } 6796 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6797 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6798 /*isSigned=*/false); 6799 if (DefaultThreadLimitVal) 6800 NumThreads = CGF.Builder.CreateSelect( 6801 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6802 DefaultThreadLimitVal, NumThreads); 6803 } else { 6804 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6805 : CGF.Builder.getInt32(0); 6806 } 6807 // Process condition of the if clause. 6808 if (CondVal) { 6809 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6810 CGF.Builder.getInt32(1)); 6811 } 6812 return NumThreads; 6813 } 6814 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6815 return CGF.Builder.getInt32(1); 6816 return DefaultThreadLimitVal; 6817 } 6818 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6819 : CGF.Builder.getInt32(0); 6820 } 6821 6822 /// Emit the number of threads for a target directive. Inspect the 6823 /// thread_limit clause associated with a teams construct combined or closely 6824 /// nested with the target directive. 6825 /// 6826 /// Emit the num_threads clause for directives such as 'target parallel' that 6827 /// have no associated teams construct. 6828 /// 6829 /// Otherwise, return nullptr. 6830 static llvm::Value * 6831 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6832 const OMPExecutableDirective &D) { 6833 assert(!CGF.getLangOpts().OpenMPIsDevice && 6834 "Clauses associated with the teams directive expected to be emitted " 6835 "only for the host!"); 6836 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6837 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6838 "Expected target-based executable directive."); 6839 CGBuilderTy &Bld = CGF.Builder; 6840 llvm::Value *ThreadLimitVal = nullptr; 6841 llvm::Value *NumThreadsVal = nullptr; 6842 switch (DirectiveKind) { 6843 case OMPD_target: { 6844 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6845 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6846 return NumThreads; 6847 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6848 CGF.getContext(), CS->getCapturedStmt()); 6849 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6850 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6851 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6852 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6853 const auto *ThreadLimitClause = 6854 Dir->getSingleClause<OMPThreadLimitClause>(); 6855 CodeGenFunction::LexicalScope Scope( 6856 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6857 if (const auto *PreInit = 6858 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6859 for (const auto *I : PreInit->decls()) { 6860 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6861 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6862 } else { 6863 CodeGenFunction::AutoVarEmission Emission = 6864 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6865 CGF.EmitAutoVarCleanups(Emission); 6866 } 6867 } 6868 } 6869 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6870 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6871 ThreadLimitVal = 6872 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6873 } 6874 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6875 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6876 CS = Dir->getInnermostCapturedStmt(); 6877 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6878 CGF.getContext(), CS->getCapturedStmt()); 6879 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6880 } 6881 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6882 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6883 CS = Dir->getInnermostCapturedStmt(); 6884 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6885 return NumThreads; 6886 } 6887 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6888 return Bld.getInt32(1); 6889 } 6890 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6891 } 6892 case OMPD_target_teams: { 6893 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6894 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6895 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6896 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6897 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6898 ThreadLimitVal = 6899 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6900 } 6901 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6902 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6903 return NumThreads; 6904 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6905 CGF.getContext(), CS->getCapturedStmt()); 6906 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6907 if (Dir->getDirectiveKind() == OMPD_distribute) { 6908 CS = Dir->getInnermostCapturedStmt(); 6909 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6910 return NumThreads; 6911 } 6912 } 6913 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6914 } 6915 case OMPD_target_teams_distribute: 6916 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6917 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6918 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6919 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6920 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6921 ThreadLimitVal = 6922 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6923 } 6924 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6925 case OMPD_target_parallel: 6926 case OMPD_target_parallel_for: 6927 case OMPD_target_parallel_for_simd: 6928 case OMPD_target_teams_distribute_parallel_for: 6929 case OMPD_target_teams_distribute_parallel_for_simd: { 6930 llvm::Value *CondVal = nullptr; 6931 // Handle if clause. If if clause present, the number of threads is 6932 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6933 if (D.hasClausesOfKind<OMPIfClause>()) { 6934 const OMPIfClause *IfClause = nullptr; 6935 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6936 if (C->getNameModifier() == OMPD_unknown || 6937 C->getNameModifier() == OMPD_parallel) { 6938 IfClause = C; 6939 break; 6940 } 6941 } 6942 if (IfClause) { 6943 const Expr *Cond = IfClause->getCondition(); 6944 bool Result; 6945 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6946 if (!Result) 6947 return Bld.getInt32(1); 6948 } else { 6949 CodeGenFunction::RunCleanupsScope Scope(CGF); 6950 CondVal = CGF.EvaluateExprAsBool(Cond); 6951 } 6952 } 6953 } 6954 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6955 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6956 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6957 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6958 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6959 ThreadLimitVal = 6960 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6961 } 6962 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6963 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6964 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6965 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6966 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6967 NumThreadsVal = 6968 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6969 ThreadLimitVal = ThreadLimitVal 6970 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6971 ThreadLimitVal), 6972 NumThreadsVal, ThreadLimitVal) 6973 : NumThreadsVal; 6974 } 6975 if (!ThreadLimitVal) 6976 ThreadLimitVal = Bld.getInt32(0); 6977 if (CondVal) 6978 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6979 return ThreadLimitVal; 6980 } 6981 case OMPD_target_teams_distribute_simd: 6982 case OMPD_target_simd: 6983 return Bld.getInt32(1); 6984 case OMPD_parallel: 6985 case OMPD_for: 6986 case OMPD_parallel_for: 6987 case OMPD_parallel_master: 6988 case OMPD_parallel_sections: 6989 case OMPD_for_simd: 6990 case OMPD_parallel_for_simd: 6991 case OMPD_cancel: 6992 case OMPD_cancellation_point: 6993 case OMPD_ordered: 6994 case OMPD_threadprivate: 6995 case OMPD_allocate: 6996 case OMPD_task: 6997 case OMPD_simd: 6998 case OMPD_tile: 6999 case OMPD_sections: 7000 case OMPD_section: 7001 case OMPD_single: 7002 case OMPD_master: 7003 case OMPD_critical: 7004 case OMPD_taskyield: 7005 case OMPD_barrier: 7006 case OMPD_taskwait: 7007 case OMPD_taskgroup: 7008 case OMPD_atomic: 7009 case OMPD_flush: 7010 case OMPD_depobj: 7011 case OMPD_scan: 7012 case OMPD_teams: 7013 case OMPD_target_data: 7014 case OMPD_target_exit_data: 7015 case OMPD_target_enter_data: 7016 case OMPD_distribute: 7017 case OMPD_distribute_simd: 7018 case OMPD_distribute_parallel_for: 7019 case OMPD_distribute_parallel_for_simd: 7020 case OMPD_teams_distribute: 7021 case OMPD_teams_distribute_simd: 7022 case OMPD_teams_distribute_parallel_for: 7023 case OMPD_teams_distribute_parallel_for_simd: 7024 case OMPD_target_update: 7025 case OMPD_declare_simd: 7026 case OMPD_declare_variant: 7027 case OMPD_begin_declare_variant: 7028 case OMPD_end_declare_variant: 7029 case OMPD_declare_target: 7030 case OMPD_end_declare_target: 7031 case OMPD_declare_reduction: 7032 case OMPD_declare_mapper: 7033 case OMPD_taskloop: 7034 case OMPD_taskloop_simd: 7035 case OMPD_master_taskloop: 7036 case OMPD_master_taskloop_simd: 7037 case OMPD_parallel_master_taskloop: 7038 case OMPD_parallel_master_taskloop_simd: 7039 case OMPD_requires: 7040 case OMPD_unknown: 7041 break; 7042 default: 7043 break; 7044 } 7045 llvm_unreachable("Unsupported directive kind."); 7046 } 7047 7048 namespace { 7049 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7050 7051 // Utility to handle information from clauses associated with a given 7052 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7053 // It provides a convenient interface to obtain the information and generate 7054 // code for that information. 7055 class MappableExprsHandler { 7056 public: 7057 /// Values for bit flags used to specify the mapping type for 7058 /// offloading. 7059 enum OpenMPOffloadMappingFlags : uint64_t { 7060 /// No flags 7061 OMP_MAP_NONE = 0x0, 7062 /// Allocate memory on the device and move data from host to device. 7063 OMP_MAP_TO = 0x01, 7064 /// Allocate memory on the device and move data from device to host. 7065 OMP_MAP_FROM = 0x02, 7066 /// Always perform the requested mapping action on the element, even 7067 /// if it was already mapped before. 7068 OMP_MAP_ALWAYS = 0x04, 7069 /// Delete the element from the device environment, ignoring the 7070 /// current reference count associated with the element. 7071 OMP_MAP_DELETE = 0x08, 7072 /// The element being mapped is a pointer-pointee pair; both the 7073 /// pointer and the pointee should be mapped. 7074 OMP_MAP_PTR_AND_OBJ = 0x10, 7075 /// This flags signals that the base address of an entry should be 7076 /// passed to the target kernel as an argument. 7077 OMP_MAP_TARGET_PARAM = 0x20, 7078 /// Signal that the runtime library has to return the device pointer 7079 /// in the current position for the data being mapped. Used when we have the 7080 /// use_device_ptr or use_device_addr clause. 7081 OMP_MAP_RETURN_PARAM = 0x40, 7082 /// This flag signals that the reference being passed is a pointer to 7083 /// private data. 7084 OMP_MAP_PRIVATE = 0x80, 7085 /// Pass the element to the device by value. 7086 OMP_MAP_LITERAL = 0x100, 7087 /// Implicit map 7088 OMP_MAP_IMPLICIT = 0x200, 7089 /// Close is a hint to the runtime to allocate memory close to 7090 /// the target device. 7091 OMP_MAP_CLOSE = 0x400, 7092 /// 0x800 is reserved for compatibility with XLC. 7093 /// Produce a runtime error if the data is not already allocated. 7094 OMP_MAP_PRESENT = 0x1000, 7095 /// Signal that the runtime library should use args as an array of 7096 /// descriptor_dim pointers and use args_size as dims. Used when we have 7097 /// non-contiguous list items in target update directive 7098 OMP_MAP_NON_CONTIG = 0x100000000000, 7099 /// The 16 MSBs of the flags indicate whether the entry is member of some 7100 /// struct/class. 7101 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7102 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7103 }; 7104 7105 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7106 static unsigned getFlagMemberOffset() { 7107 unsigned Offset = 0; 7108 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7109 Remain = Remain >> 1) 7110 Offset++; 7111 return Offset; 7112 } 7113 7114 /// Class that holds debugging information for a data mapping to be passed to 7115 /// the runtime library. 7116 class MappingExprInfo { 7117 /// The variable declaration used for the data mapping. 7118 const ValueDecl *MapDecl = nullptr; 7119 /// The original expression used in the map clause, or null if there is 7120 /// none. 7121 const Expr *MapExpr = nullptr; 7122 7123 public: 7124 MappingExprInfo(const ValueDecl *MapDecl, const Expr *MapExpr = nullptr) 7125 : MapDecl(MapDecl), MapExpr(MapExpr) {} 7126 7127 const ValueDecl *getMapDecl() const { return MapDecl; } 7128 const Expr *getMapExpr() const { return MapExpr; } 7129 }; 7130 7131 /// Class that associates information with a base pointer to be passed to the 7132 /// runtime library. 7133 class BasePointerInfo { 7134 /// The base pointer. 7135 llvm::Value *Ptr = nullptr; 7136 /// The base declaration that refers to this device pointer, or null if 7137 /// there is none. 7138 const ValueDecl *DevPtrDecl = nullptr; 7139 7140 public: 7141 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7142 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7143 llvm::Value *operator*() const { return Ptr; } 7144 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7145 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7146 }; 7147 7148 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>; 7149 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7150 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7151 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7152 using MapMappersArrayTy = SmallVector<const ValueDecl *, 4>; 7153 using MapDimArrayTy = SmallVector<uint64_t, 4>; 7154 using MapNonContiguousArrayTy = SmallVector<MapValuesArrayTy, 4>; 7155 7156 /// This structure contains combined information generated for mappable 7157 /// clauses, including base pointers, pointers, sizes, map types, user-defined 7158 /// mappers, and non-contiguous information. 7159 struct MapCombinedInfoTy { 7160 struct StructNonContiguousInfo { 7161 bool IsNonContiguous = false; 7162 MapDimArrayTy Dims; 7163 MapNonContiguousArrayTy Offsets; 7164 MapNonContiguousArrayTy Counts; 7165 MapNonContiguousArrayTy Strides; 7166 }; 7167 MapExprsArrayTy Exprs; 7168 MapBaseValuesArrayTy BasePointers; 7169 MapValuesArrayTy Pointers; 7170 MapValuesArrayTy Sizes; 7171 MapFlagsArrayTy Types; 7172 MapMappersArrayTy Mappers; 7173 StructNonContiguousInfo NonContigInfo; 7174 7175 /// Append arrays in \a CurInfo. 7176 void append(MapCombinedInfoTy &CurInfo) { 7177 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end()); 7178 BasePointers.append(CurInfo.BasePointers.begin(), 7179 CurInfo.BasePointers.end()); 7180 Pointers.append(CurInfo.Pointers.begin(), CurInfo.Pointers.end()); 7181 Sizes.append(CurInfo.Sizes.begin(), CurInfo.Sizes.end()); 7182 Types.append(CurInfo.Types.begin(), CurInfo.Types.end()); 7183 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end()); 7184 NonContigInfo.Dims.append(CurInfo.NonContigInfo.Dims.begin(), 7185 CurInfo.NonContigInfo.Dims.end()); 7186 NonContigInfo.Offsets.append(CurInfo.NonContigInfo.Offsets.begin(), 7187 CurInfo.NonContigInfo.Offsets.end()); 7188 NonContigInfo.Counts.append(CurInfo.NonContigInfo.Counts.begin(), 7189 CurInfo.NonContigInfo.Counts.end()); 7190 NonContigInfo.Strides.append(CurInfo.NonContigInfo.Strides.begin(), 7191 CurInfo.NonContigInfo.Strides.end()); 7192 } 7193 }; 7194 7195 /// Map between a struct and the its lowest & highest elements which have been 7196 /// mapped. 7197 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7198 /// HE(FieldIndex, Pointer)} 7199 struct StructRangeInfoTy { 7200 MapCombinedInfoTy PreliminaryMapData; 7201 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7202 0, Address::invalid()}; 7203 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7204 0, Address::invalid()}; 7205 Address Base = Address::invalid(); 7206 Address LB = Address::invalid(); 7207 bool IsArraySection = false; 7208 bool HasCompleteRecord = false; 7209 }; 7210 7211 private: 7212 /// Kind that defines how a device pointer has to be returned. 7213 struct MapInfo { 7214 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7215 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7216 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7217 ArrayRef<OpenMPMotionModifierKind> MotionModifiers; 7218 bool ReturnDevicePointer = false; 7219 bool IsImplicit = false; 7220 const ValueDecl *Mapper = nullptr; 7221 const Expr *VarRef = nullptr; 7222 bool ForDeviceAddr = false; 7223 7224 MapInfo() = default; 7225 MapInfo( 7226 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7227 OpenMPMapClauseKind MapType, 7228 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7229 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7230 bool ReturnDevicePointer, bool IsImplicit, 7231 const ValueDecl *Mapper = nullptr, const Expr *VarRef = nullptr, 7232 bool ForDeviceAddr = false) 7233 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7234 MotionModifiers(MotionModifiers), 7235 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit), 7236 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {} 7237 }; 7238 7239 /// If use_device_ptr or use_device_addr is used on a decl which is a struct 7240 /// member and there is no map information about it, then emission of that 7241 /// entry is deferred until the whole struct has been processed. 7242 struct DeferredDevicePtrEntryTy { 7243 const Expr *IE = nullptr; 7244 const ValueDecl *VD = nullptr; 7245 bool ForDeviceAddr = false; 7246 7247 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD, 7248 bool ForDeviceAddr) 7249 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {} 7250 }; 7251 7252 /// The target directive from where the mappable clauses were extracted. It 7253 /// is either a executable directive or a user-defined mapper directive. 7254 llvm::PointerUnion<const OMPExecutableDirective *, 7255 const OMPDeclareMapperDecl *> 7256 CurDir; 7257 7258 /// Function the directive is being generated for. 7259 CodeGenFunction &CGF; 7260 7261 /// Set of all first private variables in the current directive. 7262 /// bool data is set to true if the variable is implicitly marked as 7263 /// firstprivate, false otherwise. 7264 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7265 7266 /// Map between device pointer declarations and their expression components. 7267 /// The key value for declarations in 'this' is null. 7268 llvm::DenseMap< 7269 const ValueDecl *, 7270 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7271 DevPointersMap; 7272 7273 llvm::Value *getExprTypeSize(const Expr *E) const { 7274 QualType ExprTy = E->getType().getCanonicalType(); 7275 7276 // Calculate the size for array shaping expression. 7277 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) { 7278 llvm::Value *Size = 7279 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType()); 7280 for (const Expr *SE : OAE->getDimensions()) { 7281 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 7282 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 7283 CGF.getContext().getSizeType(), 7284 SE->getExprLoc()); 7285 Size = CGF.Builder.CreateNUWMul(Size, Sz); 7286 } 7287 return Size; 7288 } 7289 7290 // Reference types are ignored for mapping purposes. 7291 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7292 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7293 7294 // Given that an array section is considered a built-in type, we need to 7295 // do the calculation based on the length of the section instead of relying 7296 // on CGF.getTypeSize(E->getType()). 7297 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7298 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7299 OAE->getBase()->IgnoreParenImpCasts()) 7300 .getCanonicalType(); 7301 7302 // If there is no length associated with the expression and lower bound is 7303 // not specified too, that means we are using the whole length of the 7304 // base. 7305 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7306 !OAE->getLowerBound()) 7307 return CGF.getTypeSize(BaseTy); 7308 7309 llvm::Value *ElemSize; 7310 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7311 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7312 } else { 7313 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7314 assert(ATy && "Expecting array type if not a pointer type."); 7315 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7316 } 7317 7318 // If we don't have a length at this point, that is because we have an 7319 // array section with a single element. 7320 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid()) 7321 return ElemSize; 7322 7323 if (const Expr *LenExpr = OAE->getLength()) { 7324 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7325 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7326 CGF.getContext().getSizeType(), 7327 LenExpr->getExprLoc()); 7328 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7329 } 7330 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7331 OAE->getLowerBound() && "expected array_section[lb:]."); 7332 // Size = sizetype - lb * elemtype; 7333 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7334 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7335 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7336 CGF.getContext().getSizeType(), 7337 OAE->getLowerBound()->getExprLoc()); 7338 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7339 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7340 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7341 LengthVal = CGF.Builder.CreateSelect( 7342 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7343 return LengthVal; 7344 } 7345 return CGF.getTypeSize(ExprTy); 7346 } 7347 7348 /// Return the corresponding bits for a given map clause modifier. Add 7349 /// a flag marking the map as a pointer if requested. Add a flag marking the 7350 /// map as the first one of a series of maps that relate to the same map 7351 /// expression. 7352 OpenMPOffloadMappingFlags getMapTypeBits( 7353 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7354 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit, 7355 bool AddPtrFlag, bool AddIsTargetParamFlag, bool IsNonContiguous) const { 7356 OpenMPOffloadMappingFlags Bits = 7357 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7358 switch (MapType) { 7359 case OMPC_MAP_alloc: 7360 case OMPC_MAP_release: 7361 // alloc and release is the default behavior in the runtime library, i.e. 7362 // if we don't pass any bits alloc/release that is what the runtime is 7363 // going to do. Therefore, we don't need to signal anything for these two 7364 // type modifiers. 7365 break; 7366 case OMPC_MAP_to: 7367 Bits |= OMP_MAP_TO; 7368 break; 7369 case OMPC_MAP_from: 7370 Bits |= OMP_MAP_FROM; 7371 break; 7372 case OMPC_MAP_tofrom: 7373 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7374 break; 7375 case OMPC_MAP_delete: 7376 Bits |= OMP_MAP_DELETE; 7377 break; 7378 case OMPC_MAP_unknown: 7379 llvm_unreachable("Unexpected map type!"); 7380 } 7381 if (AddPtrFlag) 7382 Bits |= OMP_MAP_PTR_AND_OBJ; 7383 if (AddIsTargetParamFlag) 7384 Bits |= OMP_MAP_TARGET_PARAM; 7385 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7386 != MapModifiers.end()) 7387 Bits |= OMP_MAP_ALWAYS; 7388 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7389 != MapModifiers.end()) 7390 Bits |= OMP_MAP_CLOSE; 7391 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_present) != 7392 MapModifiers.end() || 7393 llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present) != 7394 MotionModifiers.end()) 7395 Bits |= OMP_MAP_PRESENT; 7396 if (IsNonContiguous) 7397 Bits |= OMP_MAP_NON_CONTIG; 7398 return Bits; 7399 } 7400 7401 /// Return true if the provided expression is a final array section. A 7402 /// final array section, is one whose length can't be proved to be one. 7403 bool isFinalArraySectionExpression(const Expr *E) const { 7404 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7405 7406 // It is not an array section and therefore not a unity-size one. 7407 if (!OASE) 7408 return false; 7409 7410 // An array section with no colon always refer to a single element. 7411 if (OASE->getColonLocFirst().isInvalid()) 7412 return false; 7413 7414 const Expr *Length = OASE->getLength(); 7415 7416 // If we don't have a length we have to check if the array has size 1 7417 // for this dimension. Also, we should always expect a length if the 7418 // base type is pointer. 7419 if (!Length) { 7420 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7421 OASE->getBase()->IgnoreParenImpCasts()) 7422 .getCanonicalType(); 7423 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7424 return ATy->getSize().getSExtValue() != 1; 7425 // If we don't have a constant dimension length, we have to consider 7426 // the current section as having any size, so it is not necessarily 7427 // unitary. If it happen to be unity size, that's user fault. 7428 return true; 7429 } 7430 7431 // Check if the length evaluates to 1. 7432 Expr::EvalResult Result; 7433 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7434 return true; // Can have more that size 1. 7435 7436 llvm::APSInt ConstLength = Result.Val.getInt(); 7437 return ConstLength.getSExtValue() != 1; 7438 } 7439 7440 /// Generate the base pointers, section pointers, sizes, map type bits, and 7441 /// user-defined mappers (all included in \a CombinedInfo) for the provided 7442 /// map type, map or motion modifiers, and expression components. 7443 /// \a IsFirstComponent should be set to true if the provided set of 7444 /// components is the first associated with a capture. 7445 void generateInfoForComponentList( 7446 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7447 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7448 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7449 MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct, 7450 bool IsFirstComponentList, bool IsImplicit, 7451 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false, 7452 const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr, 7453 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7454 OverlappedElements = llvm::None) const { 7455 // The following summarizes what has to be generated for each map and the 7456 // types below. The generated information is expressed in this order: 7457 // base pointer, section pointer, size, flags 7458 // (to add to the ones that come from the map type and modifier). 7459 // 7460 // double d; 7461 // int i[100]; 7462 // float *p; 7463 // 7464 // struct S1 { 7465 // int i; 7466 // float f[50]; 7467 // } 7468 // struct S2 { 7469 // int i; 7470 // float f[50]; 7471 // S1 s; 7472 // double *p; 7473 // struct S2 *ps; 7474 // int &ref; 7475 // } 7476 // S2 s; 7477 // S2 *ps; 7478 // 7479 // map(d) 7480 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7481 // 7482 // map(i) 7483 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7484 // 7485 // map(i[1:23]) 7486 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7487 // 7488 // map(p) 7489 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7490 // 7491 // map(p[1:24]) 7492 // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ 7493 // in unified shared memory mode or for local pointers 7494 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7495 // 7496 // map(s) 7497 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7498 // 7499 // map(s.i) 7500 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7501 // 7502 // map(s.s.f) 7503 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7504 // 7505 // map(s.p) 7506 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7507 // 7508 // map(to: s.p[:22]) 7509 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7510 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7511 // &(s.p), &(s.p[0]), 22*sizeof(double), 7512 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7513 // (*) alloc space for struct members, only this is a target parameter 7514 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7515 // optimizes this entry out, same in the examples below) 7516 // (***) map the pointee (map: to) 7517 // 7518 // map(to: s.ref) 7519 // &s, &(s.ref), sizeof(int*), TARGET_PARAM (*) 7520 // &s, &(s.ref), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7521 // (*) alloc space for struct members, only this is a target parameter 7522 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7523 // optimizes this entry out, same in the examples below) 7524 // (***) map the pointee (map: to) 7525 // 7526 // map(s.ps) 7527 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7528 // 7529 // map(from: s.ps->s.i) 7530 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7531 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7532 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7533 // 7534 // map(to: s.ps->ps) 7535 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7536 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7537 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7538 // 7539 // map(s.ps->ps->ps) 7540 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7541 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7542 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7543 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7544 // 7545 // map(to: s.ps->ps->s.f[:22]) 7546 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7547 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7548 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7549 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7550 // 7551 // map(ps) 7552 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7553 // 7554 // map(ps->i) 7555 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7556 // 7557 // map(ps->s.f) 7558 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7559 // 7560 // map(from: ps->p) 7561 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7562 // 7563 // map(to: ps->p[:22]) 7564 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7565 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7566 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7567 // 7568 // map(ps->ps) 7569 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7570 // 7571 // map(from: ps->ps->s.i) 7572 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7573 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7574 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7575 // 7576 // map(from: ps->ps->ps) 7577 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7578 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7579 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7580 // 7581 // map(ps->ps->ps->ps) 7582 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7583 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7584 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7585 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7586 // 7587 // map(to: ps->ps->ps->s.f[:22]) 7588 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7589 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7590 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7591 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7592 // 7593 // map(to: s.f[:22]) map(from: s.p[:33]) 7594 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7595 // sizeof(double*) (**), TARGET_PARAM 7596 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7597 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7598 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7599 // (*) allocate contiguous space needed to fit all mapped members even if 7600 // we allocate space for members not mapped (in this example, 7601 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7602 // them as well because they fall between &s.f[0] and &s.p) 7603 // 7604 // map(from: s.f[:22]) map(to: ps->p[:33]) 7605 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7606 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7607 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7608 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7609 // (*) the struct this entry pertains to is the 2nd element in the list of 7610 // arguments, hence MEMBER_OF(2) 7611 // 7612 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7613 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7614 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7615 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7616 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7617 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7618 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7619 // (*) the struct this entry pertains to is the 4th element in the list 7620 // of arguments, hence MEMBER_OF(4) 7621 7622 // Track if the map information being generated is the first for a capture. 7623 bool IsCaptureFirstInfo = IsFirstComponentList; 7624 // When the variable is on a declare target link or in a to clause with 7625 // unified memory, a reference is needed to hold the host/device address 7626 // of the variable. 7627 bool RequiresReference = false; 7628 7629 // Scan the components from the base to the complete expression. 7630 auto CI = Components.rbegin(); 7631 auto CE = Components.rend(); 7632 auto I = CI; 7633 7634 // Track if the map information being generated is the first for a list of 7635 // components. 7636 bool IsExpressionFirstInfo = true; 7637 bool FirstPointerInComplexData = false; 7638 Address BP = Address::invalid(); 7639 const Expr *AssocExpr = I->getAssociatedExpression(); 7640 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7641 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7642 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr); 7643 7644 if (isa<MemberExpr>(AssocExpr)) { 7645 // The base is the 'this' pointer. The content of the pointer is going 7646 // to be the base of the field being mapped. 7647 BP = CGF.LoadCXXThisAddress(); 7648 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7649 (OASE && 7650 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7651 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7652 } else if (OAShE && 7653 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) { 7654 BP = Address( 7655 CGF.EmitScalarExpr(OAShE->getBase()), 7656 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType())); 7657 } else { 7658 // The base is the reference to the variable. 7659 // BP = &Var. 7660 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7661 if (const auto *VD = 7662 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7663 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7664 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7665 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7666 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7667 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7668 RequiresReference = true; 7669 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7670 } 7671 } 7672 } 7673 7674 // If the variable is a pointer and is being dereferenced (i.e. is not 7675 // the last component), the base has to be the pointer itself, not its 7676 // reference. References are ignored for mapping purposes. 7677 QualType Ty = 7678 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7679 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7680 // No need to generate individual map information for the pointer, it 7681 // can be associated with the combined storage if shared memory mode is 7682 // active or the base declaration is not global variable. 7683 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration()); 7684 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 7685 !VD || VD->hasLocalStorage()) 7686 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7687 else 7688 FirstPointerInComplexData = true; 7689 ++I; 7690 } 7691 } 7692 7693 // Track whether a component of the list should be marked as MEMBER_OF some 7694 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7695 // in a component list should be marked as MEMBER_OF, all subsequent entries 7696 // do not belong to the base struct. E.g. 7697 // struct S2 s; 7698 // s.ps->ps->ps->f[:] 7699 // (1) (2) (3) (4) 7700 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7701 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7702 // is the pointee of ps(2) which is not member of struct s, so it should not 7703 // be marked as such (it is still PTR_AND_OBJ). 7704 // The variable is initialized to false so that PTR_AND_OBJ entries which 7705 // are not struct members are not considered (e.g. array of pointers to 7706 // data). 7707 bool ShouldBeMemberOf = false; 7708 7709 // Variable keeping track of whether or not we have encountered a component 7710 // in the component list which is a member expression. Useful when we have a 7711 // pointer or a final array section, in which case it is the previous 7712 // component in the list which tells us whether we have a member expression. 7713 // E.g. X.f[:] 7714 // While processing the final array section "[:]" it is "f" which tells us 7715 // whether we are dealing with a member of a declared struct. 7716 const MemberExpr *EncounteredME = nullptr; 7717 7718 // Track for the total number of dimension. Start from one for the dummy 7719 // dimension. 7720 uint64_t DimSize = 1; 7721 7722 bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous; 7723 bool IsPrevMemberReference = false; 7724 7725 for (; I != CE; ++I) { 7726 // If the current component is member of a struct (parent struct) mark it. 7727 if (!EncounteredME) { 7728 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7729 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7730 // as MEMBER_OF the parent struct. 7731 if (EncounteredME) { 7732 ShouldBeMemberOf = true; 7733 // Do not emit as complex pointer if this is actually not array-like 7734 // expression. 7735 if (FirstPointerInComplexData) { 7736 QualType Ty = std::prev(I) 7737 ->getAssociatedDeclaration() 7738 ->getType() 7739 .getNonReferenceType(); 7740 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7741 FirstPointerInComplexData = false; 7742 } 7743 } 7744 } 7745 7746 auto Next = std::next(I); 7747 7748 // We need to generate the addresses and sizes if this is the last 7749 // component, if the component is a pointer or if it is an array section 7750 // whose length can't be proved to be one. If this is a pointer, it 7751 // becomes the base address for the following components. 7752 7753 // A final array section, is one whose length can't be proved to be one. 7754 // If the map item is non-contiguous then we don't treat any array section 7755 // as final array section. 7756 bool IsFinalArraySection = 7757 !IsNonContiguous && 7758 isFinalArraySectionExpression(I->getAssociatedExpression()); 7759 7760 // If we have a declaration for the mapping use that, otherwise use 7761 // the base declaration of the map clause. 7762 const ValueDecl *MapDecl = (I->getAssociatedDeclaration()) 7763 ? I->getAssociatedDeclaration() 7764 : BaseDecl; 7765 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression() 7766 : MapExpr; 7767 7768 // Get information on whether the element is a pointer. Have to do a 7769 // special treatment for array sections given that they are built-in 7770 // types. 7771 const auto *OASE = 7772 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7773 const auto *OAShE = 7774 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression()); 7775 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 7776 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 7777 bool IsPointer = 7778 OAShE || 7779 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7780 .getCanonicalType() 7781 ->isAnyPointerType()) || 7782 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7783 bool IsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) && 7784 MapDecl && 7785 MapDecl->getType()->isLValueReferenceType(); 7786 bool IsNonDerefPointer = IsPointer && !UO && !BO && !IsNonContiguous; 7787 7788 if (OASE) 7789 ++DimSize; 7790 7791 if (Next == CE || IsMemberReference || IsNonDerefPointer || 7792 IsFinalArraySection) { 7793 // If this is not the last component, we expect the pointer to be 7794 // associated with an array expression or member expression. 7795 assert((Next == CE || 7796 isa<MemberExpr>(Next->getAssociatedExpression()) || 7797 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7798 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 7799 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || 7800 isa<UnaryOperator>(Next->getAssociatedExpression()) || 7801 isa<BinaryOperator>(Next->getAssociatedExpression())) && 7802 "Unexpected expression"); 7803 7804 Address LB = Address::invalid(); 7805 Address LowestElem = Address::invalid(); 7806 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF, 7807 const MemberExpr *E) { 7808 const Expr *BaseExpr = E->getBase(); 7809 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a 7810 // scalar. 7811 LValue BaseLV; 7812 if (E->isArrow()) { 7813 LValueBaseInfo BaseInfo; 7814 TBAAAccessInfo TBAAInfo; 7815 Address Addr = 7816 CGF.EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo); 7817 QualType PtrTy = BaseExpr->getType()->getPointeeType(); 7818 BaseLV = CGF.MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); 7819 } else { 7820 BaseLV = CGF.EmitOMPSharedLValue(BaseExpr); 7821 } 7822 return BaseLV; 7823 }; 7824 if (OAShE) { 7825 LowestElem = LB = Address(CGF.EmitScalarExpr(OAShE->getBase()), 7826 CGF.getContext().getTypeAlignInChars( 7827 OAShE->getBase()->getType())); 7828 } else if (IsMemberReference) { 7829 const auto *ME = cast<MemberExpr>(I->getAssociatedExpression()); 7830 LValue BaseLVal = EmitMemberExprBase(CGF, ME); 7831 LowestElem = CGF.EmitLValueForFieldInitialization( 7832 BaseLVal, cast<FieldDecl>(MapDecl)) 7833 .getAddress(CGF); 7834 LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType()) 7835 .getAddress(CGF); 7836 } else { 7837 LowestElem = LB = 7838 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7839 .getAddress(CGF); 7840 } 7841 7842 // If this component is a pointer inside the base struct then we don't 7843 // need to create any entry for it - it will be combined with the object 7844 // it is pointing to into a single PTR_AND_OBJ entry. 7845 bool IsMemberPointerOrAddr = 7846 EncounteredME && 7847 (((IsPointer || ForDeviceAddr) && 7848 I->getAssociatedExpression() == EncounteredME) || 7849 (IsPrevMemberReference && !IsPointer) || 7850 (IsMemberReference && Next != CE && 7851 !Next->getAssociatedExpression()->getType()->isPointerType())); 7852 if (!OverlappedElements.empty() && Next == CE) { 7853 // Handle base element with the info for overlapped elements. 7854 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7855 assert(!IsPointer && 7856 "Unexpected base element with the pointer type."); 7857 // Mark the whole struct as the struct that requires allocation on the 7858 // device. 7859 PartialStruct.LowestElem = {0, LowestElem}; 7860 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7861 I->getAssociatedExpression()->getType()); 7862 Address HB = CGF.Builder.CreateConstGEP( 7863 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LowestElem, 7864 CGF.VoidPtrTy), 7865 TypeSize.getQuantity() - 1); 7866 PartialStruct.HighestElem = { 7867 std::numeric_limits<decltype( 7868 PartialStruct.HighestElem.first)>::max(), 7869 HB}; 7870 PartialStruct.Base = BP; 7871 PartialStruct.LB = LB; 7872 assert( 7873 PartialStruct.PreliminaryMapData.BasePointers.empty() && 7874 "Overlapped elements must be used only once for the variable."); 7875 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo); 7876 // Emit data for non-overlapped data. 7877 OpenMPOffloadMappingFlags Flags = 7878 OMP_MAP_MEMBER_OF | 7879 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, 7880 /*AddPtrFlag=*/false, 7881 /*AddIsTargetParamFlag=*/false, IsNonContiguous); 7882 llvm::Value *Size = nullptr; 7883 // Do bitcopy of all non-overlapped structure elements. 7884 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7885 Component : OverlappedElements) { 7886 Address ComponentLB = Address::invalid(); 7887 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7888 Component) { 7889 if (const ValueDecl *VD = MC.getAssociatedDeclaration()) { 7890 const auto *FD = dyn_cast<FieldDecl>(VD); 7891 if (FD && FD->getType()->isLValueReferenceType()) { 7892 const auto *ME = 7893 cast<MemberExpr>(MC.getAssociatedExpression()); 7894 LValue BaseLVal = EmitMemberExprBase(CGF, ME); 7895 ComponentLB = 7896 CGF.EmitLValueForFieldInitialization(BaseLVal, FD) 7897 .getAddress(CGF); 7898 } else { 7899 ComponentLB = 7900 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7901 .getAddress(CGF); 7902 } 7903 Size = CGF.Builder.CreatePtrDiff( 7904 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7905 CGF.EmitCastToVoidPtr(LB.getPointer())); 7906 break; 7907 } 7908 } 7909 assert(Size && "Failed to determine structure size"); 7910 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 7911 CombinedInfo.BasePointers.push_back(BP.getPointer()); 7912 CombinedInfo.Pointers.push_back(LB.getPointer()); 7913 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 7914 Size, CGF.Int64Ty, /*isSigned=*/true)); 7915 CombinedInfo.Types.push_back(Flags); 7916 CombinedInfo.Mappers.push_back(nullptr); 7917 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 7918 : 1); 7919 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7920 } 7921 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 7922 CombinedInfo.BasePointers.push_back(BP.getPointer()); 7923 CombinedInfo.Pointers.push_back(LB.getPointer()); 7924 Size = CGF.Builder.CreatePtrDiff( 7925 CGF.Builder.CreateConstGEP(HB, 1).getPointer(), 7926 CGF.EmitCastToVoidPtr(LB.getPointer())); 7927 CombinedInfo.Sizes.push_back( 7928 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7929 CombinedInfo.Types.push_back(Flags); 7930 CombinedInfo.Mappers.push_back(nullptr); 7931 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 7932 : 1); 7933 break; 7934 } 7935 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7936 if (!IsMemberPointerOrAddr || 7937 (Next == CE && MapType != OMPC_MAP_unknown)) { 7938 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 7939 CombinedInfo.BasePointers.push_back(BP.getPointer()); 7940 CombinedInfo.Pointers.push_back(LB.getPointer()); 7941 CombinedInfo.Sizes.push_back( 7942 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7943 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 7944 : 1); 7945 7946 // If Mapper is valid, the last component inherits the mapper. 7947 bool HasMapper = Mapper && Next == CE; 7948 CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr); 7949 7950 // We need to add a pointer flag for each map that comes from the 7951 // same expression except for the first one. We also need to signal 7952 // this map is the first one that relates with the current capture 7953 // (there is a set of entries for each capture). 7954 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7955 MapType, MapModifiers, MotionModifiers, IsImplicit, 7956 !IsExpressionFirstInfo || RequiresReference || 7957 FirstPointerInComplexData || IsMemberReference, 7958 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous); 7959 7960 if (!IsExpressionFirstInfo || IsMemberReference) { 7961 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7962 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7963 if (IsPointer || (IsMemberReference && Next != CE)) 7964 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7965 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7966 7967 if (ShouldBeMemberOf) { 7968 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7969 // should be later updated with the correct value of MEMBER_OF. 7970 Flags |= OMP_MAP_MEMBER_OF; 7971 // From now on, all subsequent PTR_AND_OBJ entries should not be 7972 // marked as MEMBER_OF. 7973 ShouldBeMemberOf = false; 7974 } 7975 } 7976 7977 CombinedInfo.Types.push_back(Flags); 7978 } 7979 7980 // If we have encountered a member expression so far, keep track of the 7981 // mapped member. If the parent is "*this", then the value declaration 7982 // is nullptr. 7983 if (EncounteredME) { 7984 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 7985 unsigned FieldIndex = FD->getFieldIndex(); 7986 7987 // Update info about the lowest and highest elements for this struct 7988 if (!PartialStruct.Base.isValid()) { 7989 PartialStruct.LowestElem = {FieldIndex, LowestElem}; 7990 if (IsFinalArraySection) { 7991 Address HB = 7992 CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false) 7993 .getAddress(CGF); 7994 PartialStruct.HighestElem = {FieldIndex, HB}; 7995 } else { 7996 PartialStruct.HighestElem = {FieldIndex, LowestElem}; 7997 } 7998 PartialStruct.Base = BP; 7999 PartialStruct.LB = BP; 8000 } else if (FieldIndex < PartialStruct.LowestElem.first) { 8001 PartialStruct.LowestElem = {FieldIndex, LowestElem}; 8002 } else if (FieldIndex > PartialStruct.HighestElem.first) { 8003 PartialStruct.HighestElem = {FieldIndex, LowestElem}; 8004 } 8005 } 8006 8007 // Need to emit combined struct for array sections. 8008 if (IsFinalArraySection || IsNonContiguous) 8009 PartialStruct.IsArraySection = true; 8010 8011 // If we have a final array section, we are done with this expression. 8012 if (IsFinalArraySection) 8013 break; 8014 8015 // The pointer becomes the base for the next element. 8016 if (Next != CE) 8017 BP = IsMemberReference ? LowestElem : LB; 8018 8019 IsExpressionFirstInfo = false; 8020 IsCaptureFirstInfo = false; 8021 FirstPointerInComplexData = false; 8022 IsPrevMemberReference = IsMemberReference; 8023 } else if (FirstPointerInComplexData) { 8024 QualType Ty = Components.rbegin() 8025 ->getAssociatedDeclaration() 8026 ->getType() 8027 .getNonReferenceType(); 8028 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 8029 FirstPointerInComplexData = false; 8030 } 8031 } 8032 // If ran into the whole component - allocate the space for the whole 8033 // record. 8034 if (!EncounteredME) 8035 PartialStruct.HasCompleteRecord = true; 8036 8037 if (!IsNonContiguous) 8038 return; 8039 8040 const ASTContext &Context = CGF.getContext(); 8041 8042 // For supporting stride in array section, we need to initialize the first 8043 // dimension size as 1, first offset as 0, and first count as 1 8044 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 0)}; 8045 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 8046 MapValuesArrayTy CurStrides; 8047 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 8048 uint64_t ElementTypeSize; 8049 8050 // Collect Size information for each dimension and get the element size as 8051 // the first Stride. For example, for `int arr[10][10]`, the DimSizes 8052 // should be [10, 10] and the first stride is 4 btyes. 8053 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 8054 Components) { 8055 const Expr *AssocExpr = Component.getAssociatedExpression(); 8056 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8057 8058 if (!OASE) 8059 continue; 8060 8061 QualType Ty = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase()); 8062 auto *CAT = Context.getAsConstantArrayType(Ty); 8063 auto *VAT = Context.getAsVariableArrayType(Ty); 8064 8065 // We need all the dimension size except for the last dimension. 8066 assert((VAT || CAT || &Component == &*Components.begin()) && 8067 "Should be either ConstantArray or VariableArray if not the " 8068 "first Component"); 8069 8070 // Get element size if CurStrides is empty. 8071 if (CurStrides.empty()) { 8072 const Type *ElementType = nullptr; 8073 if (CAT) 8074 ElementType = CAT->getElementType().getTypePtr(); 8075 else if (VAT) 8076 ElementType = VAT->getElementType().getTypePtr(); 8077 else 8078 assert(&Component == &*Components.begin() && 8079 "Only expect pointer (non CAT or VAT) when this is the " 8080 "first Component"); 8081 // If ElementType is null, then it means the base is a pointer 8082 // (neither CAT nor VAT) and we'll attempt to get ElementType again 8083 // for next iteration. 8084 if (ElementType) { 8085 // For the case that having pointer as base, we need to remove one 8086 // level of indirection. 8087 if (&Component != &*Components.begin()) 8088 ElementType = ElementType->getPointeeOrArrayElementType(); 8089 ElementTypeSize = 8090 Context.getTypeSizeInChars(ElementType).getQuantity(); 8091 CurStrides.push_back( 8092 llvm::ConstantInt::get(CGF.Int64Ty, ElementTypeSize)); 8093 } 8094 } 8095 // Get dimension value except for the last dimension since we don't need 8096 // it. 8097 if (DimSizes.size() < Components.size() - 1) { 8098 if (CAT) 8099 DimSizes.push_back(llvm::ConstantInt::get( 8100 CGF.Int64Ty, CAT->getSize().getZExtValue())); 8101 else if (VAT) 8102 DimSizes.push_back(CGF.Builder.CreateIntCast( 8103 CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty, 8104 /*IsSigned=*/false)); 8105 } 8106 } 8107 8108 // Skip the dummy dimension since we have already have its information. 8109 auto DI = DimSizes.begin() + 1; 8110 // Product of dimension. 8111 llvm::Value *DimProd = 8112 llvm::ConstantInt::get(CGF.CGM.Int64Ty, ElementTypeSize); 8113 8114 // Collect info for non-contiguous. Notice that offset, count, and stride 8115 // are only meaningful for array-section, so we insert a null for anything 8116 // other than array-section. 8117 // Also, the size of offset, count, and stride are not the same as 8118 // pointers, base_pointers, sizes, or dims. Instead, the size of offset, 8119 // count, and stride are the same as the number of non-contiguous 8120 // declaration in target update to/from clause. 8121 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 8122 Components) { 8123 const Expr *AssocExpr = Component.getAssociatedExpression(); 8124 8125 if (const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) { 8126 llvm::Value *Offset = CGF.Builder.CreateIntCast( 8127 CGF.EmitScalarExpr(AE->getIdx()), CGF.Int64Ty, 8128 /*isSigned=*/false); 8129 CurOffsets.push_back(Offset); 8130 CurCounts.push_back(llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/1)); 8131 CurStrides.push_back(CurStrides.back()); 8132 continue; 8133 } 8134 8135 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8136 8137 if (!OASE) 8138 continue; 8139 8140 // Offset 8141 const Expr *OffsetExpr = OASE->getLowerBound(); 8142 llvm::Value *Offset = nullptr; 8143 if (!OffsetExpr) { 8144 // If offset is absent, then we just set it to zero. 8145 Offset = llvm::ConstantInt::get(CGF.Int64Ty, 0); 8146 } else { 8147 Offset = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(OffsetExpr), 8148 CGF.Int64Ty, 8149 /*isSigned=*/false); 8150 } 8151 CurOffsets.push_back(Offset); 8152 8153 // Count 8154 const Expr *CountExpr = OASE->getLength(); 8155 llvm::Value *Count = nullptr; 8156 if (!CountExpr) { 8157 // In Clang, once a high dimension is an array section, we construct all 8158 // the lower dimension as array section, however, for case like 8159 // arr[0:2][2], Clang construct the inner dimension as an array section 8160 // but it actually is not in an array section form according to spec. 8161 if (!OASE->getColonLocFirst().isValid() && 8162 !OASE->getColonLocSecond().isValid()) { 8163 Count = llvm::ConstantInt::get(CGF.Int64Ty, 1); 8164 } else { 8165 // OpenMP 5.0, 2.1.5 Array Sections, Description. 8166 // When the length is absent it defaults to ⌈(size − 8167 // lower-bound)/stride⌉, where size is the size of the array 8168 // dimension. 8169 const Expr *StrideExpr = OASE->getStride(); 8170 llvm::Value *Stride = 8171 StrideExpr 8172 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8173 CGF.Int64Ty, /*isSigned=*/false) 8174 : nullptr; 8175 if (Stride) 8176 Count = CGF.Builder.CreateUDiv( 8177 CGF.Builder.CreateNUWSub(*DI, Offset), Stride); 8178 else 8179 Count = CGF.Builder.CreateNUWSub(*DI, Offset); 8180 } 8181 } else { 8182 Count = CGF.EmitScalarExpr(CountExpr); 8183 } 8184 Count = CGF.Builder.CreateIntCast(Count, CGF.Int64Ty, /*isSigned=*/false); 8185 CurCounts.push_back(Count); 8186 8187 // Stride_n' = Stride_n * (D_0 * D_1 ... * D_n-1) * Unit size 8188 // Take `int arr[5][5][5]` and `arr[0:2:2][1:2:1][0:2:2]` as an example: 8189 // Offset Count Stride 8190 // D0 0 1 4 (int) <- dummy dimension 8191 // D1 0 2 8 (2 * (1) * 4) 8192 // D2 1 2 20 (1 * (1 * 5) * 4) 8193 // D3 0 2 200 (2 * (1 * 5 * 4) * 4) 8194 const Expr *StrideExpr = OASE->getStride(); 8195 llvm::Value *Stride = 8196 StrideExpr 8197 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8198 CGF.Int64Ty, /*isSigned=*/false) 8199 : nullptr; 8200 DimProd = CGF.Builder.CreateNUWMul(DimProd, *(DI - 1)); 8201 if (Stride) 8202 CurStrides.push_back(CGF.Builder.CreateNUWMul(DimProd, Stride)); 8203 else 8204 CurStrides.push_back(DimProd); 8205 if (DI != DimSizes.end()) 8206 ++DI; 8207 } 8208 8209 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets); 8210 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts); 8211 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides); 8212 } 8213 8214 /// Return the adjusted map modifiers if the declaration a capture refers to 8215 /// appears in a first-private clause. This is expected to be used only with 8216 /// directives that start with 'target'. 8217 MappableExprsHandler::OpenMPOffloadMappingFlags 8218 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 8219 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 8220 8221 // A first private variable captured by reference will use only the 8222 // 'private ptr' and 'map to' flag. Return the right flags if the captured 8223 // declaration is known as first-private in this handler. 8224 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 8225 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 8226 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 8227 return MappableExprsHandler::OMP_MAP_ALWAYS | 8228 MappableExprsHandler::OMP_MAP_TO; 8229 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 8230 return MappableExprsHandler::OMP_MAP_TO | 8231 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 8232 return MappableExprsHandler::OMP_MAP_PRIVATE | 8233 MappableExprsHandler::OMP_MAP_TO; 8234 } 8235 return MappableExprsHandler::OMP_MAP_TO | 8236 MappableExprsHandler::OMP_MAP_FROM; 8237 } 8238 8239 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 8240 // Rotate by getFlagMemberOffset() bits. 8241 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 8242 << getFlagMemberOffset()); 8243 } 8244 8245 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 8246 OpenMPOffloadMappingFlags MemberOfFlag) { 8247 // If the entry is PTR_AND_OBJ but has not been marked with the special 8248 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 8249 // marked as MEMBER_OF. 8250 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 8251 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 8252 return; 8253 8254 // Reset the placeholder value to prepare the flag for the assignment of the 8255 // proper MEMBER_OF value. 8256 Flags &= ~OMP_MAP_MEMBER_OF; 8257 Flags |= MemberOfFlag; 8258 } 8259 8260 void getPlainLayout(const CXXRecordDecl *RD, 8261 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 8262 bool AsBase) const { 8263 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 8264 8265 llvm::StructType *St = 8266 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 8267 8268 unsigned NumElements = St->getNumElements(); 8269 llvm::SmallVector< 8270 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 8271 RecordLayout(NumElements); 8272 8273 // Fill bases. 8274 for (const auto &I : RD->bases()) { 8275 if (I.isVirtual()) 8276 continue; 8277 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8278 // Ignore empty bases. 8279 if (Base->isEmpty() || CGF.getContext() 8280 .getASTRecordLayout(Base) 8281 .getNonVirtualSize() 8282 .isZero()) 8283 continue; 8284 8285 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 8286 RecordLayout[FieldIndex] = Base; 8287 } 8288 // Fill in virtual bases. 8289 for (const auto &I : RD->vbases()) { 8290 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8291 // Ignore empty bases. 8292 if (Base->isEmpty()) 8293 continue; 8294 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 8295 if (RecordLayout[FieldIndex]) 8296 continue; 8297 RecordLayout[FieldIndex] = Base; 8298 } 8299 // Fill in all the fields. 8300 assert(!RD->isUnion() && "Unexpected union."); 8301 for (const auto *Field : RD->fields()) { 8302 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 8303 // will fill in later.) 8304 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 8305 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 8306 RecordLayout[FieldIndex] = Field; 8307 } 8308 } 8309 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 8310 &Data : RecordLayout) { 8311 if (Data.isNull()) 8312 continue; 8313 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 8314 getPlainLayout(Base, Layout, /*AsBase=*/true); 8315 else 8316 Layout.push_back(Data.get<const FieldDecl *>()); 8317 } 8318 } 8319 8320 /// Generate all the base pointers, section pointers, sizes, map types, and 8321 /// mappers for the extracted mappable expressions (all included in \a 8322 /// CombinedInfo). Also, for each item that relates with a device pointer, a 8323 /// pair of the relevant declaration and index where it occurs is appended to 8324 /// the device pointers info array. 8325 void generateAllInfoForClauses( 8326 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo, 8327 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 8328 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 8329 // We have to process the component lists that relate with the same 8330 // declaration in a single chunk so that we can generate the map flags 8331 // correctly. Therefore, we organize all lists in a map. 8332 enum MapKind { Present, Allocs, Other, Total }; 8333 llvm::MapVector<CanonicalDeclPtr<const Decl>, 8334 SmallVector<SmallVector<MapInfo, 8>, 4>> 8335 Info; 8336 8337 // Helper function to fill the information map for the different supported 8338 // clauses. 8339 auto &&InfoGen = 8340 [&Info, &SkipVarSet]( 8341 const ValueDecl *D, MapKind Kind, 8342 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8343 OpenMPMapClauseKind MapType, 8344 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8345 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 8346 bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper, 8347 const Expr *VarRef = nullptr, bool ForDeviceAddr = false) { 8348 if (SkipVarSet.contains(D)) 8349 return; 8350 auto It = Info.find(D); 8351 if (It == Info.end()) 8352 It = Info 8353 .insert(std::make_pair( 8354 D, SmallVector<SmallVector<MapInfo, 8>, 4>(Total))) 8355 .first; 8356 It->second[Kind].emplace_back( 8357 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer, 8358 IsImplicit, Mapper, VarRef, ForDeviceAddr); 8359 }; 8360 8361 for (const auto *Cl : Clauses) { 8362 const auto *C = dyn_cast<OMPMapClause>(Cl); 8363 if (!C) 8364 continue; 8365 MapKind Kind = Other; 8366 if (!C->getMapTypeModifiers().empty() && 8367 llvm::any_of(C->getMapTypeModifiers(), [](OpenMPMapModifierKind K) { 8368 return K == OMPC_MAP_MODIFIER_present; 8369 })) 8370 Kind = Present; 8371 else if (C->getMapType() == OMPC_MAP_alloc) 8372 Kind = Allocs; 8373 const auto *EI = C->getVarRefs().begin(); 8374 for (const auto L : C->component_lists()) { 8375 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 8376 InfoGen(std::get<0>(L), Kind, std::get<1>(L), C->getMapType(), 8377 C->getMapTypeModifiers(), llvm::None, 8378 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L), 8379 E); 8380 ++EI; 8381 } 8382 } 8383 for (const auto *Cl : Clauses) { 8384 const auto *C = dyn_cast<OMPToClause>(Cl); 8385 if (!C) 8386 continue; 8387 MapKind Kind = Other; 8388 if (!C->getMotionModifiers().empty() && 8389 llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) { 8390 return K == OMPC_MOTION_MODIFIER_present; 8391 })) 8392 Kind = Present; 8393 const auto *EI = C->getVarRefs().begin(); 8394 for (const auto L : C->component_lists()) { 8395 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, llvm::None, 8396 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8397 C->isImplicit(), std::get<2>(L), *EI); 8398 ++EI; 8399 } 8400 } 8401 for (const auto *Cl : Clauses) { 8402 const auto *C = dyn_cast<OMPFromClause>(Cl); 8403 if (!C) 8404 continue; 8405 MapKind Kind = Other; 8406 if (!C->getMotionModifiers().empty() && 8407 llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) { 8408 return K == OMPC_MOTION_MODIFIER_present; 8409 })) 8410 Kind = Present; 8411 const auto *EI = C->getVarRefs().begin(); 8412 for (const auto L : C->component_lists()) { 8413 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, llvm::None, 8414 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8415 C->isImplicit(), std::get<2>(L), *EI); 8416 ++EI; 8417 } 8418 } 8419 8420 // Look at the use_device_ptr clause information and mark the existing map 8421 // entries as such. If there is no map information for an entry in the 8422 // use_device_ptr list, we create one with map type 'alloc' and zero size 8423 // section. It is the user fault if that was not mapped before. If there is 8424 // no map information and the pointer is a struct member, then we defer the 8425 // emission of that entry until the whole struct has been processed. 8426 llvm::MapVector<CanonicalDeclPtr<const Decl>, 8427 SmallVector<DeferredDevicePtrEntryTy, 4>> 8428 DeferredInfo; 8429 MapCombinedInfoTy UseDevicePtrCombinedInfo; 8430 8431 for (const auto *Cl : Clauses) { 8432 const auto *C = dyn_cast<OMPUseDevicePtrClause>(Cl); 8433 if (!C) 8434 continue; 8435 for (const auto L : C->component_lists()) { 8436 OMPClauseMappableExprCommon::MappableExprComponentListRef Components = 8437 std::get<1>(L); 8438 assert(!Components.empty() && 8439 "Not expecting empty list of components!"); 8440 const ValueDecl *VD = Components.back().getAssociatedDeclaration(); 8441 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8442 const Expr *IE = Components.back().getAssociatedExpression(); 8443 // If the first component is a member expression, we have to look into 8444 // 'this', which maps to null in the map of map information. Otherwise 8445 // look directly for the information. 8446 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8447 8448 // We potentially have map information for this declaration already. 8449 // Look for the first set of components that refer to it. 8450 if (It != Info.end()) { 8451 bool Found = false; 8452 for (auto &Data : It->second) { 8453 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) { 8454 return MI.Components.back().getAssociatedDeclaration() == VD; 8455 }); 8456 // If we found a map entry, signal that the pointer has to be 8457 // returned and move on to the next declaration. Exclude cases where 8458 // the base pointer is mapped as array subscript, array section or 8459 // array shaping. The base address is passed as a pointer to base in 8460 // this case and cannot be used as a base for use_device_ptr list 8461 // item. 8462 if (CI != Data.end()) { 8463 auto PrevCI = std::next(CI->Components.rbegin()); 8464 const auto *VarD = dyn_cast<VarDecl>(VD); 8465 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8466 isa<MemberExpr>(IE) || 8467 !VD->getType().getNonReferenceType()->isPointerType() || 8468 PrevCI == CI->Components.rend() || 8469 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD || 8470 VarD->hasLocalStorage()) { 8471 CI->ReturnDevicePointer = true; 8472 Found = true; 8473 break; 8474 } 8475 } 8476 } 8477 if (Found) 8478 continue; 8479 } 8480 8481 // We didn't find any match in our map information - generate a zero 8482 // size array section - if the pointer is a struct member we defer this 8483 // action until the whole struct has been processed. 8484 if (isa<MemberExpr>(IE)) { 8485 // Insert the pointer into Info to be processed by 8486 // generateInfoForComponentList. Because it is a member pointer 8487 // without a pointee, no entry will be generated for it, therefore 8488 // we need to generate one after the whole struct has been processed. 8489 // Nonetheless, generateInfoForComponentList must be called to take 8490 // the pointer into account for the calculation of the range of the 8491 // partial struct. 8492 InfoGen(nullptr, Other, Components, OMPC_MAP_unknown, llvm::None, 8493 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8494 nullptr); 8495 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false); 8496 } else { 8497 llvm::Value *Ptr = 8498 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8499 UseDevicePtrCombinedInfo.Exprs.push_back(VD); 8500 UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD); 8501 UseDevicePtrCombinedInfo.Pointers.push_back(Ptr); 8502 UseDevicePtrCombinedInfo.Sizes.push_back( 8503 llvm::Constant::getNullValue(CGF.Int64Ty)); 8504 UseDevicePtrCombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM); 8505 UseDevicePtrCombinedInfo.Mappers.push_back(nullptr); 8506 } 8507 } 8508 } 8509 8510 // Look at the use_device_addr clause information and mark the existing map 8511 // entries as such. If there is no map information for an entry in the 8512 // use_device_addr list, we create one with map type 'alloc' and zero size 8513 // section. It is the user fault if that was not mapped before. If there is 8514 // no map information and the pointer is a struct member, then we defer the 8515 // emission of that entry until the whole struct has been processed. 8516 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed; 8517 for (const auto *Cl : Clauses) { 8518 const auto *C = dyn_cast<OMPUseDeviceAddrClause>(Cl); 8519 if (!C) 8520 continue; 8521 for (const auto L : C->component_lists()) { 8522 assert(!std::get<1>(L).empty() && 8523 "Not expecting empty list of components!"); 8524 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration(); 8525 if (!Processed.insert(VD).second) 8526 continue; 8527 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8528 const Expr *IE = std::get<1>(L).back().getAssociatedExpression(); 8529 // If the first component is a member expression, we have to look into 8530 // 'this', which maps to null in the map of map information. Otherwise 8531 // look directly for the information. 8532 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8533 8534 // We potentially have map information for this declaration already. 8535 // Look for the first set of components that refer to it. 8536 if (It != Info.end()) { 8537 bool Found = false; 8538 for (auto &Data : It->second) { 8539 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) { 8540 return MI.Components.back().getAssociatedDeclaration() == VD; 8541 }); 8542 // If we found a map entry, signal that the pointer has to be 8543 // returned and move on to the next declaration. 8544 if (CI != Data.end()) { 8545 CI->ReturnDevicePointer = true; 8546 Found = true; 8547 break; 8548 } 8549 } 8550 if (Found) 8551 continue; 8552 } 8553 8554 // We didn't find any match in our map information - generate a zero 8555 // size array section - if the pointer is a struct member we defer this 8556 // action until the whole struct has been processed. 8557 if (isa<MemberExpr>(IE)) { 8558 // Insert the pointer into Info to be processed by 8559 // generateInfoForComponentList. Because it is a member pointer 8560 // without a pointee, no entry will be generated for it, therefore 8561 // we need to generate one after the whole struct has been processed. 8562 // Nonetheless, generateInfoForComponentList must be called to take 8563 // the pointer into account for the calculation of the range of the 8564 // partial struct. 8565 InfoGen(nullptr, Other, std::get<1>(L), OMPC_MAP_unknown, llvm::None, 8566 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8567 nullptr, nullptr, /*ForDeviceAddr=*/true); 8568 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true); 8569 } else { 8570 llvm::Value *Ptr; 8571 if (IE->isGLValue()) 8572 Ptr = CGF.EmitLValue(IE).getPointer(CGF); 8573 else 8574 Ptr = CGF.EmitScalarExpr(IE); 8575 CombinedInfo.Exprs.push_back(VD); 8576 CombinedInfo.BasePointers.emplace_back(Ptr, VD); 8577 CombinedInfo.Pointers.push_back(Ptr); 8578 CombinedInfo.Sizes.push_back( 8579 llvm::Constant::getNullValue(CGF.Int64Ty)); 8580 CombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM); 8581 CombinedInfo.Mappers.push_back(nullptr); 8582 } 8583 } 8584 } 8585 8586 for (const auto &Data : Info) { 8587 StructRangeInfoTy PartialStruct; 8588 // Temporary generated information. 8589 MapCombinedInfoTy CurInfo; 8590 const Decl *D = Data.first; 8591 const ValueDecl *VD = cast_or_null<ValueDecl>(D); 8592 for (const auto &M : Data.second) { 8593 for (const MapInfo &L : M) { 8594 assert(!L.Components.empty() && 8595 "Not expecting declaration with no component lists."); 8596 8597 // Remember the current base pointer index. 8598 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size(); 8599 CurInfo.NonContigInfo.IsNonContiguous = 8600 L.Components.back().isNonContiguous(); 8601 generateInfoForComponentList( 8602 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components, 8603 CurInfo, PartialStruct, /*IsFirstComponentList=*/false, 8604 L.IsImplicit, L.Mapper, L.ForDeviceAddr, VD, L.VarRef); 8605 8606 // If this entry relates with a device pointer, set the relevant 8607 // declaration and add the 'return pointer' flag. 8608 if (L.ReturnDevicePointer) { 8609 assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx && 8610 "Unexpected number of mapped base pointers."); 8611 8612 const ValueDecl *RelevantVD = 8613 L.Components.back().getAssociatedDeclaration(); 8614 assert(RelevantVD && 8615 "No relevant declaration related with device pointer??"); 8616 8617 CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl( 8618 RelevantVD); 8619 CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8620 } 8621 } 8622 } 8623 8624 // Append any pending zero-length pointers which are struct members and 8625 // used with use_device_ptr or use_device_addr. 8626 auto CI = DeferredInfo.find(Data.first); 8627 if (CI != DeferredInfo.end()) { 8628 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8629 llvm::Value *BasePtr; 8630 llvm::Value *Ptr; 8631 if (L.ForDeviceAddr) { 8632 if (L.IE->isGLValue()) 8633 Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8634 else 8635 Ptr = this->CGF.EmitScalarExpr(L.IE); 8636 BasePtr = Ptr; 8637 // Entry is RETURN_PARAM. Also, set the placeholder value 8638 // MEMBER_OF=FFFF so that the entry is later updated with the 8639 // correct value of MEMBER_OF. 8640 CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF); 8641 } else { 8642 BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8643 Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE), 8644 L.IE->getExprLoc()); 8645 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the 8646 // placeholder value MEMBER_OF=FFFF so that the entry is later 8647 // updated with the correct value of MEMBER_OF. 8648 CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8649 OMP_MAP_MEMBER_OF); 8650 } 8651 CurInfo.Exprs.push_back(L.VD); 8652 CurInfo.BasePointers.emplace_back(BasePtr, L.VD); 8653 CurInfo.Pointers.push_back(Ptr); 8654 CurInfo.Sizes.push_back( 8655 llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8656 CurInfo.Mappers.push_back(nullptr); 8657 } 8658 } 8659 // If there is an entry in PartialStruct it means we have a struct with 8660 // individual members mapped. Emit an extra combined entry. 8661 if (PartialStruct.Base.isValid()) { 8662 CurInfo.NonContigInfo.Dims.push_back(0); 8663 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD); 8664 } 8665 8666 // We need to append the results of this capture to what we already 8667 // have. 8668 CombinedInfo.append(CurInfo); 8669 } 8670 // Append data for use_device_ptr clauses. 8671 CombinedInfo.append(UseDevicePtrCombinedInfo); 8672 } 8673 8674 public: 8675 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 8676 : CurDir(&Dir), CGF(CGF) { 8677 // Extract firstprivate clause information. 8678 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 8679 for (const auto *D : C->varlists()) 8680 FirstPrivateDecls.try_emplace( 8681 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 8682 // Extract implicit firstprivates from uses_allocators clauses. 8683 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) { 8684 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 8685 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 8686 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits)) 8687 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()), 8688 /*Implicit=*/true); 8689 else if (const auto *VD = dyn_cast<VarDecl>( 8690 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts()) 8691 ->getDecl())) 8692 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true); 8693 } 8694 } 8695 // Extract device pointer clause information. 8696 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 8697 for (auto L : C->component_lists()) 8698 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L)); 8699 } 8700 8701 /// Constructor for the declare mapper directive. 8702 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 8703 : CurDir(&Dir), CGF(CGF) {} 8704 8705 /// Generate code for the combined entry if we have a partially mapped struct 8706 /// and take care of the mapping flags of the arguments corresponding to 8707 /// individual struct members. 8708 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo, 8709 MapFlagsArrayTy &CurTypes, 8710 const StructRangeInfoTy &PartialStruct, 8711 const ValueDecl *VD = nullptr, 8712 bool NotTargetParams = true) const { 8713 if (CurTypes.size() == 1 && 8714 ((CurTypes.back() & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF) && 8715 !PartialStruct.IsArraySection) 8716 return; 8717 Address LBAddr = PartialStruct.LowestElem.second; 8718 Address HBAddr = PartialStruct.HighestElem.second; 8719 if (PartialStruct.HasCompleteRecord) { 8720 LBAddr = PartialStruct.LB; 8721 HBAddr = PartialStruct.LB; 8722 } 8723 CombinedInfo.Exprs.push_back(VD); 8724 // Base is the base of the struct 8725 CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); 8726 // Pointer is the address of the lowest element 8727 llvm::Value *LB = LBAddr.getPointer(); 8728 CombinedInfo.Pointers.push_back(LB); 8729 // There should not be a mapper for a combined entry. 8730 CombinedInfo.Mappers.push_back(nullptr); 8731 // Size is (addr of {highest+1} element) - (addr of lowest element) 8732 llvm::Value *HB = HBAddr.getPointer(); 8733 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 8734 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 8735 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 8736 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 8737 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 8738 /*isSigned=*/false); 8739 CombinedInfo.Sizes.push_back(Size); 8740 // Map type is always TARGET_PARAM, if generate info for captures. 8741 CombinedInfo.Types.push_back(NotTargetParams ? OMP_MAP_NONE 8742 : OMP_MAP_TARGET_PARAM); 8743 // If any element has the present modifier, then make sure the runtime 8744 // doesn't attempt to allocate the struct. 8745 if (CurTypes.end() != 8746 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) { 8747 return Type & OMP_MAP_PRESENT; 8748 })) 8749 CombinedInfo.Types.back() |= OMP_MAP_PRESENT; 8750 // Remove TARGET_PARAM flag from the first element 8751 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 8752 8753 // All other current entries will be MEMBER_OF the combined entry 8754 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8755 // 0xFFFF in the MEMBER_OF field). 8756 OpenMPOffloadMappingFlags MemberOfFlag = 8757 getMemberOfFlag(CombinedInfo.BasePointers.size() - 1); 8758 for (auto &M : CurTypes) 8759 setCorrectMemberOfFlag(M, MemberOfFlag); 8760 } 8761 8762 /// Generate all the base pointers, section pointers, sizes, map types, and 8763 /// mappers for the extracted mappable expressions (all included in \a 8764 /// CombinedInfo). Also, for each item that relates with a device pointer, a 8765 /// pair of the relevant declaration and index where it occurs is appended to 8766 /// the device pointers info array. 8767 void generateAllInfo( 8768 MapCombinedInfoTy &CombinedInfo, 8769 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 8770 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 8771 assert(CurDir.is<const OMPExecutableDirective *>() && 8772 "Expect a executable directive"); 8773 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8774 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, SkipVarSet); 8775 } 8776 8777 /// Generate all the base pointers, section pointers, sizes, map types, and 8778 /// mappers for the extracted map clauses of user-defined mapper (all included 8779 /// in \a CombinedInfo). 8780 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const { 8781 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8782 "Expect a declare mapper directive"); 8783 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8784 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo); 8785 } 8786 8787 /// Emit capture info for lambdas for variables captured by reference. 8788 void generateInfoForLambdaCaptures( 8789 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 8790 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8791 const auto *RD = VD->getType() 8792 .getCanonicalType() 8793 .getNonReferenceType() 8794 ->getAsCXXRecordDecl(); 8795 if (!RD || !RD->isLambda()) 8796 return; 8797 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8798 LValue VDLVal = CGF.MakeAddrLValue( 8799 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8800 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8801 FieldDecl *ThisCapture = nullptr; 8802 RD->getCaptureFields(Captures, ThisCapture); 8803 if (ThisCapture) { 8804 LValue ThisLVal = 8805 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8806 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8807 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8808 VDLVal.getPointer(CGF)); 8809 CombinedInfo.Exprs.push_back(VD); 8810 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF)); 8811 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF)); 8812 CombinedInfo.Sizes.push_back( 8813 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8814 CGF.Int64Ty, /*isSigned=*/true)); 8815 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8816 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8817 CombinedInfo.Mappers.push_back(nullptr); 8818 } 8819 for (const LambdaCapture &LC : RD->captures()) { 8820 if (!LC.capturesVariable()) 8821 continue; 8822 const VarDecl *VD = LC.getCapturedVar(); 8823 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8824 continue; 8825 auto It = Captures.find(VD); 8826 assert(It != Captures.end() && "Found lambda capture without field."); 8827 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8828 if (LC.getCaptureKind() == LCK_ByRef) { 8829 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8830 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8831 VDLVal.getPointer(CGF)); 8832 CombinedInfo.Exprs.push_back(VD); 8833 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 8834 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF)); 8835 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8836 CGF.getTypeSize( 8837 VD->getType().getCanonicalType().getNonReferenceType()), 8838 CGF.Int64Ty, /*isSigned=*/true)); 8839 } else { 8840 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8841 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8842 VDLVal.getPointer(CGF)); 8843 CombinedInfo.Exprs.push_back(VD); 8844 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 8845 CombinedInfo.Pointers.push_back(VarRVal.getScalarVal()); 8846 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8847 } 8848 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8849 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8850 CombinedInfo.Mappers.push_back(nullptr); 8851 } 8852 } 8853 8854 /// Set correct indices for lambdas captures. 8855 void adjustMemberOfForLambdaCaptures( 8856 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8857 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8858 MapFlagsArrayTy &Types) const { 8859 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8860 // Set correct member_of idx for all implicit lambda captures. 8861 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8862 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8863 continue; 8864 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8865 assert(BasePtr && "Unable to find base lambda address."); 8866 int TgtIdx = -1; 8867 for (unsigned J = I; J > 0; --J) { 8868 unsigned Idx = J - 1; 8869 if (Pointers[Idx] != BasePtr) 8870 continue; 8871 TgtIdx = Idx; 8872 break; 8873 } 8874 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8875 // All other current entries will be MEMBER_OF the combined entry 8876 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8877 // 0xFFFF in the MEMBER_OF field). 8878 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8879 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8880 } 8881 } 8882 8883 /// Generate the base pointers, section pointers, sizes, map types, and 8884 /// mappers associated to a given capture (all included in \a CombinedInfo). 8885 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8886 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 8887 StructRangeInfoTy &PartialStruct) const { 8888 assert(!Cap->capturesVariableArrayType() && 8889 "Not expecting to generate map info for a variable array type!"); 8890 8891 // We need to know when we generating information for the first component 8892 const ValueDecl *VD = Cap->capturesThis() 8893 ? nullptr 8894 : Cap->getCapturedVar()->getCanonicalDecl(); 8895 8896 // If this declaration appears in a is_device_ptr clause we just have to 8897 // pass the pointer by value. If it is a reference to a declaration, we just 8898 // pass its value. 8899 if (DevPointersMap.count(VD)) { 8900 CombinedInfo.Exprs.push_back(VD); 8901 CombinedInfo.BasePointers.emplace_back(Arg, VD); 8902 CombinedInfo.Pointers.push_back(Arg); 8903 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8904 CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty, 8905 /*isSigned=*/true)); 8906 CombinedInfo.Types.push_back( 8907 (Cap->capturesVariable() ? OMP_MAP_TO : OMP_MAP_LITERAL) | 8908 OMP_MAP_TARGET_PARAM); 8909 CombinedInfo.Mappers.push_back(nullptr); 8910 return; 8911 } 8912 8913 using MapData = 8914 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8915 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool, 8916 const ValueDecl *, const Expr *>; 8917 SmallVector<MapData, 4> DeclComponentLists; 8918 assert(CurDir.is<const OMPExecutableDirective *>() && 8919 "Expect a executable directive"); 8920 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8921 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8922 const auto *EI = C->getVarRefs().begin(); 8923 for (const auto L : C->decl_component_lists(VD)) { 8924 const ValueDecl *VDecl, *Mapper; 8925 // The Expression is not correct if the mapping is implicit 8926 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 8927 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8928 std::tie(VDecl, Components, Mapper) = L; 8929 assert(VDecl == VD && "We got information for the wrong declaration??"); 8930 assert(!Components.empty() && 8931 "Not expecting declaration with no component lists."); 8932 DeclComponentLists.emplace_back(Components, C->getMapType(), 8933 C->getMapTypeModifiers(), 8934 C->isImplicit(), Mapper, E); 8935 ++EI; 8936 } 8937 } 8938 llvm::stable_sort(DeclComponentLists, [](const MapData &LHS, 8939 const MapData &RHS) { 8940 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS); 8941 OpenMPMapClauseKind MapType = std::get<1>(RHS); 8942 bool HasPresent = !MapModifiers.empty() && 8943 llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) { 8944 return K == clang::OMPC_MAP_MODIFIER_present; 8945 }); 8946 bool HasAllocs = MapType == OMPC_MAP_alloc; 8947 MapModifiers = std::get<2>(RHS); 8948 MapType = std::get<1>(LHS); 8949 bool HasPresentR = 8950 !MapModifiers.empty() && 8951 llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) { 8952 return K == clang::OMPC_MAP_MODIFIER_present; 8953 }); 8954 bool HasAllocsR = MapType == OMPC_MAP_alloc; 8955 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR); 8956 }); 8957 8958 // Find overlapping elements (including the offset from the base element). 8959 llvm::SmallDenseMap< 8960 const MapData *, 8961 llvm::SmallVector< 8962 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8963 4> 8964 OverlappedData; 8965 size_t Count = 0; 8966 for (const MapData &L : DeclComponentLists) { 8967 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8968 OpenMPMapClauseKind MapType; 8969 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8970 bool IsImplicit; 8971 const ValueDecl *Mapper; 8972 const Expr *VarRef; 8973 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 8974 L; 8975 ++Count; 8976 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8977 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8978 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper, 8979 VarRef) = L1; 8980 auto CI = Components.rbegin(); 8981 auto CE = Components.rend(); 8982 auto SI = Components1.rbegin(); 8983 auto SE = Components1.rend(); 8984 for (; CI != CE && SI != SE; ++CI, ++SI) { 8985 if (CI->getAssociatedExpression()->getStmtClass() != 8986 SI->getAssociatedExpression()->getStmtClass()) 8987 break; 8988 // Are we dealing with different variables/fields? 8989 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8990 break; 8991 } 8992 // Found overlapping if, at least for one component, reached the head 8993 // of the components list. 8994 if (CI == CE || SI == SE) { 8995 // Ignore it if it is the same component. 8996 if (CI == CE && SI == SE) 8997 continue; 8998 const auto It = (SI == SE) ? CI : SI; 8999 // If one component is a pointer and another one is a kind of 9000 // dereference of this pointer (array subscript, section, dereference, 9001 // etc.), it is not an overlapping. 9002 if (!isa<MemberExpr>(It->getAssociatedExpression()) || 9003 std::prev(It) 9004 ->getAssociatedExpression() 9005 ->getType() 9006 ->isPointerType()) 9007 continue; 9008 const MapData &BaseData = CI == CE ? L : L1; 9009 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 9010 SI == SE ? Components : Components1; 9011 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 9012 OverlappedElements.getSecond().push_back(SubData); 9013 } 9014 } 9015 } 9016 // Sort the overlapped elements for each item. 9017 llvm::SmallVector<const FieldDecl *, 4> Layout; 9018 if (!OverlappedData.empty()) { 9019 const Type *BaseType = VD->getType().getCanonicalType().getTypePtr(); 9020 const Type *OrigType = BaseType->getPointeeOrArrayElementType(); 9021 while (BaseType != OrigType) { 9022 BaseType = OrigType->getCanonicalTypeInternal().getTypePtr(); 9023 OrigType = BaseType->getPointeeOrArrayElementType(); 9024 } 9025 9026 if (const auto *CRD = BaseType->getAsCXXRecordDecl()) 9027 getPlainLayout(CRD, Layout, /*AsBase=*/false); 9028 else { 9029 const auto *RD = BaseType->getAsRecordDecl(); 9030 Layout.append(RD->field_begin(), RD->field_end()); 9031 } 9032 } 9033 for (auto &Pair : OverlappedData) { 9034 llvm::stable_sort( 9035 Pair.getSecond(), 9036 [&Layout]( 9037 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 9038 OMPClauseMappableExprCommon::MappableExprComponentListRef 9039 Second) { 9040 auto CI = First.rbegin(); 9041 auto CE = First.rend(); 9042 auto SI = Second.rbegin(); 9043 auto SE = Second.rend(); 9044 for (; CI != CE && SI != SE; ++CI, ++SI) { 9045 if (CI->getAssociatedExpression()->getStmtClass() != 9046 SI->getAssociatedExpression()->getStmtClass()) 9047 break; 9048 // Are we dealing with different variables/fields? 9049 if (CI->getAssociatedDeclaration() != 9050 SI->getAssociatedDeclaration()) 9051 break; 9052 } 9053 9054 // Lists contain the same elements. 9055 if (CI == CE && SI == SE) 9056 return false; 9057 9058 // List with less elements is less than list with more elements. 9059 if (CI == CE || SI == SE) 9060 return CI == CE; 9061 9062 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 9063 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 9064 if (FD1->getParent() == FD2->getParent()) 9065 return FD1->getFieldIndex() < FD2->getFieldIndex(); 9066 const auto It = 9067 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 9068 return FD == FD1 || FD == FD2; 9069 }); 9070 return *It == FD1; 9071 }); 9072 } 9073 9074 // Associated with a capture, because the mapping flags depend on it. 9075 // Go through all of the elements with the overlapped elements. 9076 bool IsFirstComponentList = true; 9077 for (const auto &Pair : OverlappedData) { 9078 const MapData &L = *Pair.getFirst(); 9079 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9080 OpenMPMapClauseKind MapType; 9081 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9082 bool IsImplicit; 9083 const ValueDecl *Mapper; 9084 const Expr *VarRef; 9085 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9086 L; 9087 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 9088 OverlappedComponents = Pair.getSecond(); 9089 generateInfoForComponentList( 9090 MapType, MapModifiers, llvm::None, Components, CombinedInfo, 9091 PartialStruct, IsFirstComponentList, IsImplicit, Mapper, 9092 /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents); 9093 IsFirstComponentList = false; 9094 } 9095 // Go through other elements without overlapped elements. 9096 for (const MapData &L : DeclComponentLists) { 9097 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9098 OpenMPMapClauseKind MapType; 9099 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9100 bool IsImplicit; 9101 const ValueDecl *Mapper; 9102 const Expr *VarRef; 9103 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9104 L; 9105 auto It = OverlappedData.find(&L); 9106 if (It == OverlappedData.end()) 9107 generateInfoForComponentList(MapType, MapModifiers, llvm::None, 9108 Components, CombinedInfo, PartialStruct, 9109 IsFirstComponentList, IsImplicit, Mapper, 9110 /*ForDeviceAddr=*/false, VD, VarRef); 9111 IsFirstComponentList = false; 9112 } 9113 } 9114 9115 /// Generate the default map information for a given capture \a CI, 9116 /// record field declaration \a RI and captured value \a CV. 9117 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 9118 const FieldDecl &RI, llvm::Value *CV, 9119 MapCombinedInfoTy &CombinedInfo) const { 9120 bool IsImplicit = true; 9121 // Do the default mapping. 9122 if (CI.capturesThis()) { 9123 CombinedInfo.Exprs.push_back(nullptr); 9124 CombinedInfo.BasePointers.push_back(CV); 9125 CombinedInfo.Pointers.push_back(CV); 9126 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 9127 CombinedInfo.Sizes.push_back( 9128 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 9129 CGF.Int64Ty, /*isSigned=*/true)); 9130 // Default map type. 9131 CombinedInfo.Types.push_back(OMP_MAP_TO | OMP_MAP_FROM); 9132 } else if (CI.capturesVariableByCopy()) { 9133 const VarDecl *VD = CI.getCapturedVar(); 9134 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9135 CombinedInfo.BasePointers.push_back(CV); 9136 CombinedInfo.Pointers.push_back(CV); 9137 if (!RI.getType()->isAnyPointerType()) { 9138 // We have to signal to the runtime captures passed by value that are 9139 // not pointers. 9140 CombinedInfo.Types.push_back(OMP_MAP_LITERAL); 9141 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9142 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 9143 } else { 9144 // Pointers are implicitly mapped with a zero size and no flags 9145 // (other than first map that is added for all implicit maps). 9146 CombinedInfo.Types.push_back(OMP_MAP_NONE); 9147 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 9148 } 9149 auto I = FirstPrivateDecls.find(VD); 9150 if (I != FirstPrivateDecls.end()) 9151 IsImplicit = I->getSecond(); 9152 } else { 9153 assert(CI.capturesVariable() && "Expected captured reference."); 9154 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 9155 QualType ElementType = PtrTy->getPointeeType(); 9156 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9157 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 9158 // The default map type for a scalar/complex type is 'to' because by 9159 // default the value doesn't have to be retrieved. For an aggregate 9160 // type, the default is 'tofrom'. 9161 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI)); 9162 const VarDecl *VD = CI.getCapturedVar(); 9163 auto I = FirstPrivateDecls.find(VD); 9164 if (I != FirstPrivateDecls.end() && 9165 VD->getType().isConstant(CGF.getContext())) { 9166 llvm::Constant *Addr = 9167 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 9168 // Copy the value of the original variable to the new global copy. 9169 CGF.Builder.CreateMemCpy( 9170 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 9171 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 9172 CombinedInfo.Sizes.back(), /*IsVolatile=*/false); 9173 // Use new global variable as the base pointers. 9174 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9175 CombinedInfo.BasePointers.push_back(Addr); 9176 CombinedInfo.Pointers.push_back(Addr); 9177 } else { 9178 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9179 CombinedInfo.BasePointers.push_back(CV); 9180 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 9181 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 9182 CV, ElementType, CGF.getContext().getDeclAlign(VD), 9183 AlignmentSource::Decl)); 9184 CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); 9185 } else { 9186 CombinedInfo.Pointers.push_back(CV); 9187 } 9188 } 9189 if (I != FirstPrivateDecls.end()) 9190 IsImplicit = I->getSecond(); 9191 } 9192 // Every default map produces a single argument which is a target parameter. 9193 CombinedInfo.Types.back() |= OMP_MAP_TARGET_PARAM; 9194 9195 // Add flag stating this is an implicit map. 9196 if (IsImplicit) 9197 CombinedInfo.Types.back() |= OMP_MAP_IMPLICIT; 9198 9199 // No user-defined mapper for default mapping. 9200 CombinedInfo.Mappers.push_back(nullptr); 9201 } 9202 }; 9203 } // anonymous namespace 9204 9205 static void emitNonContiguousDescriptor( 9206 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9207 CGOpenMPRuntime::TargetDataInfo &Info) { 9208 CodeGenModule &CGM = CGF.CGM; 9209 MappableExprsHandler::MapCombinedInfoTy::StructNonContiguousInfo 9210 &NonContigInfo = CombinedInfo.NonContigInfo; 9211 9212 // Build an array of struct descriptor_dim and then assign it to 9213 // offload_args. 9214 // 9215 // struct descriptor_dim { 9216 // uint64_t offset; 9217 // uint64_t count; 9218 // uint64_t stride 9219 // }; 9220 ASTContext &C = CGF.getContext(); 9221 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 9222 RecordDecl *RD; 9223 RD = C.buildImplicitRecord("descriptor_dim"); 9224 RD->startDefinition(); 9225 addFieldToRecordDecl(C, RD, Int64Ty); 9226 addFieldToRecordDecl(C, RD, Int64Ty); 9227 addFieldToRecordDecl(C, RD, Int64Ty); 9228 RD->completeDefinition(); 9229 QualType DimTy = C.getRecordType(RD); 9230 9231 enum { OffsetFD = 0, CountFD, StrideFD }; 9232 // We need two index variable here since the size of "Dims" is the same as the 9233 // size of Components, however, the size of offset, count, and stride is equal 9234 // to the size of base declaration that is non-contiguous. 9235 for (unsigned I = 0, L = 0, E = NonContigInfo.Dims.size(); I < E; ++I) { 9236 // Skip emitting ir if dimension size is 1 since it cannot be 9237 // non-contiguous. 9238 if (NonContigInfo.Dims[I] == 1) 9239 continue; 9240 llvm::APInt Size(/*numBits=*/32, NonContigInfo.Dims[I]); 9241 QualType ArrayTy = 9242 C.getConstantArrayType(DimTy, Size, nullptr, ArrayType::Normal, 0); 9243 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 9244 for (unsigned II = 0, EE = NonContigInfo.Dims[I]; II < EE; ++II) { 9245 unsigned RevIdx = EE - II - 1; 9246 LValue DimsLVal = CGF.MakeAddrLValue( 9247 CGF.Builder.CreateConstArrayGEP(DimsAddr, II), DimTy); 9248 // Offset 9249 LValue OffsetLVal = CGF.EmitLValueForField( 9250 DimsLVal, *std::next(RD->field_begin(), OffsetFD)); 9251 CGF.EmitStoreOfScalar(NonContigInfo.Offsets[L][RevIdx], OffsetLVal); 9252 // Count 9253 LValue CountLVal = CGF.EmitLValueForField( 9254 DimsLVal, *std::next(RD->field_begin(), CountFD)); 9255 CGF.EmitStoreOfScalar(NonContigInfo.Counts[L][RevIdx], CountLVal); 9256 // Stride 9257 LValue StrideLVal = CGF.EmitLValueForField( 9258 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 9259 CGF.EmitStoreOfScalar(NonContigInfo.Strides[L][RevIdx], StrideLVal); 9260 } 9261 // args[I] = &dims 9262 Address DAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9263 DimsAddr, CGM.Int8PtrTy); 9264 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9265 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9266 Info.PointersArray, 0, I); 9267 Address PAddr(P, CGF.getPointerAlign()); 9268 CGF.Builder.CreateStore(DAddr.getPointer(), PAddr); 9269 ++L; 9270 } 9271 } 9272 9273 /// Emit a string constant containing the names of the values mapped to the 9274 /// offloading runtime library. 9275 llvm::Constant * 9276 emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, 9277 MappableExprsHandler::MappingExprInfo &MapExprs) { 9278 llvm::Constant *SrcLocStr; 9279 if (!MapExprs.getMapDecl()) { 9280 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(); 9281 } else { 9282 std::string ExprName = ""; 9283 if (MapExprs.getMapExpr()) { 9284 PrintingPolicy P(CGF.getContext().getLangOpts()); 9285 llvm::raw_string_ostream OS(ExprName); 9286 MapExprs.getMapExpr()->printPretty(OS, nullptr, P); 9287 OS.flush(); 9288 } else { 9289 ExprName = MapExprs.getMapDecl()->getNameAsString(); 9290 } 9291 9292 SourceLocation Loc = MapExprs.getMapDecl()->getLocation(); 9293 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 9294 const char *FileName = PLoc.getFilename(); 9295 unsigned Line = PLoc.getLine(); 9296 unsigned Column = PLoc.getColumn(); 9297 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FileName, ExprName.c_str(), 9298 Line, Column); 9299 } 9300 return SrcLocStr; 9301 } 9302 9303 /// Emit the arrays used to pass the captures and map information to the 9304 /// offloading runtime library. If there is no map or capture information, 9305 /// return nullptr by reference. 9306 static void emitOffloadingArrays( 9307 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9308 CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, 9309 bool IsNonContiguous = false) { 9310 CodeGenModule &CGM = CGF.CGM; 9311 ASTContext &Ctx = CGF.getContext(); 9312 9313 // Reset the array information. 9314 Info.clearArrayInfo(); 9315 Info.NumberOfPtrs = CombinedInfo.BasePointers.size(); 9316 9317 if (Info.NumberOfPtrs) { 9318 // Detect if we have any capture size requiring runtime evaluation of the 9319 // size so that a constant array could be eventually used. 9320 bool hasRuntimeEvaluationCaptureSize = false; 9321 for (llvm::Value *S : CombinedInfo.Sizes) 9322 if (!isa<llvm::Constant>(S)) { 9323 hasRuntimeEvaluationCaptureSize = true; 9324 break; 9325 } 9326 9327 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 9328 QualType PointerArrayType = Ctx.getConstantArrayType( 9329 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 9330 /*IndexTypeQuals=*/0); 9331 9332 Info.BasePointersArray = 9333 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 9334 Info.PointersArray = 9335 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 9336 Address MappersArray = 9337 CGF.CreateMemTemp(PointerArrayType, ".offload_mappers"); 9338 Info.MappersArray = MappersArray.getPointer(); 9339 9340 // If we don't have any VLA types or other types that require runtime 9341 // evaluation, we can use a constant array for the map sizes, otherwise we 9342 // need to fill up the arrays as we do for the pointers. 9343 QualType Int64Ty = 9344 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 9345 if (hasRuntimeEvaluationCaptureSize) { 9346 QualType SizeArrayType = Ctx.getConstantArrayType( 9347 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 9348 /*IndexTypeQuals=*/0); 9349 Info.SizesArray = 9350 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 9351 } else { 9352 // We expect all the sizes to be constant, so we collect them to create 9353 // a constant array. 9354 SmallVector<llvm::Constant *, 16> ConstSizes; 9355 for (unsigned I = 0, E = CombinedInfo.Sizes.size(); I < E; ++I) { 9356 if (IsNonContiguous && 9357 (CombinedInfo.Types[I] & MappableExprsHandler::OMP_MAP_NON_CONTIG)) { 9358 ConstSizes.push_back(llvm::ConstantInt::get( 9359 CGF.Int64Ty, CombinedInfo.NonContigInfo.Dims[I])); 9360 } else { 9361 ConstSizes.push_back(cast<llvm::Constant>(CombinedInfo.Sizes[I])); 9362 } 9363 } 9364 9365 auto *SizesArrayInit = llvm::ConstantArray::get( 9366 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 9367 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 9368 auto *SizesArrayGbl = new llvm::GlobalVariable( 9369 CGM.getModule(), SizesArrayInit->getType(), 9370 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 9371 SizesArrayInit, Name); 9372 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 9373 Info.SizesArray = SizesArrayGbl; 9374 } 9375 9376 // The map types are always constant so we don't need to generate code to 9377 // fill arrays. Instead, we create an array constant. 9378 SmallVector<uint64_t, 4> Mapping(CombinedInfo.Types.size(), 0); 9379 llvm::copy(CombinedInfo.Types, Mapping.begin()); 9380 std::string MaptypesName = 9381 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 9382 auto *MapTypesArrayGbl = 9383 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName); 9384 Info.MapTypesArray = MapTypesArrayGbl; 9385 9386 // The information types are only built if there is debug information 9387 // requested. 9388 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) { 9389 Info.MapNamesArray = llvm::Constant::getNullValue( 9390 llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo()); 9391 } else { 9392 auto fillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) { 9393 return emitMappingInformation(CGF, OMPBuilder, MapExpr); 9394 }; 9395 SmallVector<llvm::Constant *, 4> InfoMap(CombinedInfo.Exprs.size()); 9396 llvm::transform(CombinedInfo.Exprs, InfoMap.begin(), fillInfoMap); 9397 std::string MapnamesName = 9398 CGM.getOpenMPRuntime().getName({"offload_mapnames"}); 9399 auto *MapNamesArrayGbl = 9400 OMPBuilder.createOffloadMapnames(InfoMap, MapnamesName); 9401 Info.MapNamesArray = MapNamesArrayGbl; 9402 } 9403 9404 // If there's a present map type modifier, it must not be applied to the end 9405 // of a region, so generate a separate map type array in that case. 9406 if (Info.separateBeginEndCalls()) { 9407 bool EndMapTypesDiffer = false; 9408 for (uint64_t &Type : Mapping) { 9409 if (Type & MappableExprsHandler::OMP_MAP_PRESENT) { 9410 Type &= ~MappableExprsHandler::OMP_MAP_PRESENT; 9411 EndMapTypesDiffer = true; 9412 } 9413 } 9414 if (EndMapTypesDiffer) { 9415 MapTypesArrayGbl = 9416 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName); 9417 Info.MapTypesArrayEnd = MapTypesArrayGbl; 9418 } 9419 } 9420 9421 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 9422 llvm::Value *BPVal = *CombinedInfo.BasePointers[I]; 9423 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 9424 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9425 Info.BasePointersArray, 0, I); 9426 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9427 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9428 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9429 CGF.Builder.CreateStore(BPVal, BPAddr); 9430 9431 if (Info.requiresDevicePointerInfo()) 9432 if (const ValueDecl *DevVD = 9433 CombinedInfo.BasePointers[I].getDevicePtrDecl()) 9434 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 9435 9436 llvm::Value *PVal = CombinedInfo.Pointers[I]; 9437 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9438 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9439 Info.PointersArray, 0, I); 9440 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9441 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9442 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9443 CGF.Builder.CreateStore(PVal, PAddr); 9444 9445 if (hasRuntimeEvaluationCaptureSize) { 9446 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 9447 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9448 Info.SizesArray, 9449 /*Idx0=*/0, 9450 /*Idx1=*/I); 9451 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 9452 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(CombinedInfo.Sizes[I], 9453 CGM.Int64Ty, 9454 /*isSigned=*/true), 9455 SAddr); 9456 } 9457 9458 // Fill up the mapper array. 9459 llvm::Value *MFunc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 9460 if (CombinedInfo.Mappers[I]) { 9461 MFunc = CGM.getOpenMPRuntime().getOrCreateUserDefinedMapperFunc( 9462 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I])); 9463 MFunc = CGF.Builder.CreatePointerCast(MFunc, CGM.VoidPtrTy); 9464 Info.HasMapper = true; 9465 } 9466 Address MAddr = CGF.Builder.CreateConstArrayGEP(MappersArray, I); 9467 CGF.Builder.CreateStore(MFunc, MAddr); 9468 } 9469 } 9470 9471 if (!IsNonContiguous || CombinedInfo.NonContigInfo.Offsets.empty() || 9472 Info.NumberOfPtrs == 0) 9473 return; 9474 9475 emitNonContiguousDescriptor(CGF, CombinedInfo, Info); 9476 } 9477 9478 namespace { 9479 /// Additional arguments for emitOffloadingArraysArgument function. 9480 struct ArgumentsOptions { 9481 bool ForEndCall = false; 9482 ArgumentsOptions() = default; 9483 ArgumentsOptions(bool ForEndCall) : ForEndCall(ForEndCall) {} 9484 }; 9485 } // namespace 9486 9487 /// Emit the arguments to be passed to the runtime library based on the 9488 /// arrays of base pointers, pointers, sizes, map types, and mappers. If 9489 /// ForEndCall, emit map types to be passed for the end of the region instead of 9490 /// the beginning. 9491 static void emitOffloadingArraysArgument( 9492 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 9493 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 9494 llvm::Value *&MapTypesArrayArg, llvm::Value *&MapNamesArrayArg, 9495 llvm::Value *&MappersArrayArg, CGOpenMPRuntime::TargetDataInfo &Info, 9496 const ArgumentsOptions &Options = ArgumentsOptions()) { 9497 assert((!Options.ForEndCall || Info.separateBeginEndCalls()) && 9498 "expected region end call to runtime only when end call is separate"); 9499 CodeGenModule &CGM = CGF.CGM; 9500 if (Info.NumberOfPtrs) { 9501 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9502 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9503 Info.BasePointersArray, 9504 /*Idx0=*/0, /*Idx1=*/0); 9505 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9506 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9507 Info.PointersArray, 9508 /*Idx0=*/0, 9509 /*Idx1=*/0); 9510 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9511 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 9512 /*Idx0=*/0, /*Idx1=*/0); 9513 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9514 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9515 Options.ForEndCall && Info.MapTypesArrayEnd ? Info.MapTypesArrayEnd 9516 : Info.MapTypesArray, 9517 /*Idx0=*/0, 9518 /*Idx1=*/0); 9519 9520 // Only emit the mapper information arrays if debug information is 9521 // requested. 9522 if (CGF.CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 9523 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9524 else 9525 MapNamesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9526 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9527 Info.MapNamesArray, 9528 /*Idx0=*/0, 9529 /*Idx1=*/0); 9530 // If there is no user-defined mapper, set the mapper array to nullptr to 9531 // avoid an unnecessary data privatization 9532 if (!Info.HasMapper) 9533 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9534 else 9535 MappersArrayArg = 9536 CGF.Builder.CreatePointerCast(Info.MappersArray, CGM.VoidPtrPtrTy); 9537 } else { 9538 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9539 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9540 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9541 MapTypesArrayArg = 9542 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9543 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9544 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9545 } 9546 } 9547 9548 /// Check for inner distribute directive. 9549 static const OMPExecutableDirective * 9550 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 9551 const auto *CS = D.getInnermostCapturedStmt(); 9552 const auto *Body = 9553 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 9554 const Stmt *ChildStmt = 9555 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9556 9557 if (const auto *NestedDir = 9558 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9559 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 9560 switch (D.getDirectiveKind()) { 9561 case OMPD_target: 9562 if (isOpenMPDistributeDirective(DKind)) 9563 return NestedDir; 9564 if (DKind == OMPD_teams) { 9565 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 9566 /*IgnoreCaptured=*/true); 9567 if (!Body) 9568 return nullptr; 9569 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9570 if (const auto *NND = 9571 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9572 DKind = NND->getDirectiveKind(); 9573 if (isOpenMPDistributeDirective(DKind)) 9574 return NND; 9575 } 9576 } 9577 return nullptr; 9578 case OMPD_target_teams: 9579 if (isOpenMPDistributeDirective(DKind)) 9580 return NestedDir; 9581 return nullptr; 9582 case OMPD_target_parallel: 9583 case OMPD_target_simd: 9584 case OMPD_target_parallel_for: 9585 case OMPD_target_parallel_for_simd: 9586 return nullptr; 9587 case OMPD_target_teams_distribute: 9588 case OMPD_target_teams_distribute_simd: 9589 case OMPD_target_teams_distribute_parallel_for: 9590 case OMPD_target_teams_distribute_parallel_for_simd: 9591 case OMPD_parallel: 9592 case OMPD_for: 9593 case OMPD_parallel_for: 9594 case OMPD_parallel_master: 9595 case OMPD_parallel_sections: 9596 case OMPD_for_simd: 9597 case OMPD_parallel_for_simd: 9598 case OMPD_cancel: 9599 case OMPD_cancellation_point: 9600 case OMPD_ordered: 9601 case OMPD_threadprivate: 9602 case OMPD_allocate: 9603 case OMPD_task: 9604 case OMPD_simd: 9605 case OMPD_tile: 9606 case OMPD_sections: 9607 case OMPD_section: 9608 case OMPD_single: 9609 case OMPD_master: 9610 case OMPD_critical: 9611 case OMPD_taskyield: 9612 case OMPD_barrier: 9613 case OMPD_taskwait: 9614 case OMPD_taskgroup: 9615 case OMPD_atomic: 9616 case OMPD_flush: 9617 case OMPD_depobj: 9618 case OMPD_scan: 9619 case OMPD_teams: 9620 case OMPD_target_data: 9621 case OMPD_target_exit_data: 9622 case OMPD_target_enter_data: 9623 case OMPD_distribute: 9624 case OMPD_distribute_simd: 9625 case OMPD_distribute_parallel_for: 9626 case OMPD_distribute_parallel_for_simd: 9627 case OMPD_teams_distribute: 9628 case OMPD_teams_distribute_simd: 9629 case OMPD_teams_distribute_parallel_for: 9630 case OMPD_teams_distribute_parallel_for_simd: 9631 case OMPD_target_update: 9632 case OMPD_declare_simd: 9633 case OMPD_declare_variant: 9634 case OMPD_begin_declare_variant: 9635 case OMPD_end_declare_variant: 9636 case OMPD_declare_target: 9637 case OMPD_end_declare_target: 9638 case OMPD_declare_reduction: 9639 case OMPD_declare_mapper: 9640 case OMPD_taskloop: 9641 case OMPD_taskloop_simd: 9642 case OMPD_master_taskloop: 9643 case OMPD_master_taskloop_simd: 9644 case OMPD_parallel_master_taskloop: 9645 case OMPD_parallel_master_taskloop_simd: 9646 case OMPD_requires: 9647 case OMPD_unknown: 9648 default: 9649 llvm_unreachable("Unexpected directive."); 9650 } 9651 } 9652 9653 return nullptr; 9654 } 9655 9656 /// Emit the user-defined mapper function. The code generation follows the 9657 /// pattern in the example below. 9658 /// \code 9659 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 9660 /// void *base, void *begin, 9661 /// int64_t size, int64_t type, 9662 /// void *name = nullptr) { 9663 /// // Allocate space for an array section first or add a base/begin for 9664 /// // pointer dereference. 9665 /// if ((size > 1 || (base != begin && maptype.IsPtrAndObj)) && 9666 /// !maptype.IsDelete) 9667 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9668 /// size*sizeof(Ty), clearToFromMember(type)); 9669 /// // Map members. 9670 /// for (unsigned i = 0; i < size; i++) { 9671 /// // For each component specified by this mapper: 9672 /// for (auto c : begin[i]->all_components) { 9673 /// if (c.hasMapper()) 9674 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 9675 /// c.arg_type, c.arg_name); 9676 /// else 9677 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 9678 /// c.arg_begin, c.arg_size, c.arg_type, 9679 /// c.arg_name); 9680 /// } 9681 /// } 9682 /// // Delete the array section. 9683 /// if (size > 1 && maptype.IsDelete) 9684 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9685 /// size*sizeof(Ty), clearToFromMember(type)); 9686 /// } 9687 /// \endcode 9688 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 9689 CodeGenFunction *CGF) { 9690 if (UDMMap.count(D) > 0) 9691 return; 9692 ASTContext &C = CGM.getContext(); 9693 QualType Ty = D->getType(); 9694 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 9695 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 9696 auto *MapperVarDecl = 9697 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 9698 SourceLocation Loc = D->getLocation(); 9699 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 9700 9701 // Prepare mapper function arguments and attributes. 9702 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9703 C.VoidPtrTy, ImplicitParamDecl::Other); 9704 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9705 ImplicitParamDecl::Other); 9706 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9707 C.VoidPtrTy, ImplicitParamDecl::Other); 9708 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9709 ImplicitParamDecl::Other); 9710 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9711 ImplicitParamDecl::Other); 9712 ImplicitParamDecl NameArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9713 ImplicitParamDecl::Other); 9714 FunctionArgList Args; 9715 Args.push_back(&HandleArg); 9716 Args.push_back(&BaseArg); 9717 Args.push_back(&BeginArg); 9718 Args.push_back(&SizeArg); 9719 Args.push_back(&TypeArg); 9720 Args.push_back(&NameArg); 9721 const CGFunctionInfo &FnInfo = 9722 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 9723 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 9724 SmallString<64> TyStr; 9725 llvm::raw_svector_ostream Out(TyStr); 9726 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 9727 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 9728 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 9729 Name, &CGM.getModule()); 9730 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 9731 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 9732 // Start the mapper function code generation. 9733 CodeGenFunction MapperCGF(CGM); 9734 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 9735 // Compute the starting and end addresses of array elements. 9736 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 9737 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 9738 C.getPointerType(Int64Ty), Loc); 9739 // Prepare common arguments for array initiation and deletion. 9740 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 9741 MapperCGF.GetAddrOfLocalVar(&HandleArg), 9742 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9743 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 9744 MapperCGF.GetAddrOfLocalVar(&BaseArg), 9745 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9746 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 9747 MapperCGF.GetAddrOfLocalVar(&BeginArg), 9748 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9749 // Convert the size in bytes into the number of array elements. 9750 Size = MapperCGF.Builder.CreateExactUDiv( 9751 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9752 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 9753 BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy)); 9754 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 9755 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 9756 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 9757 C.getPointerType(Int64Ty), Loc); 9758 llvm::Value *MapName = MapperCGF.EmitLoadOfScalar( 9759 MapperCGF.GetAddrOfLocalVar(&NameArg), 9760 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9761 9762 // Emit array initiation if this is an array section and \p MapType indicates 9763 // that memory allocation is required. 9764 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 9765 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9766 MapName, ElementSize, HeadBB, /*IsInit=*/true); 9767 9768 // Emit a for loop to iterate through SizeArg of elements and map all of them. 9769 9770 // Emit the loop header block. 9771 MapperCGF.EmitBlock(HeadBB); 9772 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 9773 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 9774 // Evaluate whether the initial condition is satisfied. 9775 llvm::Value *IsEmpty = 9776 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 9777 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 9778 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 9779 9780 // Emit the loop body block. 9781 MapperCGF.EmitBlock(BodyBB); 9782 llvm::BasicBlock *LastBB = BodyBB; 9783 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 9784 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 9785 PtrPHI->addIncoming(PtrBegin, EntryBB); 9786 Address PtrCurrent = 9787 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 9788 .getAlignment() 9789 .alignmentOfArrayElement(ElementSize)); 9790 // Privatize the declared variable of mapper to be the current array element. 9791 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 9792 Scope.addPrivate(MapperVarDecl, [PtrCurrent]() { return PtrCurrent; }); 9793 (void)Scope.Privatize(); 9794 9795 // Get map clause information. Fill up the arrays with all mapped variables. 9796 MappableExprsHandler::MapCombinedInfoTy Info; 9797 MappableExprsHandler MEHandler(*D, MapperCGF); 9798 MEHandler.generateAllInfoForMapper(Info); 9799 9800 // Call the runtime API __tgt_mapper_num_components to get the number of 9801 // pre-existing components. 9802 llvm::Value *OffloadingArgs[] = {Handle}; 9803 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 9804 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 9805 OMPRTL___tgt_mapper_num_components), 9806 OffloadingArgs); 9807 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 9808 PreviousSize, 9809 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 9810 9811 // Fill up the runtime mapper handle for all components. 9812 for (unsigned I = 0; I < Info.BasePointers.size(); ++I) { 9813 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 9814 *Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9815 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9816 Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9817 llvm::Value *CurSizeArg = Info.Sizes[I]; 9818 llvm::Value *CurNameArg = 9819 (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 9820 ? llvm::ConstantPointerNull::get(CGM.VoidPtrTy) 9821 : emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]); 9822 9823 // Extract the MEMBER_OF field from the map type. 9824 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(Info.Types[I]); 9825 llvm::Value *MemberMapType = 9826 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9827 9828 // Combine the map type inherited from user-defined mapper with that 9829 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9830 // bits of the \a MapType, which is the input argument of the mapper 9831 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9832 // bits of MemberMapType. 9833 // [OpenMP 5.0], 1.2.6. map-type decay. 9834 // | alloc | to | from | tofrom | release | delete 9835 // ---------------------------------------------------------- 9836 // alloc | alloc | alloc | alloc | alloc | release | delete 9837 // to | alloc | to | alloc | to | release | delete 9838 // from | alloc | alloc | from | from | release | delete 9839 // tofrom | alloc | to | from | tofrom | release | delete 9840 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9841 MapType, 9842 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9843 MappableExprsHandler::OMP_MAP_FROM)); 9844 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9845 llvm::BasicBlock *AllocElseBB = 9846 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9847 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9848 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9849 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9850 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9851 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9852 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9853 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9854 MapperCGF.EmitBlock(AllocBB); 9855 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9856 MemberMapType, 9857 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9858 MappableExprsHandler::OMP_MAP_FROM))); 9859 MapperCGF.Builder.CreateBr(EndBB); 9860 MapperCGF.EmitBlock(AllocElseBB); 9861 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9862 LeftToFrom, 9863 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9864 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9865 // In case of to, clear OMP_MAP_FROM. 9866 MapperCGF.EmitBlock(ToBB); 9867 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9868 MemberMapType, 9869 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9870 MapperCGF.Builder.CreateBr(EndBB); 9871 MapperCGF.EmitBlock(ToElseBB); 9872 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9873 LeftToFrom, 9874 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9875 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9876 // In case of from, clear OMP_MAP_TO. 9877 MapperCGF.EmitBlock(FromBB); 9878 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9879 MemberMapType, 9880 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9881 // In case of tofrom, do nothing. 9882 MapperCGF.EmitBlock(EndBB); 9883 LastBB = EndBB; 9884 llvm::PHINode *CurMapType = 9885 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9886 CurMapType->addIncoming(AllocMapType, AllocBB); 9887 CurMapType->addIncoming(ToMapType, ToBB); 9888 CurMapType->addIncoming(FromMapType, FromBB); 9889 CurMapType->addIncoming(MemberMapType, ToElseBB); 9890 9891 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9892 CurSizeArg, CurMapType, CurNameArg}; 9893 if (Info.Mappers[I]) { 9894 // Call the corresponding mapper function. 9895 llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc( 9896 cast<OMPDeclareMapperDecl>(Info.Mappers[I])); 9897 assert(MapperFunc && "Expect a valid mapper function is available."); 9898 MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs); 9899 } else { 9900 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9901 // data structure. 9902 MapperCGF.EmitRuntimeCall( 9903 OMPBuilder.getOrCreateRuntimeFunction( 9904 CGM.getModule(), OMPRTL___tgt_push_mapper_component), 9905 OffloadingArgs); 9906 } 9907 } 9908 9909 // Update the pointer to point to the next element that needs to be mapped, 9910 // and check whether we have mapped all elements. 9911 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9912 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9913 PtrPHI->addIncoming(PtrNext, LastBB); 9914 llvm::Value *IsDone = 9915 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9916 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9917 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9918 9919 MapperCGF.EmitBlock(ExitBB); 9920 // Emit array deletion if this is an array section and \p MapType indicates 9921 // that deletion is required. 9922 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9923 MapName, ElementSize, DoneBB, /*IsInit=*/false); 9924 9925 // Emit the function exit block. 9926 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9927 MapperCGF.FinishFunction(); 9928 UDMMap.try_emplace(D, Fn); 9929 if (CGF) { 9930 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9931 Decls.second.push_back(D); 9932 } 9933 } 9934 9935 /// Emit the array initialization or deletion portion for user-defined mapper 9936 /// code generation. First, it evaluates whether an array section is mapped and 9937 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9938 /// true, and \a MapType indicates to not delete this array, array 9939 /// initialization code is generated. If \a IsInit is false, and \a MapType 9940 /// indicates to not this array, array deletion code is generated. 9941 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9942 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9943 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9944 llvm::Value *MapName, CharUnits ElementSize, llvm::BasicBlock *ExitBB, 9945 bool IsInit) { 9946 StringRef Prefix = IsInit ? ".init" : ".del"; 9947 9948 // Evaluate if this is an array section. 9949 llvm::BasicBlock *BodyBB = 9950 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 9951 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGT( 9952 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9953 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9954 MapType, 9955 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9956 llvm::Value *DeleteCond; 9957 llvm::Value *Cond; 9958 if (IsInit) { 9959 // base != begin? 9960 llvm::Value *BaseIsBegin = MapperCGF.Builder.CreateIsNotNull( 9961 MapperCGF.Builder.CreatePtrDiff(Base, Begin)); 9962 // IsPtrAndObj? 9963 llvm::Value *PtrAndObjBit = MapperCGF.Builder.CreateAnd( 9964 MapType, 9965 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_PTR_AND_OBJ)); 9966 PtrAndObjBit = MapperCGF.Builder.CreateIsNotNull(PtrAndObjBit); 9967 BaseIsBegin = MapperCGF.Builder.CreateAnd(BaseIsBegin, PtrAndObjBit); 9968 Cond = MapperCGF.Builder.CreateOr(IsArray, BaseIsBegin); 9969 DeleteCond = MapperCGF.Builder.CreateIsNull( 9970 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9971 } else { 9972 Cond = IsArray; 9973 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9974 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9975 } 9976 Cond = MapperCGF.Builder.CreateAnd(Cond, DeleteCond); 9977 MapperCGF.Builder.CreateCondBr(Cond, BodyBB, ExitBB); 9978 9979 MapperCGF.EmitBlock(BodyBB); 9980 // Get the array size by multiplying element size and element number (i.e., \p 9981 // Size). 9982 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9983 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9984 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9985 // memory allocation/deletion purpose only. 9986 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9987 MapType, 9988 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9989 MappableExprsHandler::OMP_MAP_FROM))); 9990 MapTypeArg = MapperCGF.Builder.CreateOr( 9991 MapTypeArg, 9992 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_IMPLICIT)); 9993 9994 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9995 // data structure. 9996 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, 9997 ArraySize, MapTypeArg, MapName}; 9998 MapperCGF.EmitRuntimeCall( 9999 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 10000 OMPRTL___tgt_push_mapper_component), 10001 OffloadingArgs); 10002 } 10003 10004 llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc( 10005 const OMPDeclareMapperDecl *D) { 10006 auto I = UDMMap.find(D); 10007 if (I != UDMMap.end()) 10008 return I->second; 10009 emitUserDefinedMapper(D); 10010 return UDMMap.lookup(D); 10011 } 10012 10013 void CGOpenMPRuntime::emitTargetNumIterationsCall( 10014 CodeGenFunction &CGF, const OMPExecutableDirective &D, 10015 llvm::Value *DeviceID, 10016 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 10017 const OMPLoopDirective &D)> 10018 SizeEmitter) { 10019 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 10020 const OMPExecutableDirective *TD = &D; 10021 // Get nested teams distribute kind directive, if any. 10022 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 10023 TD = getNestedDistributeDirective(CGM.getContext(), D); 10024 if (!TD) 10025 return; 10026 const auto *LD = cast<OMPLoopDirective>(TD); 10027 auto &&CodeGen = [LD, DeviceID, SizeEmitter, &D, this](CodeGenFunction &CGF, 10028 PrePostActionTy &) { 10029 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 10030 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10031 llvm::Value *Args[] = {RTLoc, DeviceID, NumIterations}; 10032 CGF.EmitRuntimeCall( 10033 OMPBuilder.getOrCreateRuntimeFunction( 10034 CGM.getModule(), OMPRTL___kmpc_push_target_tripcount_mapper), 10035 Args); 10036 } 10037 }; 10038 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 10039 } 10040 10041 void CGOpenMPRuntime::emitTargetCall( 10042 CodeGenFunction &CGF, const OMPExecutableDirective &D, 10043 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 10044 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 10045 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 10046 const OMPLoopDirective &D)> 10047 SizeEmitter) { 10048 if (!CGF.HaveInsertPoint()) 10049 return; 10050 10051 assert(OutlinedFn && "Invalid outlined function!"); 10052 10053 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 10054 D.hasClausesOfKind<OMPNowaitClause>(); 10055 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 10056 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 10057 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 10058 PrePostActionTy &) { 10059 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10060 }; 10061 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 10062 10063 CodeGenFunction::OMPTargetDataInfo InputInfo; 10064 llvm::Value *MapTypesArray = nullptr; 10065 llvm::Value *MapNamesArray = nullptr; 10066 // Fill up the pointer arrays and transfer execution to the device. 10067 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 10068 &MapTypesArray, &MapNamesArray, &CS, RequiresOuterTask, 10069 &CapturedVars, 10070 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 10071 if (Device.getInt() == OMPC_DEVICE_ancestor) { 10072 // Reverse offloading is not supported, so just execute on the host. 10073 if (RequiresOuterTask) { 10074 CapturedVars.clear(); 10075 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10076 } 10077 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10078 return; 10079 } 10080 10081 // On top of the arrays that were filled up, the target offloading call 10082 // takes as arguments the device id as well as the host pointer. The host 10083 // pointer is used by the runtime library to identify the current target 10084 // region, so it only has to be unique and not necessarily point to 10085 // anything. It could be the pointer to the outlined function that 10086 // implements the target region, but we aren't using that so that the 10087 // compiler doesn't need to keep that, and could therefore inline the host 10088 // function if proven worthwhile during optimization. 10089 10090 // From this point on, we need to have an ID of the target region defined. 10091 assert(OutlinedFnID && "Invalid outlined function ID!"); 10092 10093 // Emit device ID if any. 10094 llvm::Value *DeviceID; 10095 if (Device.getPointer()) { 10096 assert((Device.getInt() == OMPC_DEVICE_unknown || 10097 Device.getInt() == OMPC_DEVICE_device_num) && 10098 "Expected device_num modifier."); 10099 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer()); 10100 DeviceID = 10101 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true); 10102 } else { 10103 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10104 } 10105 10106 // Emit the number of elements in the offloading arrays. 10107 llvm::Value *PointerNum = 10108 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10109 10110 // Return value of the runtime offloading call. 10111 llvm::Value *Return; 10112 10113 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 10114 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 10115 10116 // Source location for the ident struct 10117 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10118 10119 // Emit tripcount for the target loop-based directive. 10120 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 10121 10122 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10123 // The target region is an outlined function launched by the runtime 10124 // via calls __tgt_target() or __tgt_target_teams(). 10125 // 10126 // __tgt_target() launches a target region with one team and one thread, 10127 // executing a serial region. This master thread may in turn launch 10128 // more threads within its team upon encountering a parallel region, 10129 // however, no additional teams can be launched on the device. 10130 // 10131 // __tgt_target_teams() launches a target region with one or more teams, 10132 // each with one or more threads. This call is required for target 10133 // constructs such as: 10134 // 'target teams' 10135 // 'target' / 'teams' 10136 // 'target teams distribute parallel for' 10137 // 'target parallel' 10138 // and so on. 10139 // 10140 // Note that on the host and CPU targets, the runtime implementation of 10141 // these calls simply call the outlined function without forking threads. 10142 // The outlined functions themselves have runtime calls to 10143 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 10144 // the compiler in emitTeamsCall() and emitParallelCall(). 10145 // 10146 // In contrast, on the NVPTX target, the implementation of 10147 // __tgt_target_teams() launches a GPU kernel with the requested number 10148 // of teams and threads so no additional calls to the runtime are required. 10149 if (NumTeams) { 10150 // If we have NumTeams defined this means that we have an enclosed teams 10151 // region. Therefore we also expect to have NumThreads defined. These two 10152 // values should be defined in the presence of a teams directive, 10153 // regardless of having any clauses associated. If the user is using teams 10154 // but no clauses, these two values will be the default that should be 10155 // passed to the runtime library - a 32-bit integer with the value zero. 10156 assert(NumThreads && "Thread limit expression should be available along " 10157 "with number of teams."); 10158 llvm::Value *OffloadingArgs[] = {RTLoc, 10159 DeviceID, 10160 OutlinedFnID, 10161 PointerNum, 10162 InputInfo.BasePointersArray.getPointer(), 10163 InputInfo.PointersArray.getPointer(), 10164 InputInfo.SizesArray.getPointer(), 10165 MapTypesArray, 10166 MapNamesArray, 10167 InputInfo.MappersArray.getPointer(), 10168 NumTeams, 10169 NumThreads}; 10170 Return = CGF.EmitRuntimeCall( 10171 OMPBuilder.getOrCreateRuntimeFunction( 10172 CGM.getModule(), HasNowait 10173 ? OMPRTL___tgt_target_teams_nowait_mapper 10174 : OMPRTL___tgt_target_teams_mapper), 10175 OffloadingArgs); 10176 } else { 10177 llvm::Value *OffloadingArgs[] = {RTLoc, 10178 DeviceID, 10179 OutlinedFnID, 10180 PointerNum, 10181 InputInfo.BasePointersArray.getPointer(), 10182 InputInfo.PointersArray.getPointer(), 10183 InputInfo.SizesArray.getPointer(), 10184 MapTypesArray, 10185 MapNamesArray, 10186 InputInfo.MappersArray.getPointer()}; 10187 Return = CGF.EmitRuntimeCall( 10188 OMPBuilder.getOrCreateRuntimeFunction( 10189 CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper 10190 : OMPRTL___tgt_target_mapper), 10191 OffloadingArgs); 10192 } 10193 10194 // Check the error code and execute the host version if required. 10195 llvm::BasicBlock *OffloadFailedBlock = 10196 CGF.createBasicBlock("omp_offload.failed"); 10197 llvm::BasicBlock *OffloadContBlock = 10198 CGF.createBasicBlock("omp_offload.cont"); 10199 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 10200 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 10201 10202 CGF.EmitBlock(OffloadFailedBlock); 10203 if (RequiresOuterTask) { 10204 CapturedVars.clear(); 10205 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10206 } 10207 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10208 CGF.EmitBranch(OffloadContBlock); 10209 10210 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 10211 }; 10212 10213 // Notify that the host version must be executed. 10214 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 10215 RequiresOuterTask](CodeGenFunction &CGF, 10216 PrePostActionTy &) { 10217 if (RequiresOuterTask) { 10218 CapturedVars.clear(); 10219 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10220 } 10221 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10222 }; 10223 10224 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 10225 &MapNamesArray, &CapturedVars, RequiresOuterTask, 10226 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 10227 // Fill up the arrays with all the captured variables. 10228 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 10229 10230 // Get mappable expression information. 10231 MappableExprsHandler MEHandler(D, CGF); 10232 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 10233 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet; 10234 10235 auto RI = CS.getCapturedRecordDecl()->field_begin(); 10236 auto *CV = CapturedVars.begin(); 10237 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 10238 CE = CS.capture_end(); 10239 CI != CE; ++CI, ++RI, ++CV) { 10240 MappableExprsHandler::MapCombinedInfoTy CurInfo; 10241 MappableExprsHandler::StructRangeInfoTy PartialStruct; 10242 10243 // VLA sizes are passed to the outlined region by copy and do not have map 10244 // information associated. 10245 if (CI->capturesVariableArrayType()) { 10246 CurInfo.Exprs.push_back(nullptr); 10247 CurInfo.BasePointers.push_back(*CV); 10248 CurInfo.Pointers.push_back(*CV); 10249 CurInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 10250 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 10251 // Copy to the device as an argument. No need to retrieve it. 10252 CurInfo.Types.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 10253 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 10254 MappableExprsHandler::OMP_MAP_IMPLICIT); 10255 CurInfo.Mappers.push_back(nullptr); 10256 } else { 10257 // If we have any information in the map clause, we use it, otherwise we 10258 // just do a default mapping. 10259 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct); 10260 if (!CI->capturesThis()) 10261 MappedVarSet.insert(CI->getCapturedVar()); 10262 else 10263 MappedVarSet.insert(nullptr); 10264 if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid()) 10265 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo); 10266 // Generate correct mapping for variables captured by reference in 10267 // lambdas. 10268 if (CI->capturesVariable()) 10269 MEHandler.generateInfoForLambdaCaptures(CI->getCapturedVar(), *CV, 10270 CurInfo, LambdaPointers); 10271 } 10272 // We expect to have at least an element of information for this capture. 10273 assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) && 10274 "Non-existing map pointer for capture!"); 10275 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() && 10276 CurInfo.BasePointers.size() == CurInfo.Sizes.size() && 10277 CurInfo.BasePointers.size() == CurInfo.Types.size() && 10278 CurInfo.BasePointers.size() == CurInfo.Mappers.size() && 10279 "Inconsistent map information sizes!"); 10280 10281 // If there is an entry in PartialStruct it means we have a struct with 10282 // individual members mapped. Emit an extra combined entry. 10283 if (PartialStruct.Base.isValid()) { 10284 CombinedInfo.append(PartialStruct.PreliminaryMapData); 10285 MEHandler.emitCombinedEntry( 10286 CombinedInfo, CurInfo.Types, PartialStruct, nullptr, 10287 !PartialStruct.PreliminaryMapData.BasePointers.empty()); 10288 } 10289 10290 // We need to append the results of this capture to what we already have. 10291 CombinedInfo.append(CurInfo); 10292 } 10293 // Adjust MEMBER_OF flags for the lambdas captures. 10294 MEHandler.adjustMemberOfForLambdaCaptures( 10295 LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers, 10296 CombinedInfo.Types); 10297 // Map any list items in a map clause that were not captures because they 10298 // weren't referenced within the construct. 10299 MEHandler.generateAllInfo(CombinedInfo, MappedVarSet); 10300 10301 TargetDataInfo Info; 10302 // Fill up the arrays and create the arguments. 10303 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder); 10304 emitOffloadingArraysArgument( 10305 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 10306 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 10307 {/*ForEndTask=*/false}); 10308 10309 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10310 InputInfo.BasePointersArray = 10311 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10312 InputInfo.PointersArray = 10313 Address(Info.PointersArray, CGM.getPointerAlign()); 10314 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 10315 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 10316 MapTypesArray = Info.MapTypesArray; 10317 MapNamesArray = Info.MapNamesArray; 10318 if (RequiresOuterTask) 10319 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10320 else 10321 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10322 }; 10323 10324 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 10325 CodeGenFunction &CGF, PrePostActionTy &) { 10326 if (RequiresOuterTask) { 10327 CodeGenFunction::OMPTargetDataInfo InputInfo; 10328 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 10329 } else { 10330 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 10331 } 10332 }; 10333 10334 // If we have a target function ID it means that we need to support 10335 // offloading, otherwise, just execute on the host. We need to execute on host 10336 // regardless of the conditional in the if clause if, e.g., the user do not 10337 // specify target triples. 10338 if (OutlinedFnID) { 10339 if (IfCond) { 10340 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 10341 } else { 10342 RegionCodeGenTy ThenRCG(TargetThenGen); 10343 ThenRCG(CGF); 10344 } 10345 } else { 10346 RegionCodeGenTy ElseRCG(TargetElseGen); 10347 ElseRCG(CGF); 10348 } 10349 } 10350 10351 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 10352 StringRef ParentName) { 10353 if (!S) 10354 return; 10355 10356 // Codegen OMP target directives that offload compute to the device. 10357 bool RequiresDeviceCodegen = 10358 isa<OMPExecutableDirective>(S) && 10359 isOpenMPTargetExecutionDirective( 10360 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 10361 10362 if (RequiresDeviceCodegen) { 10363 const auto &E = *cast<OMPExecutableDirective>(S); 10364 unsigned DeviceID; 10365 unsigned FileID; 10366 unsigned Line; 10367 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 10368 FileID, Line); 10369 10370 // Is this a target region that should not be emitted as an entry point? If 10371 // so just signal we are done with this target region. 10372 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 10373 ParentName, Line)) 10374 return; 10375 10376 switch (E.getDirectiveKind()) { 10377 case OMPD_target: 10378 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 10379 cast<OMPTargetDirective>(E)); 10380 break; 10381 case OMPD_target_parallel: 10382 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 10383 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 10384 break; 10385 case OMPD_target_teams: 10386 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 10387 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 10388 break; 10389 case OMPD_target_teams_distribute: 10390 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 10391 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 10392 break; 10393 case OMPD_target_teams_distribute_simd: 10394 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 10395 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 10396 break; 10397 case OMPD_target_parallel_for: 10398 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 10399 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 10400 break; 10401 case OMPD_target_parallel_for_simd: 10402 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 10403 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 10404 break; 10405 case OMPD_target_simd: 10406 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 10407 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 10408 break; 10409 case OMPD_target_teams_distribute_parallel_for: 10410 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 10411 CGM, ParentName, 10412 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 10413 break; 10414 case OMPD_target_teams_distribute_parallel_for_simd: 10415 CodeGenFunction:: 10416 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 10417 CGM, ParentName, 10418 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 10419 break; 10420 case OMPD_parallel: 10421 case OMPD_for: 10422 case OMPD_parallel_for: 10423 case OMPD_parallel_master: 10424 case OMPD_parallel_sections: 10425 case OMPD_for_simd: 10426 case OMPD_parallel_for_simd: 10427 case OMPD_cancel: 10428 case OMPD_cancellation_point: 10429 case OMPD_ordered: 10430 case OMPD_threadprivate: 10431 case OMPD_allocate: 10432 case OMPD_task: 10433 case OMPD_simd: 10434 case OMPD_tile: 10435 case OMPD_sections: 10436 case OMPD_section: 10437 case OMPD_single: 10438 case OMPD_master: 10439 case OMPD_critical: 10440 case OMPD_taskyield: 10441 case OMPD_barrier: 10442 case OMPD_taskwait: 10443 case OMPD_taskgroup: 10444 case OMPD_atomic: 10445 case OMPD_flush: 10446 case OMPD_depobj: 10447 case OMPD_scan: 10448 case OMPD_teams: 10449 case OMPD_target_data: 10450 case OMPD_target_exit_data: 10451 case OMPD_target_enter_data: 10452 case OMPD_distribute: 10453 case OMPD_distribute_simd: 10454 case OMPD_distribute_parallel_for: 10455 case OMPD_distribute_parallel_for_simd: 10456 case OMPD_teams_distribute: 10457 case OMPD_teams_distribute_simd: 10458 case OMPD_teams_distribute_parallel_for: 10459 case OMPD_teams_distribute_parallel_for_simd: 10460 case OMPD_target_update: 10461 case OMPD_declare_simd: 10462 case OMPD_declare_variant: 10463 case OMPD_begin_declare_variant: 10464 case OMPD_end_declare_variant: 10465 case OMPD_declare_target: 10466 case OMPD_end_declare_target: 10467 case OMPD_declare_reduction: 10468 case OMPD_declare_mapper: 10469 case OMPD_taskloop: 10470 case OMPD_taskloop_simd: 10471 case OMPD_master_taskloop: 10472 case OMPD_master_taskloop_simd: 10473 case OMPD_parallel_master_taskloop: 10474 case OMPD_parallel_master_taskloop_simd: 10475 case OMPD_requires: 10476 case OMPD_unknown: 10477 default: 10478 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 10479 } 10480 return; 10481 } 10482 10483 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 10484 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 10485 return; 10486 10487 scanForTargetRegionsFunctions(E->getRawStmt(), ParentName); 10488 return; 10489 } 10490 10491 // If this is a lambda function, look into its body. 10492 if (const auto *L = dyn_cast<LambdaExpr>(S)) 10493 S = L->getBody(); 10494 10495 // Keep looking for target regions recursively. 10496 for (const Stmt *II : S->children()) 10497 scanForTargetRegionsFunctions(II, ParentName); 10498 } 10499 10500 static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice) { 10501 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10502 OMPDeclareTargetDeclAttr::getDeviceType(VD); 10503 if (!DevTy) 10504 return false; 10505 // Do not emit device_type(nohost) functions for the host. 10506 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 10507 return true; 10508 // Do not emit device_type(host) functions for the device. 10509 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host) 10510 return true; 10511 return false; 10512 } 10513 10514 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 10515 // If emitting code for the host, we do not process FD here. Instead we do 10516 // the normal code generation. 10517 if (!CGM.getLangOpts().OpenMPIsDevice) { 10518 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) 10519 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD), 10520 CGM.getLangOpts().OpenMPIsDevice)) 10521 return true; 10522 return false; 10523 } 10524 10525 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 10526 // Try to detect target regions in the function. 10527 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 10528 StringRef Name = CGM.getMangledName(GD); 10529 scanForTargetRegionsFunctions(FD->getBody(), Name); 10530 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD), 10531 CGM.getLangOpts().OpenMPIsDevice)) 10532 return true; 10533 } 10534 10535 // Do not to emit function if it is not marked as declare target. 10536 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 10537 AlreadyEmittedTargetDecls.count(VD) == 0; 10538 } 10539 10540 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 10541 if (isAssumedToBeNotEmitted(cast<ValueDecl>(GD.getDecl()), 10542 CGM.getLangOpts().OpenMPIsDevice)) 10543 return true; 10544 10545 if (!CGM.getLangOpts().OpenMPIsDevice) 10546 return false; 10547 10548 // Check if there are Ctors/Dtors in this declaration and look for target 10549 // regions in it. We use the complete variant to produce the kernel name 10550 // mangling. 10551 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 10552 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 10553 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 10554 StringRef ParentName = 10555 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 10556 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 10557 } 10558 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 10559 StringRef ParentName = 10560 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 10561 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 10562 } 10563 } 10564 10565 // Do not to emit variable if it is not marked as declare target. 10566 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10567 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 10568 cast<VarDecl>(GD.getDecl())); 10569 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 10570 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10571 HasRequiresUnifiedSharedMemory)) { 10572 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 10573 return true; 10574 } 10575 return false; 10576 } 10577 10578 llvm::Constant * 10579 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 10580 const VarDecl *VD) { 10581 assert(VD->getType().isConstant(CGM.getContext()) && 10582 "Expected constant variable."); 10583 StringRef VarName; 10584 llvm::Constant *Addr; 10585 llvm::GlobalValue::LinkageTypes Linkage; 10586 QualType Ty = VD->getType(); 10587 SmallString<128> Buffer; 10588 { 10589 unsigned DeviceID; 10590 unsigned FileID; 10591 unsigned Line; 10592 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 10593 FileID, Line); 10594 llvm::raw_svector_ostream OS(Buffer); 10595 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 10596 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 10597 VarName = OS.str(); 10598 } 10599 Linkage = llvm::GlobalValue::InternalLinkage; 10600 Addr = 10601 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 10602 getDefaultFirstprivateAddressSpace()); 10603 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 10604 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 10605 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 10606 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10607 VarName, Addr, VarSize, 10608 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 10609 return Addr; 10610 } 10611 10612 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 10613 llvm::Constant *Addr) { 10614 if (CGM.getLangOpts().OMPTargetTriples.empty() && 10615 !CGM.getLangOpts().OpenMPIsDevice) 10616 return; 10617 10618 // If we have host/nohost variables, they do not need to be registered. 10619 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10620 OMPDeclareTargetDeclAttr::getDeviceType(VD); 10621 if (DevTy && DevTy.getValue() != OMPDeclareTargetDeclAttr::DT_Any) 10622 return; 10623 10624 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10625 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10626 if (!Res) { 10627 if (CGM.getLangOpts().OpenMPIsDevice) { 10628 // Register non-target variables being emitted in device code (debug info 10629 // may cause this). 10630 StringRef VarName = CGM.getMangledName(VD); 10631 EmittedNonTargetVariables.try_emplace(VarName, Addr); 10632 } 10633 return; 10634 } 10635 // Register declare target variables. 10636 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 10637 StringRef VarName; 10638 CharUnits VarSize; 10639 llvm::GlobalValue::LinkageTypes Linkage; 10640 10641 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10642 !HasRequiresUnifiedSharedMemory) { 10643 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10644 VarName = CGM.getMangledName(VD); 10645 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 10646 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 10647 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 10648 } else { 10649 VarSize = CharUnits::Zero(); 10650 } 10651 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 10652 // Temp solution to prevent optimizations of the internal variables. 10653 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 10654 // Do not create a "ref-variable" if the original is not also available 10655 // on the host. 10656 if (!OffloadEntriesInfoManager.hasDeviceGlobalVarEntryInfo(VarName)) 10657 return; 10658 std::string RefName = getName({VarName, "ref"}); 10659 if (!CGM.GetGlobalValue(RefName)) { 10660 llvm::Constant *AddrRef = 10661 getOrCreateInternalVariable(Addr->getType(), RefName); 10662 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 10663 GVAddrRef->setConstant(/*Val=*/true); 10664 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 10665 GVAddrRef->setInitializer(Addr); 10666 CGM.addCompilerUsedGlobal(GVAddrRef); 10667 } 10668 } 10669 } else { 10670 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 10671 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10672 HasRequiresUnifiedSharedMemory)) && 10673 "Declare target attribute must link or to with unified memory."); 10674 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 10675 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 10676 else 10677 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10678 10679 if (CGM.getLangOpts().OpenMPIsDevice) { 10680 VarName = Addr->getName(); 10681 Addr = nullptr; 10682 } else { 10683 VarName = getAddrOfDeclareTargetVar(VD).getName(); 10684 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 10685 } 10686 VarSize = CGM.getPointerSize(); 10687 Linkage = llvm::GlobalValue::WeakAnyLinkage; 10688 } 10689 10690 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10691 VarName, Addr, VarSize, Flags, Linkage); 10692 } 10693 10694 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 10695 if (isa<FunctionDecl>(GD.getDecl()) || 10696 isa<OMPDeclareReductionDecl>(GD.getDecl())) 10697 return emitTargetFunctions(GD); 10698 10699 return emitTargetGlobalVariable(GD); 10700 } 10701 10702 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 10703 for (const VarDecl *VD : DeferredGlobalVariables) { 10704 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10705 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10706 if (!Res) 10707 continue; 10708 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10709 !HasRequiresUnifiedSharedMemory) { 10710 CGM.EmitGlobal(VD); 10711 } else { 10712 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 10713 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10714 HasRequiresUnifiedSharedMemory)) && 10715 "Expected link clause or to clause with unified memory."); 10716 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 10717 } 10718 } 10719 } 10720 10721 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 10722 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 10723 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 10724 " Expected target-based directive."); 10725 } 10726 10727 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 10728 for (const OMPClause *Clause : D->clauselists()) { 10729 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 10730 HasRequiresUnifiedSharedMemory = true; 10731 } else if (const auto *AC = 10732 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 10733 switch (AC->getAtomicDefaultMemOrderKind()) { 10734 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 10735 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 10736 break; 10737 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 10738 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 10739 break; 10740 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 10741 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 10742 break; 10743 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 10744 break; 10745 } 10746 } 10747 } 10748 } 10749 10750 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 10751 return RequiresAtomicOrdering; 10752 } 10753 10754 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 10755 LangAS &AS) { 10756 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 10757 return false; 10758 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 10759 switch(A->getAllocatorType()) { 10760 case OMPAllocateDeclAttr::OMPNullMemAlloc: 10761 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 10762 // Not supported, fallback to the default mem space. 10763 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 10764 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 10765 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 10766 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 10767 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 10768 case OMPAllocateDeclAttr::OMPConstMemAlloc: 10769 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 10770 AS = LangAS::Default; 10771 return true; 10772 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 10773 llvm_unreachable("Expected predefined allocator for the variables with the " 10774 "static storage."); 10775 } 10776 return false; 10777 } 10778 10779 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 10780 return HasRequiresUnifiedSharedMemory; 10781 } 10782 10783 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 10784 CodeGenModule &CGM) 10785 : CGM(CGM) { 10786 if (CGM.getLangOpts().OpenMPIsDevice) { 10787 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 10788 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 10789 } 10790 } 10791 10792 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 10793 if (CGM.getLangOpts().OpenMPIsDevice) 10794 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 10795 } 10796 10797 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 10798 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 10799 return true; 10800 10801 const auto *D = cast<FunctionDecl>(GD.getDecl()); 10802 // Do not to emit function if it is marked as declare target as it was already 10803 // emitted. 10804 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 10805 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 10806 if (auto *F = dyn_cast_or_null<llvm::Function>( 10807 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 10808 return !F->isDeclaration(); 10809 return false; 10810 } 10811 return true; 10812 } 10813 10814 return !AlreadyEmittedTargetDecls.insert(D).second; 10815 } 10816 10817 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 10818 // If we don't have entries or if we are emitting code for the device, we 10819 // don't need to do anything. 10820 if (CGM.getLangOpts().OMPTargetTriples.empty() || 10821 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 10822 (OffloadEntriesInfoManager.empty() && 10823 !HasEmittedDeclareTargetRegion && 10824 !HasEmittedTargetRegion)) 10825 return nullptr; 10826 10827 // Create and register the function that handles the requires directives. 10828 ASTContext &C = CGM.getContext(); 10829 10830 llvm::Function *RequiresRegFn; 10831 { 10832 CodeGenFunction CGF(CGM); 10833 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 10834 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 10835 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 10836 RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI); 10837 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 10838 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 10839 // TODO: check for other requires clauses. 10840 // The requires directive takes effect only when a target region is 10841 // present in the compilation unit. Otherwise it is ignored and not 10842 // passed to the runtime. This avoids the runtime from throwing an error 10843 // for mismatching requires clauses across compilation units that don't 10844 // contain at least 1 target region. 10845 assert((HasEmittedTargetRegion || 10846 HasEmittedDeclareTargetRegion || 10847 !OffloadEntriesInfoManager.empty()) && 10848 "Target or declare target region expected."); 10849 if (HasRequiresUnifiedSharedMemory) 10850 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 10851 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 10852 CGM.getModule(), OMPRTL___tgt_register_requires), 10853 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 10854 CGF.FinishFunction(); 10855 } 10856 return RequiresRegFn; 10857 } 10858 10859 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 10860 const OMPExecutableDirective &D, 10861 SourceLocation Loc, 10862 llvm::Function *OutlinedFn, 10863 ArrayRef<llvm::Value *> CapturedVars) { 10864 if (!CGF.HaveInsertPoint()) 10865 return; 10866 10867 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10868 CodeGenFunction::RunCleanupsScope Scope(CGF); 10869 10870 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 10871 llvm::Value *Args[] = { 10872 RTLoc, 10873 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 10874 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 10875 llvm::SmallVector<llvm::Value *, 16> RealArgs; 10876 RealArgs.append(std::begin(Args), std::end(Args)); 10877 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 10878 10879 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 10880 CGM.getModule(), OMPRTL___kmpc_fork_teams); 10881 CGF.EmitRuntimeCall(RTLFn, RealArgs); 10882 } 10883 10884 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 10885 const Expr *NumTeams, 10886 const Expr *ThreadLimit, 10887 SourceLocation Loc) { 10888 if (!CGF.HaveInsertPoint()) 10889 return; 10890 10891 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10892 10893 llvm::Value *NumTeamsVal = 10894 NumTeams 10895 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 10896 CGF.CGM.Int32Ty, /* isSigned = */ true) 10897 : CGF.Builder.getInt32(0); 10898 10899 llvm::Value *ThreadLimitVal = 10900 ThreadLimit 10901 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 10902 CGF.CGM.Int32Ty, /* isSigned = */ true) 10903 : CGF.Builder.getInt32(0); 10904 10905 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 10906 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 10907 ThreadLimitVal}; 10908 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 10909 CGM.getModule(), OMPRTL___kmpc_push_num_teams), 10910 PushNumTeamsArgs); 10911 } 10912 10913 void CGOpenMPRuntime::emitTargetDataCalls( 10914 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10915 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 10916 if (!CGF.HaveInsertPoint()) 10917 return; 10918 10919 // Action used to replace the default codegen action and turn privatization 10920 // off. 10921 PrePostActionTy NoPrivAction; 10922 10923 // Generate the code for the opening of the data environment. Capture all the 10924 // arguments of the runtime call by reference because they are used in the 10925 // closing of the region. 10926 auto &&BeginThenGen = [this, &D, Device, &Info, 10927 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 10928 // Fill up the arrays with all the mapped variables. 10929 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 10930 10931 // Get map clause information. 10932 MappableExprsHandler MEHandler(D, CGF); 10933 MEHandler.generateAllInfo(CombinedInfo); 10934 10935 // Fill up the arrays and create the arguments. 10936 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 10937 /*IsNonContiguous=*/true); 10938 10939 llvm::Value *BasePointersArrayArg = nullptr; 10940 llvm::Value *PointersArrayArg = nullptr; 10941 llvm::Value *SizesArrayArg = nullptr; 10942 llvm::Value *MapTypesArrayArg = nullptr; 10943 llvm::Value *MapNamesArrayArg = nullptr; 10944 llvm::Value *MappersArrayArg = nullptr; 10945 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10946 SizesArrayArg, MapTypesArrayArg, 10947 MapNamesArrayArg, MappersArrayArg, Info); 10948 10949 // Emit device ID if any. 10950 llvm::Value *DeviceID = nullptr; 10951 if (Device) { 10952 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10953 CGF.Int64Ty, /*isSigned=*/true); 10954 } else { 10955 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10956 } 10957 10958 // Emit the number of elements in the offloading arrays. 10959 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10960 // 10961 // Source location for the ident struct 10962 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10963 10964 llvm::Value *OffloadingArgs[] = {RTLoc, 10965 DeviceID, 10966 PointerNum, 10967 BasePointersArrayArg, 10968 PointersArrayArg, 10969 SizesArrayArg, 10970 MapTypesArrayArg, 10971 MapNamesArrayArg, 10972 MappersArrayArg}; 10973 CGF.EmitRuntimeCall( 10974 OMPBuilder.getOrCreateRuntimeFunction( 10975 CGM.getModule(), OMPRTL___tgt_target_data_begin_mapper), 10976 OffloadingArgs); 10977 10978 // If device pointer privatization is required, emit the body of the region 10979 // here. It will have to be duplicated: with and without privatization. 10980 if (!Info.CaptureDeviceAddrMap.empty()) 10981 CodeGen(CGF); 10982 }; 10983 10984 // Generate code for the closing of the data region. 10985 auto &&EndThenGen = [this, Device, &Info, &D](CodeGenFunction &CGF, 10986 PrePostActionTy &) { 10987 assert(Info.isValid() && "Invalid data environment closing arguments."); 10988 10989 llvm::Value *BasePointersArrayArg = nullptr; 10990 llvm::Value *PointersArrayArg = nullptr; 10991 llvm::Value *SizesArrayArg = nullptr; 10992 llvm::Value *MapTypesArrayArg = nullptr; 10993 llvm::Value *MapNamesArrayArg = nullptr; 10994 llvm::Value *MappersArrayArg = nullptr; 10995 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10996 SizesArrayArg, MapTypesArrayArg, 10997 MapNamesArrayArg, MappersArrayArg, Info, 10998 {/*ForEndCall=*/true}); 10999 11000 // Emit device ID if any. 11001 llvm::Value *DeviceID = nullptr; 11002 if (Device) { 11003 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11004 CGF.Int64Ty, /*isSigned=*/true); 11005 } else { 11006 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11007 } 11008 11009 // Emit the number of elements in the offloading arrays. 11010 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 11011 11012 // Source location for the ident struct 11013 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11014 11015 llvm::Value *OffloadingArgs[] = {RTLoc, 11016 DeviceID, 11017 PointerNum, 11018 BasePointersArrayArg, 11019 PointersArrayArg, 11020 SizesArrayArg, 11021 MapTypesArrayArg, 11022 MapNamesArrayArg, 11023 MappersArrayArg}; 11024 CGF.EmitRuntimeCall( 11025 OMPBuilder.getOrCreateRuntimeFunction( 11026 CGM.getModule(), OMPRTL___tgt_target_data_end_mapper), 11027 OffloadingArgs); 11028 }; 11029 11030 // If we need device pointer privatization, we need to emit the body of the 11031 // region with no privatization in the 'else' branch of the conditional. 11032 // Otherwise, we don't have to do anything. 11033 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 11034 PrePostActionTy &) { 11035 if (!Info.CaptureDeviceAddrMap.empty()) { 11036 CodeGen.setAction(NoPrivAction); 11037 CodeGen(CGF); 11038 } 11039 }; 11040 11041 // We don't have to do anything to close the region if the if clause evaluates 11042 // to false. 11043 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 11044 11045 if (IfCond) { 11046 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 11047 } else { 11048 RegionCodeGenTy RCG(BeginThenGen); 11049 RCG(CGF); 11050 } 11051 11052 // If we don't require privatization of device pointers, we emit the body in 11053 // between the runtime calls. This avoids duplicating the body code. 11054 if (Info.CaptureDeviceAddrMap.empty()) { 11055 CodeGen.setAction(NoPrivAction); 11056 CodeGen(CGF); 11057 } 11058 11059 if (IfCond) { 11060 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 11061 } else { 11062 RegionCodeGenTy RCG(EndThenGen); 11063 RCG(CGF); 11064 } 11065 } 11066 11067 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 11068 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11069 const Expr *Device) { 11070 if (!CGF.HaveInsertPoint()) 11071 return; 11072 11073 assert((isa<OMPTargetEnterDataDirective>(D) || 11074 isa<OMPTargetExitDataDirective>(D) || 11075 isa<OMPTargetUpdateDirective>(D)) && 11076 "Expecting either target enter, exit data, or update directives."); 11077 11078 CodeGenFunction::OMPTargetDataInfo InputInfo; 11079 llvm::Value *MapTypesArray = nullptr; 11080 llvm::Value *MapNamesArray = nullptr; 11081 // Generate the code for the opening of the data environment. 11082 auto &&ThenGen = [this, &D, Device, &InputInfo, &MapTypesArray, 11083 &MapNamesArray](CodeGenFunction &CGF, PrePostActionTy &) { 11084 // Emit device ID if any. 11085 llvm::Value *DeviceID = nullptr; 11086 if (Device) { 11087 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11088 CGF.Int64Ty, /*isSigned=*/true); 11089 } else { 11090 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11091 } 11092 11093 // Emit the number of elements in the offloading arrays. 11094 llvm::Constant *PointerNum = 11095 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 11096 11097 // Source location for the ident struct 11098 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11099 11100 llvm::Value *OffloadingArgs[] = {RTLoc, 11101 DeviceID, 11102 PointerNum, 11103 InputInfo.BasePointersArray.getPointer(), 11104 InputInfo.PointersArray.getPointer(), 11105 InputInfo.SizesArray.getPointer(), 11106 MapTypesArray, 11107 MapNamesArray, 11108 InputInfo.MappersArray.getPointer()}; 11109 11110 // Select the right runtime function call for each standalone 11111 // directive. 11112 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 11113 RuntimeFunction RTLFn; 11114 switch (D.getDirectiveKind()) { 11115 case OMPD_target_enter_data: 11116 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper 11117 : OMPRTL___tgt_target_data_begin_mapper; 11118 break; 11119 case OMPD_target_exit_data: 11120 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper 11121 : OMPRTL___tgt_target_data_end_mapper; 11122 break; 11123 case OMPD_target_update: 11124 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper 11125 : OMPRTL___tgt_target_data_update_mapper; 11126 break; 11127 case OMPD_parallel: 11128 case OMPD_for: 11129 case OMPD_parallel_for: 11130 case OMPD_parallel_master: 11131 case OMPD_parallel_sections: 11132 case OMPD_for_simd: 11133 case OMPD_parallel_for_simd: 11134 case OMPD_cancel: 11135 case OMPD_cancellation_point: 11136 case OMPD_ordered: 11137 case OMPD_threadprivate: 11138 case OMPD_allocate: 11139 case OMPD_task: 11140 case OMPD_simd: 11141 case OMPD_tile: 11142 case OMPD_sections: 11143 case OMPD_section: 11144 case OMPD_single: 11145 case OMPD_master: 11146 case OMPD_critical: 11147 case OMPD_taskyield: 11148 case OMPD_barrier: 11149 case OMPD_taskwait: 11150 case OMPD_taskgroup: 11151 case OMPD_atomic: 11152 case OMPD_flush: 11153 case OMPD_depobj: 11154 case OMPD_scan: 11155 case OMPD_teams: 11156 case OMPD_target_data: 11157 case OMPD_distribute: 11158 case OMPD_distribute_simd: 11159 case OMPD_distribute_parallel_for: 11160 case OMPD_distribute_parallel_for_simd: 11161 case OMPD_teams_distribute: 11162 case OMPD_teams_distribute_simd: 11163 case OMPD_teams_distribute_parallel_for: 11164 case OMPD_teams_distribute_parallel_for_simd: 11165 case OMPD_declare_simd: 11166 case OMPD_declare_variant: 11167 case OMPD_begin_declare_variant: 11168 case OMPD_end_declare_variant: 11169 case OMPD_declare_target: 11170 case OMPD_end_declare_target: 11171 case OMPD_declare_reduction: 11172 case OMPD_declare_mapper: 11173 case OMPD_taskloop: 11174 case OMPD_taskloop_simd: 11175 case OMPD_master_taskloop: 11176 case OMPD_master_taskloop_simd: 11177 case OMPD_parallel_master_taskloop: 11178 case OMPD_parallel_master_taskloop_simd: 11179 case OMPD_target: 11180 case OMPD_target_simd: 11181 case OMPD_target_teams_distribute: 11182 case OMPD_target_teams_distribute_simd: 11183 case OMPD_target_teams_distribute_parallel_for: 11184 case OMPD_target_teams_distribute_parallel_for_simd: 11185 case OMPD_target_teams: 11186 case OMPD_target_parallel: 11187 case OMPD_target_parallel_for: 11188 case OMPD_target_parallel_for_simd: 11189 case OMPD_requires: 11190 case OMPD_unknown: 11191 default: 11192 llvm_unreachable("Unexpected standalone target data directive."); 11193 break; 11194 } 11195 CGF.EmitRuntimeCall( 11196 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), RTLFn), 11197 OffloadingArgs); 11198 }; 11199 11200 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 11201 &MapNamesArray](CodeGenFunction &CGF, 11202 PrePostActionTy &) { 11203 // Fill up the arrays with all the mapped variables. 11204 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 11205 11206 // Get map clause information. 11207 MappableExprsHandler MEHandler(D, CGF); 11208 MEHandler.generateAllInfo(CombinedInfo); 11209 11210 TargetDataInfo Info; 11211 // Fill up the arrays and create the arguments. 11212 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 11213 /*IsNonContiguous=*/true); 11214 bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 11215 D.hasClausesOfKind<OMPNowaitClause>(); 11216 emitOffloadingArraysArgument( 11217 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 11218 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 11219 {/*ForEndTask=*/false}); 11220 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 11221 InputInfo.BasePointersArray = 11222 Address(Info.BasePointersArray, CGM.getPointerAlign()); 11223 InputInfo.PointersArray = 11224 Address(Info.PointersArray, CGM.getPointerAlign()); 11225 InputInfo.SizesArray = 11226 Address(Info.SizesArray, CGM.getPointerAlign()); 11227 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 11228 MapTypesArray = Info.MapTypesArray; 11229 MapNamesArray = Info.MapNamesArray; 11230 if (RequiresOuterTask) 11231 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 11232 else 11233 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 11234 }; 11235 11236 if (IfCond) { 11237 emitIfClause(CGF, IfCond, TargetThenGen, 11238 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 11239 } else { 11240 RegionCodeGenTy ThenRCG(TargetThenGen); 11241 ThenRCG(CGF); 11242 } 11243 } 11244 11245 namespace { 11246 /// Kind of parameter in a function with 'declare simd' directive. 11247 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 11248 /// Attribute set of the parameter. 11249 struct ParamAttrTy { 11250 ParamKindTy Kind = Vector; 11251 llvm::APSInt StrideOrArg; 11252 llvm::APSInt Alignment; 11253 }; 11254 } // namespace 11255 11256 static unsigned evaluateCDTSize(const FunctionDecl *FD, 11257 ArrayRef<ParamAttrTy> ParamAttrs) { 11258 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 11259 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 11260 // of that clause. The VLEN value must be power of 2. 11261 // In other case the notion of the function`s "characteristic data type" (CDT) 11262 // is used to compute the vector length. 11263 // CDT is defined in the following order: 11264 // a) For non-void function, the CDT is the return type. 11265 // b) If the function has any non-uniform, non-linear parameters, then the 11266 // CDT is the type of the first such parameter. 11267 // c) If the CDT determined by a) or b) above is struct, union, or class 11268 // type which is pass-by-value (except for the type that maps to the 11269 // built-in complex data type), the characteristic data type is int. 11270 // d) If none of the above three cases is applicable, the CDT is int. 11271 // The VLEN is then determined based on the CDT and the size of vector 11272 // register of that ISA for which current vector version is generated. The 11273 // VLEN is computed using the formula below: 11274 // VLEN = sizeof(vector_register) / sizeof(CDT), 11275 // where vector register size specified in section 3.2.1 Registers and the 11276 // Stack Frame of original AMD64 ABI document. 11277 QualType RetType = FD->getReturnType(); 11278 if (RetType.isNull()) 11279 return 0; 11280 ASTContext &C = FD->getASTContext(); 11281 QualType CDT; 11282 if (!RetType.isNull() && !RetType->isVoidType()) { 11283 CDT = RetType; 11284 } else { 11285 unsigned Offset = 0; 11286 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 11287 if (ParamAttrs[Offset].Kind == Vector) 11288 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 11289 ++Offset; 11290 } 11291 if (CDT.isNull()) { 11292 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11293 if (ParamAttrs[I + Offset].Kind == Vector) { 11294 CDT = FD->getParamDecl(I)->getType(); 11295 break; 11296 } 11297 } 11298 } 11299 } 11300 if (CDT.isNull()) 11301 CDT = C.IntTy; 11302 CDT = CDT->getCanonicalTypeUnqualified(); 11303 if (CDT->isRecordType() || CDT->isUnionType()) 11304 CDT = C.IntTy; 11305 return C.getTypeSize(CDT); 11306 } 11307 11308 static void 11309 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 11310 const llvm::APSInt &VLENVal, 11311 ArrayRef<ParamAttrTy> ParamAttrs, 11312 OMPDeclareSimdDeclAttr::BranchStateTy State) { 11313 struct ISADataTy { 11314 char ISA; 11315 unsigned VecRegSize; 11316 }; 11317 ISADataTy ISAData[] = { 11318 { 11319 'b', 128 11320 }, // SSE 11321 { 11322 'c', 256 11323 }, // AVX 11324 { 11325 'd', 256 11326 }, // AVX2 11327 { 11328 'e', 512 11329 }, // AVX512 11330 }; 11331 llvm::SmallVector<char, 2> Masked; 11332 switch (State) { 11333 case OMPDeclareSimdDeclAttr::BS_Undefined: 11334 Masked.push_back('N'); 11335 Masked.push_back('M'); 11336 break; 11337 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11338 Masked.push_back('N'); 11339 break; 11340 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11341 Masked.push_back('M'); 11342 break; 11343 } 11344 for (char Mask : Masked) { 11345 for (const ISADataTy &Data : ISAData) { 11346 SmallString<256> Buffer; 11347 llvm::raw_svector_ostream Out(Buffer); 11348 Out << "_ZGV" << Data.ISA << Mask; 11349 if (!VLENVal) { 11350 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 11351 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 11352 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 11353 } else { 11354 Out << VLENVal; 11355 } 11356 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 11357 switch (ParamAttr.Kind){ 11358 case LinearWithVarStride: 11359 Out << 's' << ParamAttr.StrideOrArg; 11360 break; 11361 case Linear: 11362 Out << 'l'; 11363 if (ParamAttr.StrideOrArg != 1) 11364 Out << ParamAttr.StrideOrArg; 11365 break; 11366 case Uniform: 11367 Out << 'u'; 11368 break; 11369 case Vector: 11370 Out << 'v'; 11371 break; 11372 } 11373 if (!!ParamAttr.Alignment) 11374 Out << 'a' << ParamAttr.Alignment; 11375 } 11376 Out << '_' << Fn->getName(); 11377 Fn->addFnAttr(Out.str()); 11378 } 11379 } 11380 } 11381 11382 // This are the Functions that are needed to mangle the name of the 11383 // vector functions generated by the compiler, according to the rules 11384 // defined in the "Vector Function ABI specifications for AArch64", 11385 // available at 11386 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 11387 11388 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 11389 /// 11390 /// TODO: Need to implement the behavior for reference marked with a 11391 /// var or no linear modifiers (1.b in the section). For this, we 11392 /// need to extend ParamKindTy to support the linear modifiers. 11393 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 11394 QT = QT.getCanonicalType(); 11395 11396 if (QT->isVoidType()) 11397 return false; 11398 11399 if (Kind == ParamKindTy::Uniform) 11400 return false; 11401 11402 if (Kind == ParamKindTy::Linear) 11403 return false; 11404 11405 // TODO: Handle linear references with modifiers 11406 11407 if (Kind == ParamKindTy::LinearWithVarStride) 11408 return false; 11409 11410 return true; 11411 } 11412 11413 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 11414 static bool getAArch64PBV(QualType QT, ASTContext &C) { 11415 QT = QT.getCanonicalType(); 11416 unsigned Size = C.getTypeSize(QT); 11417 11418 // Only scalars and complex within 16 bytes wide set PVB to true. 11419 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 11420 return false; 11421 11422 if (QT->isFloatingType()) 11423 return true; 11424 11425 if (QT->isIntegerType()) 11426 return true; 11427 11428 if (QT->isPointerType()) 11429 return true; 11430 11431 // TODO: Add support for complex types (section 3.1.2, item 2). 11432 11433 return false; 11434 } 11435 11436 /// Computes the lane size (LS) of a return type or of an input parameter, 11437 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 11438 /// TODO: Add support for references, section 3.2.1, item 1. 11439 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 11440 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 11441 QualType PTy = QT.getCanonicalType()->getPointeeType(); 11442 if (getAArch64PBV(PTy, C)) 11443 return C.getTypeSize(PTy); 11444 } 11445 if (getAArch64PBV(QT, C)) 11446 return C.getTypeSize(QT); 11447 11448 return C.getTypeSize(C.getUIntPtrType()); 11449 } 11450 11451 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 11452 // signature of the scalar function, as defined in 3.2.2 of the 11453 // AAVFABI. 11454 static std::tuple<unsigned, unsigned, bool> 11455 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 11456 QualType RetType = FD->getReturnType().getCanonicalType(); 11457 11458 ASTContext &C = FD->getASTContext(); 11459 11460 bool OutputBecomesInput = false; 11461 11462 llvm::SmallVector<unsigned, 8> Sizes; 11463 if (!RetType->isVoidType()) { 11464 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 11465 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 11466 OutputBecomesInput = true; 11467 } 11468 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11469 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 11470 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 11471 } 11472 11473 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 11474 // The LS of a function parameter / return value can only be a power 11475 // of 2, starting from 8 bits, up to 128. 11476 assert(std::all_of(Sizes.begin(), Sizes.end(), 11477 [](unsigned Size) { 11478 return Size == 8 || Size == 16 || Size == 32 || 11479 Size == 64 || Size == 128; 11480 }) && 11481 "Invalid size"); 11482 11483 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 11484 *std::max_element(std::begin(Sizes), std::end(Sizes)), 11485 OutputBecomesInput); 11486 } 11487 11488 /// Mangle the parameter part of the vector function name according to 11489 /// their OpenMP classification. The mangling function is defined in 11490 /// section 3.5 of the AAVFABI. 11491 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 11492 SmallString<256> Buffer; 11493 llvm::raw_svector_ostream Out(Buffer); 11494 for (const auto &ParamAttr : ParamAttrs) { 11495 switch (ParamAttr.Kind) { 11496 case LinearWithVarStride: 11497 Out << "ls" << ParamAttr.StrideOrArg; 11498 break; 11499 case Linear: 11500 Out << 'l'; 11501 // Don't print the step value if it is not present or if it is 11502 // equal to 1. 11503 if (ParamAttr.StrideOrArg != 1) 11504 Out << ParamAttr.StrideOrArg; 11505 break; 11506 case Uniform: 11507 Out << 'u'; 11508 break; 11509 case Vector: 11510 Out << 'v'; 11511 break; 11512 } 11513 11514 if (!!ParamAttr.Alignment) 11515 Out << 'a' << ParamAttr.Alignment; 11516 } 11517 11518 return std::string(Out.str()); 11519 } 11520 11521 // Function used to add the attribute. The parameter `VLEN` is 11522 // templated to allow the use of "x" when targeting scalable functions 11523 // for SVE. 11524 template <typename T> 11525 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 11526 char ISA, StringRef ParSeq, 11527 StringRef MangledName, bool OutputBecomesInput, 11528 llvm::Function *Fn) { 11529 SmallString<256> Buffer; 11530 llvm::raw_svector_ostream Out(Buffer); 11531 Out << Prefix << ISA << LMask << VLEN; 11532 if (OutputBecomesInput) 11533 Out << "v"; 11534 Out << ParSeq << "_" << MangledName; 11535 Fn->addFnAttr(Out.str()); 11536 } 11537 11538 // Helper function to generate the Advanced SIMD names depending on 11539 // the value of the NDS when simdlen is not present. 11540 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 11541 StringRef Prefix, char ISA, 11542 StringRef ParSeq, StringRef MangledName, 11543 bool OutputBecomesInput, 11544 llvm::Function *Fn) { 11545 switch (NDS) { 11546 case 8: 11547 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11548 OutputBecomesInput, Fn); 11549 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 11550 OutputBecomesInput, Fn); 11551 break; 11552 case 16: 11553 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11554 OutputBecomesInput, Fn); 11555 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11556 OutputBecomesInput, Fn); 11557 break; 11558 case 32: 11559 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11560 OutputBecomesInput, Fn); 11561 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11562 OutputBecomesInput, Fn); 11563 break; 11564 case 64: 11565 case 128: 11566 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11567 OutputBecomesInput, Fn); 11568 break; 11569 default: 11570 llvm_unreachable("Scalar type is too wide."); 11571 } 11572 } 11573 11574 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 11575 static void emitAArch64DeclareSimdFunction( 11576 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 11577 ArrayRef<ParamAttrTy> ParamAttrs, 11578 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 11579 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 11580 11581 // Get basic data for building the vector signature. 11582 const auto Data = getNDSWDS(FD, ParamAttrs); 11583 const unsigned NDS = std::get<0>(Data); 11584 const unsigned WDS = std::get<1>(Data); 11585 const bool OutputBecomesInput = std::get<2>(Data); 11586 11587 // Check the values provided via `simdlen` by the user. 11588 // 1. A `simdlen(1)` doesn't produce vector signatures, 11589 if (UserVLEN == 1) { 11590 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11591 DiagnosticsEngine::Warning, 11592 "The clause simdlen(1) has no effect when targeting aarch64."); 11593 CGM.getDiags().Report(SLoc, DiagID); 11594 return; 11595 } 11596 11597 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 11598 // Advanced SIMD output. 11599 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 11600 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11601 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 11602 "power of 2 when targeting Advanced SIMD."); 11603 CGM.getDiags().Report(SLoc, DiagID); 11604 return; 11605 } 11606 11607 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 11608 // limits. 11609 if (ISA == 's' && UserVLEN != 0) { 11610 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 11611 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11612 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 11613 "lanes in the architectural constraints " 11614 "for SVE (min is 128-bit, max is " 11615 "2048-bit, by steps of 128-bit)"); 11616 CGM.getDiags().Report(SLoc, DiagID) << WDS; 11617 return; 11618 } 11619 } 11620 11621 // Sort out parameter sequence. 11622 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 11623 StringRef Prefix = "_ZGV"; 11624 // Generate simdlen from user input (if any). 11625 if (UserVLEN) { 11626 if (ISA == 's') { 11627 // SVE generates only a masked function. 11628 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11629 OutputBecomesInput, Fn); 11630 } else { 11631 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11632 // Advanced SIMD generates one or two functions, depending on 11633 // the `[not]inbranch` clause. 11634 switch (State) { 11635 case OMPDeclareSimdDeclAttr::BS_Undefined: 11636 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11637 OutputBecomesInput, Fn); 11638 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11639 OutputBecomesInput, Fn); 11640 break; 11641 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11642 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11643 OutputBecomesInput, Fn); 11644 break; 11645 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11646 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11647 OutputBecomesInput, Fn); 11648 break; 11649 } 11650 } 11651 } else { 11652 // If no user simdlen is provided, follow the AAVFABI rules for 11653 // generating the vector length. 11654 if (ISA == 's') { 11655 // SVE, section 3.4.1, item 1. 11656 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 11657 OutputBecomesInput, Fn); 11658 } else { 11659 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11660 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 11661 // two vector names depending on the use of the clause 11662 // `[not]inbranch`. 11663 switch (State) { 11664 case OMPDeclareSimdDeclAttr::BS_Undefined: 11665 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11666 OutputBecomesInput, Fn); 11667 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11668 OutputBecomesInput, Fn); 11669 break; 11670 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11671 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11672 OutputBecomesInput, Fn); 11673 break; 11674 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11675 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11676 OutputBecomesInput, Fn); 11677 break; 11678 } 11679 } 11680 } 11681 } 11682 11683 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 11684 llvm::Function *Fn) { 11685 ASTContext &C = CGM.getContext(); 11686 FD = FD->getMostRecentDecl(); 11687 // Map params to their positions in function decl. 11688 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 11689 if (isa<CXXMethodDecl>(FD)) 11690 ParamPositions.try_emplace(FD, 0); 11691 unsigned ParamPos = ParamPositions.size(); 11692 for (const ParmVarDecl *P : FD->parameters()) { 11693 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 11694 ++ParamPos; 11695 } 11696 while (FD) { 11697 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 11698 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 11699 // Mark uniform parameters. 11700 for (const Expr *E : Attr->uniforms()) { 11701 E = E->IgnoreParenImpCasts(); 11702 unsigned Pos; 11703 if (isa<CXXThisExpr>(E)) { 11704 Pos = ParamPositions[FD]; 11705 } else { 11706 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11707 ->getCanonicalDecl(); 11708 Pos = ParamPositions[PVD]; 11709 } 11710 ParamAttrs[Pos].Kind = Uniform; 11711 } 11712 // Get alignment info. 11713 auto NI = Attr->alignments_begin(); 11714 for (const Expr *E : Attr->aligneds()) { 11715 E = E->IgnoreParenImpCasts(); 11716 unsigned Pos; 11717 QualType ParmTy; 11718 if (isa<CXXThisExpr>(E)) { 11719 Pos = ParamPositions[FD]; 11720 ParmTy = E->getType(); 11721 } else { 11722 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11723 ->getCanonicalDecl(); 11724 Pos = ParamPositions[PVD]; 11725 ParmTy = PVD->getType(); 11726 } 11727 ParamAttrs[Pos].Alignment = 11728 (*NI) 11729 ? (*NI)->EvaluateKnownConstInt(C) 11730 : llvm::APSInt::getUnsigned( 11731 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 11732 .getQuantity()); 11733 ++NI; 11734 } 11735 // Mark linear parameters. 11736 auto SI = Attr->steps_begin(); 11737 auto MI = Attr->modifiers_begin(); 11738 for (const Expr *E : Attr->linears()) { 11739 E = E->IgnoreParenImpCasts(); 11740 unsigned Pos; 11741 // Rescaling factor needed to compute the linear parameter 11742 // value in the mangled name. 11743 unsigned PtrRescalingFactor = 1; 11744 if (isa<CXXThisExpr>(E)) { 11745 Pos = ParamPositions[FD]; 11746 } else { 11747 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11748 ->getCanonicalDecl(); 11749 Pos = ParamPositions[PVD]; 11750 if (auto *P = dyn_cast<PointerType>(PVD->getType())) 11751 PtrRescalingFactor = CGM.getContext() 11752 .getTypeSizeInChars(P->getPointeeType()) 11753 .getQuantity(); 11754 } 11755 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 11756 ParamAttr.Kind = Linear; 11757 // Assuming a stride of 1, for `linear` without modifiers. 11758 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1); 11759 if (*SI) { 11760 Expr::EvalResult Result; 11761 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 11762 if (const auto *DRE = 11763 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 11764 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 11765 ParamAttr.Kind = LinearWithVarStride; 11766 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 11767 ParamPositions[StridePVD->getCanonicalDecl()]); 11768 } 11769 } 11770 } else { 11771 ParamAttr.StrideOrArg = Result.Val.getInt(); 11772 } 11773 } 11774 // If we are using a linear clause on a pointer, we need to 11775 // rescale the value of linear_step with the byte size of the 11776 // pointee type. 11777 if (Linear == ParamAttr.Kind) 11778 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor; 11779 ++SI; 11780 ++MI; 11781 } 11782 llvm::APSInt VLENVal; 11783 SourceLocation ExprLoc; 11784 const Expr *VLENExpr = Attr->getSimdlen(); 11785 if (VLENExpr) { 11786 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 11787 ExprLoc = VLENExpr->getExprLoc(); 11788 } 11789 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 11790 if (CGM.getTriple().isX86()) { 11791 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 11792 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 11793 unsigned VLEN = VLENVal.getExtValue(); 11794 StringRef MangledName = Fn->getName(); 11795 if (CGM.getTarget().hasFeature("sve")) 11796 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11797 MangledName, 's', 128, Fn, ExprLoc); 11798 if (CGM.getTarget().hasFeature("neon")) 11799 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11800 MangledName, 'n', 128, Fn, ExprLoc); 11801 } 11802 } 11803 FD = FD->getPreviousDecl(); 11804 } 11805 } 11806 11807 namespace { 11808 /// Cleanup action for doacross support. 11809 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 11810 public: 11811 static const int DoacrossFinArgs = 2; 11812 11813 private: 11814 llvm::FunctionCallee RTLFn; 11815 llvm::Value *Args[DoacrossFinArgs]; 11816 11817 public: 11818 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 11819 ArrayRef<llvm::Value *> CallArgs) 11820 : RTLFn(RTLFn) { 11821 assert(CallArgs.size() == DoacrossFinArgs); 11822 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11823 } 11824 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11825 if (!CGF.HaveInsertPoint()) 11826 return; 11827 CGF.EmitRuntimeCall(RTLFn, Args); 11828 } 11829 }; 11830 } // namespace 11831 11832 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11833 const OMPLoopDirective &D, 11834 ArrayRef<Expr *> NumIterations) { 11835 if (!CGF.HaveInsertPoint()) 11836 return; 11837 11838 ASTContext &C = CGM.getContext(); 11839 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 11840 RecordDecl *RD; 11841 if (KmpDimTy.isNull()) { 11842 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 11843 // kmp_int64 lo; // lower 11844 // kmp_int64 up; // upper 11845 // kmp_int64 st; // stride 11846 // }; 11847 RD = C.buildImplicitRecord("kmp_dim"); 11848 RD->startDefinition(); 11849 addFieldToRecordDecl(C, RD, Int64Ty); 11850 addFieldToRecordDecl(C, RD, Int64Ty); 11851 addFieldToRecordDecl(C, RD, Int64Ty); 11852 RD->completeDefinition(); 11853 KmpDimTy = C.getRecordType(RD); 11854 } else { 11855 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 11856 } 11857 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 11858 QualType ArrayTy = 11859 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 11860 11861 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 11862 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 11863 enum { LowerFD = 0, UpperFD, StrideFD }; 11864 // Fill dims with data. 11865 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 11866 LValue DimsLVal = CGF.MakeAddrLValue( 11867 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 11868 // dims.upper = num_iterations; 11869 LValue UpperLVal = CGF.EmitLValueForField( 11870 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 11871 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 11872 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(), 11873 Int64Ty, NumIterations[I]->getExprLoc()); 11874 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 11875 // dims.stride = 1; 11876 LValue StrideLVal = CGF.EmitLValueForField( 11877 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 11878 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 11879 StrideLVal); 11880 } 11881 11882 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 11883 // kmp_int32 num_dims, struct kmp_dim * dims); 11884 llvm::Value *Args[] = { 11885 emitUpdateLocation(CGF, D.getBeginLoc()), 11886 getThreadID(CGF, D.getBeginLoc()), 11887 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 11888 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11889 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 11890 CGM.VoidPtrTy)}; 11891 11892 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11893 CGM.getModule(), OMPRTL___kmpc_doacross_init); 11894 CGF.EmitRuntimeCall(RTLFn, Args); 11895 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 11896 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 11897 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11898 CGM.getModule(), OMPRTL___kmpc_doacross_fini); 11899 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11900 llvm::makeArrayRef(FiniArgs)); 11901 } 11902 11903 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11904 const OMPDependClause *C) { 11905 QualType Int64Ty = 11906 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 11907 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 11908 QualType ArrayTy = CGM.getContext().getConstantArrayType( 11909 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 11910 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 11911 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 11912 const Expr *CounterVal = C->getLoopData(I); 11913 assert(CounterVal); 11914 llvm::Value *CntVal = CGF.EmitScalarConversion( 11915 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 11916 CounterVal->getExprLoc()); 11917 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 11918 /*Volatile=*/false, Int64Ty); 11919 } 11920 llvm::Value *Args[] = { 11921 emitUpdateLocation(CGF, C->getBeginLoc()), 11922 getThreadID(CGF, C->getBeginLoc()), 11923 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 11924 llvm::FunctionCallee RTLFn; 11925 if (C->getDependencyKind() == OMPC_DEPEND_source) { 11926 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 11927 OMPRTL___kmpc_doacross_post); 11928 } else { 11929 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 11930 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 11931 OMPRTL___kmpc_doacross_wait); 11932 } 11933 CGF.EmitRuntimeCall(RTLFn, Args); 11934 } 11935 11936 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 11937 llvm::FunctionCallee Callee, 11938 ArrayRef<llvm::Value *> Args) const { 11939 assert(Loc.isValid() && "Outlined function call location must be valid."); 11940 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 11941 11942 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 11943 if (Fn->doesNotThrow()) { 11944 CGF.EmitNounwindRuntimeCall(Fn, Args); 11945 return; 11946 } 11947 } 11948 CGF.EmitRuntimeCall(Callee, Args); 11949 } 11950 11951 void CGOpenMPRuntime::emitOutlinedFunctionCall( 11952 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 11953 ArrayRef<llvm::Value *> Args) const { 11954 emitCall(CGF, Loc, OutlinedFn, Args); 11955 } 11956 11957 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 11958 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 11959 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 11960 HasEmittedDeclareTargetRegion = true; 11961 } 11962 11963 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 11964 const VarDecl *NativeParam, 11965 const VarDecl *TargetParam) const { 11966 return CGF.GetAddrOfLocalVar(NativeParam); 11967 } 11968 11969 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11970 const VarDecl *VD) { 11971 if (!VD) 11972 return Address::invalid(); 11973 Address UntiedAddr = Address::invalid(); 11974 Address UntiedRealAddr = Address::invalid(); 11975 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 11976 if (It != FunctionToUntiedTaskStackMap.end()) { 11977 const UntiedLocalVarsAddressesMap &UntiedData = 11978 UntiedLocalVarsStack[It->second]; 11979 auto I = UntiedData.find(VD); 11980 if (I != UntiedData.end()) { 11981 UntiedAddr = I->second.first; 11982 UntiedRealAddr = I->second.second; 11983 } 11984 } 11985 const VarDecl *CVD = VD->getCanonicalDecl(); 11986 if (CVD->hasAttr<OMPAllocateDeclAttr>()) { 11987 // Use the default allocation. 11988 if (!isAllocatableDecl(VD)) 11989 return UntiedAddr; 11990 llvm::Value *Size; 11991 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11992 if (CVD->getType()->isVariablyModifiedType()) { 11993 Size = CGF.getTypeSize(CVD->getType()); 11994 // Align the size: ((size + align - 1) / align) * align 11995 Size = CGF.Builder.CreateNUWAdd( 11996 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11997 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11998 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11999 } else { 12000 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 12001 Size = CGM.getSize(Sz.alignTo(Align)); 12002 } 12003 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 12004 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 12005 assert(AA->getAllocator() && 12006 "Expected allocator expression for non-default allocator."); 12007 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 12008 // According to the standard, the original allocator type is a enum 12009 // (integer). Convert to pointer type, if required. 12010 Allocator = CGF.EmitScalarConversion( 12011 Allocator, AA->getAllocator()->getType(), CGF.getContext().VoidPtrTy, 12012 AA->getAllocator()->getExprLoc()); 12013 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 12014 12015 llvm::Value *Addr = 12016 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 12017 CGM.getModule(), OMPRTL___kmpc_alloc), 12018 Args, getName({CVD->getName(), ".void.addr"})); 12019 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12020 CGM.getModule(), OMPRTL___kmpc_free); 12021 QualType Ty = CGM.getContext().getPointerType(CVD->getType()); 12022 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12023 Addr, CGF.ConvertTypeForMem(Ty), getName({CVD->getName(), ".addr"})); 12024 if (UntiedAddr.isValid()) 12025 CGF.EmitStoreOfScalar(Addr, UntiedAddr, /*Volatile=*/false, Ty); 12026 12027 // Cleanup action for allocate support. 12028 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 12029 llvm::FunctionCallee RTLFn; 12030 unsigned LocEncoding; 12031 Address Addr; 12032 const Expr *Allocator; 12033 12034 public: 12035 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, unsigned LocEncoding, 12036 Address Addr, const Expr *Allocator) 12037 : RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr), 12038 Allocator(Allocator) {} 12039 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 12040 if (!CGF.HaveInsertPoint()) 12041 return; 12042 llvm::Value *Args[3]; 12043 Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( 12044 CGF, SourceLocation::getFromRawEncoding(LocEncoding)); 12045 Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12046 Addr.getPointer(), CGF.VoidPtrTy); 12047 llvm::Value *AllocVal = CGF.EmitScalarExpr(Allocator); 12048 // According to the standard, the original allocator type is a enum 12049 // (integer). Convert to pointer type, if required. 12050 AllocVal = CGF.EmitScalarConversion(AllocVal, Allocator->getType(), 12051 CGF.getContext().VoidPtrTy, 12052 Allocator->getExprLoc()); 12053 Args[2] = AllocVal; 12054 12055 CGF.EmitRuntimeCall(RTLFn, Args); 12056 } 12057 }; 12058 Address VDAddr = 12059 UntiedRealAddr.isValid() ? UntiedRealAddr : Address(Addr, Align); 12060 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>( 12061 NormalAndEHCleanup, FiniRTLFn, CVD->getLocation().getRawEncoding(), 12062 VDAddr, AA->getAllocator()); 12063 if (UntiedRealAddr.isValid()) 12064 if (auto *Region = 12065 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 12066 Region->emitUntiedSwitch(CGF); 12067 return VDAddr; 12068 } 12069 return UntiedAddr; 12070 } 12071 12072 bool CGOpenMPRuntime::isLocalVarInUntiedTask(CodeGenFunction &CGF, 12073 const VarDecl *VD) const { 12074 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 12075 if (It == FunctionToUntiedTaskStackMap.end()) 12076 return false; 12077 return UntiedLocalVarsStack[It->second].count(VD) > 0; 12078 } 12079 12080 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 12081 CodeGenModule &CGM, const OMPLoopDirective &S) 12082 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 12083 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12084 if (!NeedToPush) 12085 return; 12086 NontemporalDeclsSet &DS = 12087 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 12088 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 12089 for (const Stmt *Ref : C->private_refs()) { 12090 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 12091 const ValueDecl *VD; 12092 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 12093 VD = DRE->getDecl(); 12094 } else { 12095 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 12096 assert((ME->isImplicitCXXThis() || 12097 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 12098 "Expected member of current class."); 12099 VD = ME->getMemberDecl(); 12100 } 12101 DS.insert(VD); 12102 } 12103 } 12104 } 12105 12106 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 12107 if (!NeedToPush) 12108 return; 12109 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 12110 } 12111 12112 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII( 12113 CodeGenFunction &CGF, 12114 const llvm::MapVector<CanonicalDeclPtr<const VarDecl>, 12115 std::pair<Address, Address>> &LocalVars) 12116 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) { 12117 if (!NeedToPush) 12118 return; 12119 CGM.getOpenMPRuntime().FunctionToUntiedTaskStackMap.try_emplace( 12120 CGF.CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size()); 12121 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars); 12122 } 12123 12124 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::~UntiedTaskLocalDeclsRAII() { 12125 if (!NeedToPush) 12126 return; 12127 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back(); 12128 } 12129 12130 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 12131 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12132 12133 return llvm::any_of( 12134 CGM.getOpenMPRuntime().NontemporalDeclsStack, 12135 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 12136 } 12137 12138 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 12139 const OMPExecutableDirective &S, 12140 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 12141 const { 12142 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 12143 // Vars in target/task regions must be excluded completely. 12144 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 12145 isOpenMPTaskingDirective(S.getDirectiveKind())) { 12146 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12147 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 12148 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 12149 for (const CapturedStmt::Capture &Cap : CS->captures()) { 12150 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 12151 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 12152 } 12153 } 12154 // Exclude vars in private clauses. 12155 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 12156 for (const Expr *Ref : C->varlists()) { 12157 if (!Ref->getType()->isScalarType()) 12158 continue; 12159 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12160 if (!DRE) 12161 continue; 12162 NeedToCheckForLPCs.insert(DRE->getDecl()); 12163 } 12164 } 12165 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 12166 for (const Expr *Ref : C->varlists()) { 12167 if (!Ref->getType()->isScalarType()) 12168 continue; 12169 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12170 if (!DRE) 12171 continue; 12172 NeedToCheckForLPCs.insert(DRE->getDecl()); 12173 } 12174 } 12175 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12176 for (const Expr *Ref : C->varlists()) { 12177 if (!Ref->getType()->isScalarType()) 12178 continue; 12179 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12180 if (!DRE) 12181 continue; 12182 NeedToCheckForLPCs.insert(DRE->getDecl()); 12183 } 12184 } 12185 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 12186 for (const Expr *Ref : C->varlists()) { 12187 if (!Ref->getType()->isScalarType()) 12188 continue; 12189 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12190 if (!DRE) 12191 continue; 12192 NeedToCheckForLPCs.insert(DRE->getDecl()); 12193 } 12194 } 12195 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 12196 for (const Expr *Ref : C->varlists()) { 12197 if (!Ref->getType()->isScalarType()) 12198 continue; 12199 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12200 if (!DRE) 12201 continue; 12202 NeedToCheckForLPCs.insert(DRE->getDecl()); 12203 } 12204 } 12205 for (const Decl *VD : NeedToCheckForLPCs) { 12206 for (const LastprivateConditionalData &Data : 12207 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 12208 if (Data.DeclToUniqueName.count(VD) > 0) { 12209 if (!Data.Disabled) 12210 NeedToAddForLPCsAsDisabled.insert(VD); 12211 break; 12212 } 12213 } 12214 } 12215 } 12216 12217 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12218 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 12219 : CGM(CGF.CGM), 12220 Action((CGM.getLangOpts().OpenMP >= 50 && 12221 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 12222 [](const OMPLastprivateClause *C) { 12223 return C->getKind() == 12224 OMPC_LASTPRIVATE_conditional; 12225 })) 12226 ? ActionToDo::PushAsLastprivateConditional 12227 : ActionToDo::DoNotPush) { 12228 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12229 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 12230 return; 12231 assert(Action == ActionToDo::PushAsLastprivateConditional && 12232 "Expected a push action."); 12233 LastprivateConditionalData &Data = 12234 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12235 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12236 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 12237 continue; 12238 12239 for (const Expr *Ref : C->varlists()) { 12240 Data.DeclToUniqueName.insert(std::make_pair( 12241 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 12242 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 12243 } 12244 } 12245 Data.IVLVal = IVLVal; 12246 Data.Fn = CGF.CurFn; 12247 } 12248 12249 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12250 CodeGenFunction &CGF, const OMPExecutableDirective &S) 12251 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 12252 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12253 if (CGM.getLangOpts().OpenMP < 50) 12254 return; 12255 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 12256 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 12257 if (!NeedToAddForLPCsAsDisabled.empty()) { 12258 Action = ActionToDo::DisableLastprivateConditional; 12259 LastprivateConditionalData &Data = 12260 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12261 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 12262 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 12263 Data.Fn = CGF.CurFn; 12264 Data.Disabled = true; 12265 } 12266 } 12267 12268 CGOpenMPRuntime::LastprivateConditionalRAII 12269 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 12270 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 12271 return LastprivateConditionalRAII(CGF, S); 12272 } 12273 12274 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 12275 if (CGM.getLangOpts().OpenMP < 50) 12276 return; 12277 if (Action == ActionToDo::DisableLastprivateConditional) { 12278 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12279 "Expected list of disabled private vars."); 12280 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12281 } 12282 if (Action == ActionToDo::PushAsLastprivateConditional) { 12283 assert( 12284 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12285 "Expected list of lastprivate conditional vars."); 12286 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12287 } 12288 } 12289 12290 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 12291 const VarDecl *VD) { 12292 ASTContext &C = CGM.getContext(); 12293 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 12294 if (I == LastprivateConditionalToTypes.end()) 12295 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 12296 QualType NewType; 12297 const FieldDecl *VDField; 12298 const FieldDecl *FiredField; 12299 LValue BaseLVal; 12300 auto VI = I->getSecond().find(VD); 12301 if (VI == I->getSecond().end()) { 12302 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 12303 RD->startDefinition(); 12304 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 12305 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 12306 RD->completeDefinition(); 12307 NewType = C.getRecordType(RD); 12308 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 12309 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 12310 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 12311 } else { 12312 NewType = std::get<0>(VI->getSecond()); 12313 VDField = std::get<1>(VI->getSecond()); 12314 FiredField = std::get<2>(VI->getSecond()); 12315 BaseLVal = std::get<3>(VI->getSecond()); 12316 } 12317 LValue FiredLVal = 12318 CGF.EmitLValueForField(BaseLVal, FiredField); 12319 CGF.EmitStoreOfScalar( 12320 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 12321 FiredLVal); 12322 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 12323 } 12324 12325 namespace { 12326 /// Checks if the lastprivate conditional variable is referenced in LHS. 12327 class LastprivateConditionalRefChecker final 12328 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 12329 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 12330 const Expr *FoundE = nullptr; 12331 const Decl *FoundD = nullptr; 12332 StringRef UniqueDeclName; 12333 LValue IVLVal; 12334 llvm::Function *FoundFn = nullptr; 12335 SourceLocation Loc; 12336 12337 public: 12338 bool VisitDeclRefExpr(const DeclRefExpr *E) { 12339 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12340 llvm::reverse(LPM)) { 12341 auto It = D.DeclToUniqueName.find(E->getDecl()); 12342 if (It == D.DeclToUniqueName.end()) 12343 continue; 12344 if (D.Disabled) 12345 return false; 12346 FoundE = E; 12347 FoundD = E->getDecl()->getCanonicalDecl(); 12348 UniqueDeclName = It->second; 12349 IVLVal = D.IVLVal; 12350 FoundFn = D.Fn; 12351 break; 12352 } 12353 return FoundE == E; 12354 } 12355 bool VisitMemberExpr(const MemberExpr *E) { 12356 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 12357 return false; 12358 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12359 llvm::reverse(LPM)) { 12360 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 12361 if (It == D.DeclToUniqueName.end()) 12362 continue; 12363 if (D.Disabled) 12364 return false; 12365 FoundE = E; 12366 FoundD = E->getMemberDecl()->getCanonicalDecl(); 12367 UniqueDeclName = It->second; 12368 IVLVal = D.IVLVal; 12369 FoundFn = D.Fn; 12370 break; 12371 } 12372 return FoundE == E; 12373 } 12374 bool VisitStmt(const Stmt *S) { 12375 for (const Stmt *Child : S->children()) { 12376 if (!Child) 12377 continue; 12378 if (const auto *E = dyn_cast<Expr>(Child)) 12379 if (!E->isGLValue()) 12380 continue; 12381 if (Visit(Child)) 12382 return true; 12383 } 12384 return false; 12385 } 12386 explicit LastprivateConditionalRefChecker( 12387 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 12388 : LPM(LPM) {} 12389 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 12390 getFoundData() const { 12391 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 12392 } 12393 }; 12394 } // namespace 12395 12396 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 12397 LValue IVLVal, 12398 StringRef UniqueDeclName, 12399 LValue LVal, 12400 SourceLocation Loc) { 12401 // Last updated loop counter for the lastprivate conditional var. 12402 // int<xx> last_iv = 0; 12403 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 12404 llvm::Constant *LastIV = 12405 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 12406 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 12407 IVLVal.getAlignment().getAsAlign()); 12408 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 12409 12410 // Last value of the lastprivate conditional. 12411 // decltype(priv_a) last_a; 12412 llvm::Constant *Last = getOrCreateInternalVariable( 12413 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 12414 cast<llvm::GlobalVariable>(Last)->setAlignment( 12415 LVal.getAlignment().getAsAlign()); 12416 LValue LastLVal = 12417 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 12418 12419 // Global loop counter. Required to handle inner parallel-for regions. 12420 // iv 12421 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 12422 12423 // #pragma omp critical(a) 12424 // if (last_iv <= iv) { 12425 // last_iv = iv; 12426 // last_a = priv_a; 12427 // } 12428 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 12429 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 12430 Action.Enter(CGF); 12431 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 12432 // (last_iv <= iv) ? Check if the variable is updated and store new 12433 // value in global var. 12434 llvm::Value *CmpRes; 12435 if (IVLVal.getType()->isSignedIntegerType()) { 12436 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 12437 } else { 12438 assert(IVLVal.getType()->isUnsignedIntegerType() && 12439 "Loop iteration variable must be integer."); 12440 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 12441 } 12442 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 12443 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 12444 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 12445 // { 12446 CGF.EmitBlock(ThenBB); 12447 12448 // last_iv = iv; 12449 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 12450 12451 // last_a = priv_a; 12452 switch (CGF.getEvaluationKind(LVal.getType())) { 12453 case TEK_Scalar: { 12454 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 12455 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 12456 break; 12457 } 12458 case TEK_Complex: { 12459 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 12460 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 12461 break; 12462 } 12463 case TEK_Aggregate: 12464 llvm_unreachable( 12465 "Aggregates are not supported in lastprivate conditional."); 12466 } 12467 // } 12468 CGF.EmitBranch(ExitBB); 12469 // There is no need to emit line number for unconditional branch. 12470 (void)ApplyDebugLocation::CreateEmpty(CGF); 12471 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 12472 }; 12473 12474 if (CGM.getLangOpts().OpenMPSimd) { 12475 // Do not emit as a critical region as no parallel region could be emitted. 12476 RegionCodeGenTy ThenRCG(CodeGen); 12477 ThenRCG(CGF); 12478 } else { 12479 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 12480 } 12481 } 12482 12483 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 12484 const Expr *LHS) { 12485 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12486 return; 12487 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 12488 if (!Checker.Visit(LHS)) 12489 return; 12490 const Expr *FoundE; 12491 const Decl *FoundD; 12492 StringRef UniqueDeclName; 12493 LValue IVLVal; 12494 llvm::Function *FoundFn; 12495 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 12496 Checker.getFoundData(); 12497 if (FoundFn != CGF.CurFn) { 12498 // Special codegen for inner parallel regions. 12499 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 12500 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 12501 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 12502 "Lastprivate conditional is not found in outer region."); 12503 QualType StructTy = std::get<0>(It->getSecond()); 12504 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 12505 LValue PrivLVal = CGF.EmitLValue(FoundE); 12506 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12507 PrivLVal.getAddress(CGF), 12508 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 12509 LValue BaseLVal = 12510 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 12511 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 12512 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 12513 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 12514 FiredLVal, llvm::AtomicOrdering::Unordered, 12515 /*IsVolatile=*/true, /*isInit=*/false); 12516 return; 12517 } 12518 12519 // Private address of the lastprivate conditional in the current context. 12520 // priv_a 12521 LValue LVal = CGF.EmitLValue(FoundE); 12522 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 12523 FoundE->getExprLoc()); 12524 } 12525 12526 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 12527 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12528 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 12529 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12530 return; 12531 auto Range = llvm::reverse(LastprivateConditionalStack); 12532 auto It = llvm::find_if( 12533 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 12534 if (It == Range.end() || It->Fn != CGF.CurFn) 12535 return; 12536 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 12537 assert(LPCI != LastprivateConditionalToTypes.end() && 12538 "Lastprivates must be registered already."); 12539 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12540 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 12541 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 12542 for (const auto &Pair : It->DeclToUniqueName) { 12543 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 12544 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 12545 continue; 12546 auto I = LPCI->getSecond().find(Pair.first); 12547 assert(I != LPCI->getSecond().end() && 12548 "Lastprivate must be rehistered already."); 12549 // bool Cmp = priv_a.Fired != 0; 12550 LValue BaseLVal = std::get<3>(I->getSecond()); 12551 LValue FiredLVal = 12552 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 12553 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 12554 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 12555 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 12556 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 12557 // if (Cmp) { 12558 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 12559 CGF.EmitBlock(ThenBB); 12560 Address Addr = CGF.GetAddrOfLocalVar(VD); 12561 LValue LVal; 12562 if (VD->getType()->isReferenceType()) 12563 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 12564 AlignmentSource::Decl); 12565 else 12566 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 12567 AlignmentSource::Decl); 12568 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 12569 D.getBeginLoc()); 12570 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 12571 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 12572 // } 12573 } 12574 } 12575 12576 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 12577 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 12578 SourceLocation Loc) { 12579 if (CGF.getLangOpts().OpenMP < 50) 12580 return; 12581 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 12582 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 12583 "Unknown lastprivate conditional variable."); 12584 StringRef UniqueName = It->second; 12585 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 12586 // The variable was not updated in the region - exit. 12587 if (!GV) 12588 return; 12589 LValue LPLVal = CGF.MakeAddrLValue( 12590 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 12591 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 12592 CGF.EmitStoreOfScalar(Res, PrivLVal); 12593 } 12594 12595 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 12596 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12597 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12598 llvm_unreachable("Not supported in SIMD-only mode"); 12599 } 12600 12601 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 12602 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12603 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12604 llvm_unreachable("Not supported in SIMD-only mode"); 12605 } 12606 12607 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 12608 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12609 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 12610 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 12611 bool Tied, unsigned &NumberOfParts) { 12612 llvm_unreachable("Not supported in SIMD-only mode"); 12613 } 12614 12615 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 12616 SourceLocation Loc, 12617 llvm::Function *OutlinedFn, 12618 ArrayRef<llvm::Value *> CapturedVars, 12619 const Expr *IfCond) { 12620 llvm_unreachable("Not supported in SIMD-only mode"); 12621 } 12622 12623 void CGOpenMPSIMDRuntime::emitCriticalRegion( 12624 CodeGenFunction &CGF, StringRef CriticalName, 12625 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 12626 const Expr *Hint) { 12627 llvm_unreachable("Not supported in SIMD-only mode"); 12628 } 12629 12630 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 12631 const RegionCodeGenTy &MasterOpGen, 12632 SourceLocation Loc) { 12633 llvm_unreachable("Not supported in SIMD-only mode"); 12634 } 12635 12636 void CGOpenMPSIMDRuntime::emitMaskedRegion(CodeGenFunction &CGF, 12637 const RegionCodeGenTy &MasterOpGen, 12638 SourceLocation Loc, 12639 const Expr *Filter) { 12640 llvm_unreachable("Not supported in SIMD-only mode"); 12641 } 12642 12643 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 12644 SourceLocation Loc) { 12645 llvm_unreachable("Not supported in SIMD-only mode"); 12646 } 12647 12648 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 12649 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 12650 SourceLocation Loc) { 12651 llvm_unreachable("Not supported in SIMD-only mode"); 12652 } 12653 12654 void CGOpenMPSIMDRuntime::emitSingleRegion( 12655 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 12656 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 12657 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 12658 ArrayRef<const Expr *> AssignmentOps) { 12659 llvm_unreachable("Not supported in SIMD-only mode"); 12660 } 12661 12662 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 12663 const RegionCodeGenTy &OrderedOpGen, 12664 SourceLocation Loc, 12665 bool IsThreads) { 12666 llvm_unreachable("Not supported in SIMD-only mode"); 12667 } 12668 12669 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 12670 SourceLocation Loc, 12671 OpenMPDirectiveKind Kind, 12672 bool EmitChecks, 12673 bool ForceSimpleCall) { 12674 llvm_unreachable("Not supported in SIMD-only mode"); 12675 } 12676 12677 void CGOpenMPSIMDRuntime::emitForDispatchInit( 12678 CodeGenFunction &CGF, SourceLocation Loc, 12679 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 12680 bool Ordered, const DispatchRTInput &DispatchValues) { 12681 llvm_unreachable("Not supported in SIMD-only mode"); 12682 } 12683 12684 void CGOpenMPSIMDRuntime::emitForStaticInit( 12685 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 12686 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 12687 llvm_unreachable("Not supported in SIMD-only mode"); 12688 } 12689 12690 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 12691 CodeGenFunction &CGF, SourceLocation Loc, 12692 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 12693 llvm_unreachable("Not supported in SIMD-only mode"); 12694 } 12695 12696 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 12697 SourceLocation Loc, 12698 unsigned IVSize, 12699 bool IVSigned) { 12700 llvm_unreachable("Not supported in SIMD-only mode"); 12701 } 12702 12703 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 12704 SourceLocation Loc, 12705 OpenMPDirectiveKind DKind) { 12706 llvm_unreachable("Not supported in SIMD-only mode"); 12707 } 12708 12709 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 12710 SourceLocation Loc, 12711 unsigned IVSize, bool IVSigned, 12712 Address IL, Address LB, 12713 Address UB, Address ST) { 12714 llvm_unreachable("Not supported in SIMD-only mode"); 12715 } 12716 12717 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 12718 llvm::Value *NumThreads, 12719 SourceLocation Loc) { 12720 llvm_unreachable("Not supported in SIMD-only mode"); 12721 } 12722 12723 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 12724 ProcBindKind ProcBind, 12725 SourceLocation Loc) { 12726 llvm_unreachable("Not supported in SIMD-only mode"); 12727 } 12728 12729 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 12730 const VarDecl *VD, 12731 Address VDAddr, 12732 SourceLocation Loc) { 12733 llvm_unreachable("Not supported in SIMD-only mode"); 12734 } 12735 12736 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 12737 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 12738 CodeGenFunction *CGF) { 12739 llvm_unreachable("Not supported in SIMD-only mode"); 12740 } 12741 12742 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 12743 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 12744 llvm_unreachable("Not supported in SIMD-only mode"); 12745 } 12746 12747 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 12748 ArrayRef<const Expr *> Vars, 12749 SourceLocation Loc, 12750 llvm::AtomicOrdering AO) { 12751 llvm_unreachable("Not supported in SIMD-only mode"); 12752 } 12753 12754 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 12755 const OMPExecutableDirective &D, 12756 llvm::Function *TaskFunction, 12757 QualType SharedsTy, Address Shareds, 12758 const Expr *IfCond, 12759 const OMPTaskDataTy &Data) { 12760 llvm_unreachable("Not supported in SIMD-only mode"); 12761 } 12762 12763 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 12764 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 12765 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 12766 const Expr *IfCond, const OMPTaskDataTy &Data) { 12767 llvm_unreachable("Not supported in SIMD-only mode"); 12768 } 12769 12770 void CGOpenMPSIMDRuntime::emitReduction( 12771 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 12772 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 12773 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 12774 assert(Options.SimpleReduction && "Only simple reduction is expected."); 12775 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 12776 ReductionOps, Options); 12777 } 12778 12779 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 12780 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 12781 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 12782 llvm_unreachable("Not supported in SIMD-only mode"); 12783 } 12784 12785 void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 12786 SourceLocation Loc, 12787 bool IsWorksharingReduction) { 12788 llvm_unreachable("Not supported in SIMD-only mode"); 12789 } 12790 12791 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 12792 SourceLocation Loc, 12793 ReductionCodeGen &RCG, 12794 unsigned N) { 12795 llvm_unreachable("Not supported in SIMD-only mode"); 12796 } 12797 12798 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 12799 SourceLocation Loc, 12800 llvm::Value *ReductionsPtr, 12801 LValue SharedLVal) { 12802 llvm_unreachable("Not supported in SIMD-only mode"); 12803 } 12804 12805 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 12806 SourceLocation Loc) { 12807 llvm_unreachable("Not supported in SIMD-only mode"); 12808 } 12809 12810 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 12811 CodeGenFunction &CGF, SourceLocation Loc, 12812 OpenMPDirectiveKind CancelRegion) { 12813 llvm_unreachable("Not supported in SIMD-only mode"); 12814 } 12815 12816 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 12817 SourceLocation Loc, const Expr *IfCond, 12818 OpenMPDirectiveKind CancelRegion) { 12819 llvm_unreachable("Not supported in SIMD-only mode"); 12820 } 12821 12822 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 12823 const OMPExecutableDirective &D, StringRef ParentName, 12824 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 12825 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 12826 llvm_unreachable("Not supported in SIMD-only mode"); 12827 } 12828 12829 void CGOpenMPSIMDRuntime::emitTargetCall( 12830 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12831 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 12832 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 12833 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 12834 const OMPLoopDirective &D)> 12835 SizeEmitter) { 12836 llvm_unreachable("Not supported in SIMD-only mode"); 12837 } 12838 12839 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 12840 llvm_unreachable("Not supported in SIMD-only mode"); 12841 } 12842 12843 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 12844 llvm_unreachable("Not supported in SIMD-only mode"); 12845 } 12846 12847 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 12848 return false; 12849 } 12850 12851 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 12852 const OMPExecutableDirective &D, 12853 SourceLocation Loc, 12854 llvm::Function *OutlinedFn, 12855 ArrayRef<llvm::Value *> CapturedVars) { 12856 llvm_unreachable("Not supported in SIMD-only mode"); 12857 } 12858 12859 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 12860 const Expr *NumTeams, 12861 const Expr *ThreadLimit, 12862 SourceLocation Loc) { 12863 llvm_unreachable("Not supported in SIMD-only mode"); 12864 } 12865 12866 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 12867 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12868 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 12869 llvm_unreachable("Not supported in SIMD-only mode"); 12870 } 12871 12872 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 12873 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12874 const Expr *Device) { 12875 llvm_unreachable("Not supported in SIMD-only mode"); 12876 } 12877 12878 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12879 const OMPLoopDirective &D, 12880 ArrayRef<Expr *> NumIterations) { 12881 llvm_unreachable("Not supported in SIMD-only mode"); 12882 } 12883 12884 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12885 const OMPDependClause *C) { 12886 llvm_unreachable("Not supported in SIMD-only mode"); 12887 } 12888 12889 const VarDecl * 12890 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 12891 const VarDecl *NativeParam) const { 12892 llvm_unreachable("Not supported in SIMD-only mode"); 12893 } 12894 12895 Address 12896 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 12897 const VarDecl *NativeParam, 12898 const VarDecl *TargetParam) const { 12899 llvm_unreachable("Not supported in SIMD-only mode"); 12900 } 12901