1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides a class for OpenMP runtime code generation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGOpenMPRuntime.h" 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/AST/APValue.h" 19 #include "clang/AST/Attr.h" 20 #include "clang/AST/Decl.h" 21 #include "clang/AST/OpenMPClause.h" 22 #include "clang/AST/StmtOpenMP.h" 23 #include "clang/AST/StmtVisitor.h" 24 #include "clang/Basic/BitmaskEnum.h" 25 #include "clang/Basic/FileManager.h" 26 #include "clang/Basic/OpenMPKinds.h" 27 #include "clang/Basic/SourceManager.h" 28 #include "clang/CodeGen/ConstantInitBuilder.h" 29 #include "llvm/ADT/ArrayRef.h" 30 #include "llvm/ADT/SetOperations.h" 31 #include "llvm/ADT/StringExtras.h" 32 #include "llvm/Bitcode/BitcodeReader.h" 33 #include "llvm/IR/Constants.h" 34 #include "llvm/IR/DerivedTypes.h" 35 #include "llvm/IR/GlobalValue.h" 36 #include "llvm/IR/Value.h" 37 #include "llvm/Support/AtomicOrdering.h" 38 #include "llvm/Support/Format.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include <cassert> 41 #include <numeric> 42 43 using namespace clang; 44 using namespace CodeGen; 45 using namespace llvm::omp; 46 47 namespace { 48 /// Base class for handling code generation inside OpenMP regions. 49 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 50 public: 51 /// Kinds of OpenMP regions used in codegen. 52 enum CGOpenMPRegionKind { 53 /// Region with outlined function for standalone 'parallel' 54 /// directive. 55 ParallelOutlinedRegion, 56 /// Region with outlined function for standalone 'task' directive. 57 TaskOutlinedRegion, 58 /// Region for constructs that do not require function outlining, 59 /// like 'for', 'sections', 'atomic' etc. directives. 60 InlinedRegion, 61 /// Region with outlined function for standalone 'target' directive. 62 TargetRegion, 63 }; 64 65 CGOpenMPRegionInfo(const CapturedStmt &CS, 66 const CGOpenMPRegionKind RegionKind, 67 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 68 bool HasCancel) 69 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 70 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 71 72 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 73 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 74 bool HasCancel) 75 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 76 Kind(Kind), HasCancel(HasCancel) {} 77 78 /// Get a variable or parameter for storing global thread id 79 /// inside OpenMP construct. 80 virtual const VarDecl *getThreadIDVariable() const = 0; 81 82 /// Emit the captured statement body. 83 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 84 85 /// Get an LValue for the current ThreadID variable. 86 /// \return LValue for thread id variable. This LValue always has type int32*. 87 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 88 89 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 90 91 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 92 93 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 94 95 bool hasCancel() const { return HasCancel; } 96 97 static bool classof(const CGCapturedStmtInfo *Info) { 98 return Info->getKind() == CR_OpenMP; 99 } 100 101 ~CGOpenMPRegionInfo() override = default; 102 103 protected: 104 CGOpenMPRegionKind RegionKind; 105 RegionCodeGenTy CodeGen; 106 OpenMPDirectiveKind Kind; 107 bool HasCancel; 108 }; 109 110 /// API for captured statement code generation in OpenMP constructs. 111 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 112 public: 113 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 114 const RegionCodeGenTy &CodeGen, 115 OpenMPDirectiveKind Kind, bool HasCancel, 116 StringRef HelperName) 117 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 118 HasCancel), 119 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 120 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 121 } 122 123 /// Get a variable or parameter for storing global thread id 124 /// inside OpenMP construct. 125 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 126 127 /// Get the name of the capture helper. 128 StringRef getHelperName() const override { return HelperName; } 129 130 static bool classof(const CGCapturedStmtInfo *Info) { 131 return CGOpenMPRegionInfo::classof(Info) && 132 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 133 ParallelOutlinedRegion; 134 } 135 136 private: 137 /// A variable or parameter storing global thread id for OpenMP 138 /// constructs. 139 const VarDecl *ThreadIDVar; 140 StringRef HelperName; 141 }; 142 143 /// API for captured statement code generation in OpenMP constructs. 144 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 145 public: 146 class UntiedTaskActionTy final : public PrePostActionTy { 147 bool Untied; 148 const VarDecl *PartIDVar; 149 const RegionCodeGenTy UntiedCodeGen; 150 llvm::SwitchInst *UntiedSwitch = nullptr; 151 152 public: 153 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 154 const RegionCodeGenTy &UntiedCodeGen) 155 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 156 void Enter(CodeGenFunction &CGF) override { 157 if (Untied) { 158 // Emit task switching point. 159 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 160 CGF.GetAddrOfLocalVar(PartIDVar), 161 PartIDVar->getType()->castAs<PointerType>()); 162 llvm::Value *Res = 163 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 164 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 165 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 166 CGF.EmitBlock(DoneBB); 167 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 168 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 169 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 170 CGF.Builder.GetInsertBlock()); 171 emitUntiedSwitch(CGF); 172 } 173 } 174 void emitUntiedSwitch(CodeGenFunction &CGF) const { 175 if (Untied) { 176 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 177 CGF.GetAddrOfLocalVar(PartIDVar), 178 PartIDVar->getType()->castAs<PointerType>()); 179 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 180 PartIdLVal); 181 UntiedCodeGen(CGF); 182 CodeGenFunction::JumpDest CurPoint = 183 CGF.getJumpDestInCurrentScope(".untied.next."); 184 CGF.EmitBranch(CGF.ReturnBlock.getBlock()); 185 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 186 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 187 CGF.Builder.GetInsertBlock()); 188 CGF.EmitBranchThroughCleanup(CurPoint); 189 CGF.EmitBlock(CurPoint.getBlock()); 190 } 191 } 192 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 193 }; 194 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 195 const VarDecl *ThreadIDVar, 196 const RegionCodeGenTy &CodeGen, 197 OpenMPDirectiveKind Kind, bool HasCancel, 198 const UntiedTaskActionTy &Action) 199 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 200 ThreadIDVar(ThreadIDVar), Action(Action) { 201 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 202 } 203 204 /// Get a variable or parameter for storing global thread id 205 /// inside OpenMP construct. 206 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 207 208 /// Get an LValue for the current ThreadID variable. 209 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 210 211 /// Get the name of the capture helper. 212 StringRef getHelperName() const override { return ".omp_outlined."; } 213 214 void emitUntiedSwitch(CodeGenFunction &CGF) override { 215 Action.emitUntiedSwitch(CGF); 216 } 217 218 static bool classof(const CGCapturedStmtInfo *Info) { 219 return CGOpenMPRegionInfo::classof(Info) && 220 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 221 TaskOutlinedRegion; 222 } 223 224 private: 225 /// A variable or parameter storing global thread id for OpenMP 226 /// constructs. 227 const VarDecl *ThreadIDVar; 228 /// Action for emitting code for untied tasks. 229 const UntiedTaskActionTy &Action; 230 }; 231 232 /// API for inlined captured statement code generation in OpenMP 233 /// constructs. 234 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 235 public: 236 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 237 const RegionCodeGenTy &CodeGen, 238 OpenMPDirectiveKind Kind, bool HasCancel) 239 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 240 OldCSI(OldCSI), 241 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 242 243 // Retrieve the value of the context parameter. 244 llvm::Value *getContextValue() const override { 245 if (OuterRegionInfo) 246 return OuterRegionInfo->getContextValue(); 247 llvm_unreachable("No context value for inlined OpenMP region"); 248 } 249 250 void setContextValue(llvm::Value *V) override { 251 if (OuterRegionInfo) { 252 OuterRegionInfo->setContextValue(V); 253 return; 254 } 255 llvm_unreachable("No context value for inlined OpenMP region"); 256 } 257 258 /// Lookup the captured field decl for a variable. 259 const FieldDecl *lookup(const VarDecl *VD) const override { 260 if (OuterRegionInfo) 261 return OuterRegionInfo->lookup(VD); 262 // If there is no outer outlined region,no need to lookup in a list of 263 // captured variables, we can use the original one. 264 return nullptr; 265 } 266 267 FieldDecl *getThisFieldDecl() const override { 268 if (OuterRegionInfo) 269 return OuterRegionInfo->getThisFieldDecl(); 270 return nullptr; 271 } 272 273 /// Get a variable or parameter for storing global thread id 274 /// inside OpenMP construct. 275 const VarDecl *getThreadIDVariable() const override { 276 if (OuterRegionInfo) 277 return OuterRegionInfo->getThreadIDVariable(); 278 return nullptr; 279 } 280 281 /// Get an LValue for the current ThreadID variable. 282 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 283 if (OuterRegionInfo) 284 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 285 llvm_unreachable("No LValue for inlined OpenMP construct"); 286 } 287 288 /// Get the name of the capture helper. 289 StringRef getHelperName() const override { 290 if (auto *OuterRegionInfo = getOldCSI()) 291 return OuterRegionInfo->getHelperName(); 292 llvm_unreachable("No helper name for inlined OpenMP construct"); 293 } 294 295 void emitUntiedSwitch(CodeGenFunction &CGF) override { 296 if (OuterRegionInfo) 297 OuterRegionInfo->emitUntiedSwitch(CGF); 298 } 299 300 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 301 302 static bool classof(const CGCapturedStmtInfo *Info) { 303 return CGOpenMPRegionInfo::classof(Info) && 304 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 305 } 306 307 ~CGOpenMPInlinedRegionInfo() override = default; 308 309 private: 310 /// CodeGen info about outer OpenMP region. 311 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 312 CGOpenMPRegionInfo *OuterRegionInfo; 313 }; 314 315 /// API for captured statement code generation in OpenMP target 316 /// constructs. For this captures, implicit parameters are used instead of the 317 /// captured fields. The name of the target region has to be unique in a given 318 /// application so it is provided by the client, because only the client has 319 /// the information to generate that. 320 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 321 public: 322 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 323 const RegionCodeGenTy &CodeGen, StringRef HelperName) 324 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 325 /*HasCancel=*/false), 326 HelperName(HelperName) {} 327 328 /// This is unused for target regions because each starts executing 329 /// with a single thread. 330 const VarDecl *getThreadIDVariable() const override { return nullptr; } 331 332 /// Get the name of the capture helper. 333 StringRef getHelperName() const override { return HelperName; } 334 335 static bool classof(const CGCapturedStmtInfo *Info) { 336 return CGOpenMPRegionInfo::classof(Info) && 337 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 338 } 339 340 private: 341 StringRef HelperName; 342 }; 343 344 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 345 llvm_unreachable("No codegen for expressions"); 346 } 347 /// API for generation of expressions captured in a innermost OpenMP 348 /// region. 349 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 350 public: 351 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 352 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 353 OMPD_unknown, 354 /*HasCancel=*/false), 355 PrivScope(CGF) { 356 // Make sure the globals captured in the provided statement are local by 357 // using the privatization logic. We assume the same variable is not 358 // captured more than once. 359 for (const auto &C : CS.captures()) { 360 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 361 continue; 362 363 const VarDecl *VD = C.getCapturedVar(); 364 if (VD->isLocalVarDeclOrParm()) 365 continue; 366 367 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 368 /*RefersToEnclosingVariableOrCapture=*/false, 369 VD->getType().getNonReferenceType(), VK_LValue, 370 C.getLocation()); 371 PrivScope.addPrivate( 372 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 373 } 374 (void)PrivScope.Privatize(); 375 } 376 377 /// Lookup the captured field decl for a variable. 378 const FieldDecl *lookup(const VarDecl *VD) const override { 379 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 380 return FD; 381 return nullptr; 382 } 383 384 /// Emit the captured statement body. 385 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 386 llvm_unreachable("No body for expressions"); 387 } 388 389 /// Get a variable or parameter for storing global thread id 390 /// inside OpenMP construct. 391 const VarDecl *getThreadIDVariable() const override { 392 llvm_unreachable("No thread id for expressions"); 393 } 394 395 /// Get the name of the capture helper. 396 StringRef getHelperName() const override { 397 llvm_unreachable("No helper name for expressions"); 398 } 399 400 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 401 402 private: 403 /// Private scope to capture global variables. 404 CodeGenFunction::OMPPrivateScope PrivScope; 405 }; 406 407 /// RAII for emitting code of OpenMP constructs. 408 class InlinedOpenMPRegionRAII { 409 CodeGenFunction &CGF; 410 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 411 FieldDecl *LambdaThisCaptureField = nullptr; 412 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 413 bool NoInheritance = false; 414 415 public: 416 /// Constructs region for combined constructs. 417 /// \param CodeGen Code generation sequence for combined directives. Includes 418 /// a list of functions used for code generation of implicitly inlined 419 /// regions. 420 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 421 OpenMPDirectiveKind Kind, bool HasCancel, 422 bool NoInheritance = true) 423 : CGF(CGF), NoInheritance(NoInheritance) { 424 // Start emission for the construct. 425 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 426 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 427 if (NoInheritance) { 428 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 429 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 430 CGF.LambdaThisCaptureField = nullptr; 431 BlockInfo = CGF.BlockInfo; 432 CGF.BlockInfo = nullptr; 433 } 434 } 435 436 ~InlinedOpenMPRegionRAII() { 437 // Restore original CapturedStmtInfo only if we're done with code emission. 438 auto *OldCSI = 439 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 440 delete CGF.CapturedStmtInfo; 441 CGF.CapturedStmtInfo = OldCSI; 442 if (NoInheritance) { 443 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 444 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 445 CGF.BlockInfo = BlockInfo; 446 } 447 } 448 }; 449 450 /// Values for bit flags used in the ident_t to describe the fields. 451 /// All enumeric elements are named and described in accordance with the code 452 /// from https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h 453 enum OpenMPLocationFlags : unsigned { 454 /// Use trampoline for internal microtask. 455 OMP_IDENT_IMD = 0x01, 456 /// Use c-style ident structure. 457 OMP_IDENT_KMPC = 0x02, 458 /// Atomic reduction option for kmpc_reduce. 459 OMP_ATOMIC_REDUCE = 0x10, 460 /// Explicit 'barrier' directive. 461 OMP_IDENT_BARRIER_EXPL = 0x20, 462 /// Implicit barrier in code. 463 OMP_IDENT_BARRIER_IMPL = 0x40, 464 /// Implicit barrier in 'for' directive. 465 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 466 /// Implicit barrier in 'sections' directive. 467 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 468 /// Implicit barrier in 'single' directive. 469 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 470 /// Call of __kmp_for_static_init for static loop. 471 OMP_IDENT_WORK_LOOP = 0x200, 472 /// Call of __kmp_for_static_init for sections. 473 OMP_IDENT_WORK_SECTIONS = 0x400, 474 /// Call of __kmp_for_static_init for distribute. 475 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 476 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 477 }; 478 479 namespace { 480 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 481 /// Values for bit flags for marking which requires clauses have been used. 482 enum OpenMPOffloadingRequiresDirFlags : int64_t { 483 /// flag undefined. 484 OMP_REQ_UNDEFINED = 0x000, 485 /// no requires clause present. 486 OMP_REQ_NONE = 0x001, 487 /// reverse_offload clause. 488 OMP_REQ_REVERSE_OFFLOAD = 0x002, 489 /// unified_address clause. 490 OMP_REQ_UNIFIED_ADDRESS = 0x004, 491 /// unified_shared_memory clause. 492 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 493 /// dynamic_allocators clause. 494 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 495 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 496 }; 497 498 enum OpenMPOffloadingReservedDeviceIDs { 499 /// Device ID if the device was not defined, runtime should get it 500 /// from environment variables in the spec. 501 OMP_DEVICEID_UNDEF = -1, 502 }; 503 } // anonymous namespace 504 505 /// Describes ident structure that describes a source location. 506 /// All descriptions are taken from 507 /// https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h 508 /// Original structure: 509 /// typedef struct ident { 510 /// kmp_int32 reserved_1; /**< might be used in Fortran; 511 /// see above */ 512 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 513 /// KMP_IDENT_KMPC identifies this union 514 /// member */ 515 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 516 /// see above */ 517 ///#if USE_ITT_BUILD 518 /// /* but currently used for storing 519 /// region-specific ITT */ 520 /// /* contextual information. */ 521 ///#endif /* USE_ITT_BUILD */ 522 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 523 /// C++ */ 524 /// char const *psource; /**< String describing the source location. 525 /// The string is composed of semi-colon separated 526 // fields which describe the source file, 527 /// the function and a pair of line numbers that 528 /// delimit the construct. 529 /// */ 530 /// } ident_t; 531 enum IdentFieldIndex { 532 /// might be used in Fortran 533 IdentField_Reserved_1, 534 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 535 IdentField_Flags, 536 /// Not really used in Fortran any more 537 IdentField_Reserved_2, 538 /// Source[4] in Fortran, do not use for C++ 539 IdentField_Reserved_3, 540 /// String describing the source location. The string is composed of 541 /// semi-colon separated fields which describe the source file, the function 542 /// and a pair of line numbers that delimit the construct. 543 IdentField_PSource 544 }; 545 546 /// Schedule types for 'omp for' loops (these enumerators are taken from 547 /// the enum sched_type in kmp.h). 548 enum OpenMPSchedType { 549 /// Lower bound for default (unordered) versions. 550 OMP_sch_lower = 32, 551 OMP_sch_static_chunked = 33, 552 OMP_sch_static = 34, 553 OMP_sch_dynamic_chunked = 35, 554 OMP_sch_guided_chunked = 36, 555 OMP_sch_runtime = 37, 556 OMP_sch_auto = 38, 557 /// static with chunk adjustment (e.g., simd) 558 OMP_sch_static_balanced_chunked = 45, 559 /// Lower bound for 'ordered' versions. 560 OMP_ord_lower = 64, 561 OMP_ord_static_chunked = 65, 562 OMP_ord_static = 66, 563 OMP_ord_dynamic_chunked = 67, 564 OMP_ord_guided_chunked = 68, 565 OMP_ord_runtime = 69, 566 OMP_ord_auto = 70, 567 OMP_sch_default = OMP_sch_static, 568 /// dist_schedule types 569 OMP_dist_sch_static_chunked = 91, 570 OMP_dist_sch_static = 92, 571 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 572 /// Set if the monotonic schedule modifier was present. 573 OMP_sch_modifier_monotonic = (1 << 29), 574 /// Set if the nonmonotonic schedule modifier was present. 575 OMP_sch_modifier_nonmonotonic = (1 << 30), 576 }; 577 578 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 579 /// region. 580 class CleanupTy final : public EHScopeStack::Cleanup { 581 PrePostActionTy *Action; 582 583 public: 584 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 585 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 586 if (!CGF.HaveInsertPoint()) 587 return; 588 Action->Exit(CGF); 589 } 590 }; 591 592 } // anonymous namespace 593 594 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 595 CodeGenFunction::RunCleanupsScope Scope(CGF); 596 if (PrePostAction) { 597 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 598 Callback(CodeGen, CGF, *PrePostAction); 599 } else { 600 PrePostActionTy Action; 601 Callback(CodeGen, CGF, Action); 602 } 603 } 604 605 /// Check if the combiner is a call to UDR combiner and if it is so return the 606 /// UDR decl used for reduction. 607 static const OMPDeclareReductionDecl * 608 getReductionInit(const Expr *ReductionOp) { 609 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 610 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 611 if (const auto *DRE = 612 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 613 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 614 return DRD; 615 return nullptr; 616 } 617 618 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 619 const OMPDeclareReductionDecl *DRD, 620 const Expr *InitOp, 621 Address Private, Address Original, 622 QualType Ty) { 623 if (DRD->getInitializer()) { 624 std::pair<llvm::Function *, llvm::Function *> Reduction = 625 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 626 const auto *CE = cast<CallExpr>(InitOp); 627 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 628 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 629 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 630 const auto *LHSDRE = 631 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 632 const auto *RHSDRE = 633 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 634 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 635 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 636 [=]() { return Private; }); 637 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 638 [=]() { return Original; }); 639 (void)PrivateScope.Privatize(); 640 RValue Func = RValue::get(Reduction.second); 641 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 642 CGF.EmitIgnoredExpr(InitOp); 643 } else { 644 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 645 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 646 auto *GV = new llvm::GlobalVariable( 647 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 648 llvm::GlobalValue::PrivateLinkage, Init, Name); 649 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 650 RValue InitRVal; 651 switch (CGF.getEvaluationKind(Ty)) { 652 case TEK_Scalar: 653 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 654 break; 655 case TEK_Complex: 656 InitRVal = 657 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 658 break; 659 case TEK_Aggregate: { 660 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_LValue); 661 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, LV); 662 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 663 /*IsInitializer=*/false); 664 return; 665 } 666 } 667 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_PRValue); 668 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 669 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 670 /*IsInitializer=*/false); 671 } 672 } 673 674 /// Emit initialization of arrays of complex types. 675 /// \param DestAddr Address of the array. 676 /// \param Type Type of array. 677 /// \param Init Initial expression of array. 678 /// \param SrcAddr Address of the original array. 679 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 680 QualType Type, bool EmitDeclareReductionInit, 681 const Expr *Init, 682 const OMPDeclareReductionDecl *DRD, 683 Address SrcAddr = Address::invalid()) { 684 // Perform element-by-element initialization. 685 QualType ElementTy; 686 687 // Drill down to the base element type on both arrays. 688 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 689 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 690 DestAddr = 691 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 692 if (DRD) 693 SrcAddr = 694 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 695 696 llvm::Value *SrcBegin = nullptr; 697 if (DRD) 698 SrcBegin = SrcAddr.getPointer(); 699 llvm::Value *DestBegin = DestAddr.getPointer(); 700 // Cast from pointer to array type to pointer to single element. 701 llvm::Value *DestEnd = 702 CGF.Builder.CreateGEP(DestAddr.getElementType(), DestBegin, NumElements); 703 // The basic structure here is a while-do loop. 704 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 705 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 706 llvm::Value *IsEmpty = 707 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 708 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 709 710 // Enter the loop body, making that address the current address. 711 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 712 CGF.EmitBlock(BodyBB); 713 714 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 715 716 llvm::PHINode *SrcElementPHI = nullptr; 717 Address SrcElementCurrent = Address::invalid(); 718 if (DRD) { 719 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 720 "omp.arraycpy.srcElementPast"); 721 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 722 SrcElementCurrent = 723 Address(SrcElementPHI, 724 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 725 } 726 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 727 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 728 DestElementPHI->addIncoming(DestBegin, EntryBB); 729 Address DestElementCurrent = 730 Address(DestElementPHI, 731 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 732 733 // Emit copy. 734 { 735 CodeGenFunction::RunCleanupsScope InitScope(CGF); 736 if (EmitDeclareReductionInit) { 737 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 738 SrcElementCurrent, ElementTy); 739 } else 740 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 741 /*IsInitializer=*/false); 742 } 743 744 if (DRD) { 745 // Shift the address forward by one element. 746 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 747 SrcAddr.getElementType(), SrcElementPHI, /*Idx0=*/1, 748 "omp.arraycpy.dest.element"); 749 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 750 } 751 752 // Shift the address forward by one element. 753 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 754 DestAddr.getElementType(), DestElementPHI, /*Idx0=*/1, 755 "omp.arraycpy.dest.element"); 756 // Check whether we've reached the end. 757 llvm::Value *Done = 758 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 759 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 760 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 761 762 // Done. 763 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 764 } 765 766 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 767 return CGF.EmitOMPSharedLValue(E); 768 } 769 770 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 771 const Expr *E) { 772 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 773 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 774 return LValue(); 775 } 776 777 void ReductionCodeGen::emitAggregateInitialization( 778 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 779 const OMPDeclareReductionDecl *DRD) { 780 // Emit VarDecl with copy init for arrays. 781 // Get the address of the original variable captured in current 782 // captured region. 783 const auto *PrivateVD = 784 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 785 bool EmitDeclareReductionInit = 786 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 787 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 788 EmitDeclareReductionInit, 789 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 790 : PrivateVD->getInit(), 791 DRD, SharedLVal.getAddress(CGF)); 792 } 793 794 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 795 ArrayRef<const Expr *> Origs, 796 ArrayRef<const Expr *> Privates, 797 ArrayRef<const Expr *> ReductionOps) { 798 ClausesData.reserve(Shareds.size()); 799 SharedAddresses.reserve(Shareds.size()); 800 Sizes.reserve(Shareds.size()); 801 BaseDecls.reserve(Shareds.size()); 802 const auto *IOrig = Origs.begin(); 803 const auto *IPriv = Privates.begin(); 804 const auto *IRed = ReductionOps.begin(); 805 for (const Expr *Ref : Shareds) { 806 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed); 807 std::advance(IOrig, 1); 808 std::advance(IPriv, 1); 809 std::advance(IRed, 1); 810 } 811 } 812 813 void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) { 814 assert(SharedAddresses.size() == N && OrigAddresses.size() == N && 815 "Number of generated lvalues must be exactly N."); 816 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared); 817 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared); 818 SharedAddresses.emplace_back(First, Second); 819 if (ClausesData[N].Shared == ClausesData[N].Ref) { 820 OrigAddresses.emplace_back(First, Second); 821 } else { 822 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 823 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 824 OrigAddresses.emplace_back(First, Second); 825 } 826 } 827 828 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 829 const auto *PrivateVD = 830 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 831 QualType PrivateType = PrivateVD->getType(); 832 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 833 if (!PrivateType->isVariablyModifiedType()) { 834 Sizes.emplace_back( 835 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()), 836 nullptr); 837 return; 838 } 839 llvm::Value *Size; 840 llvm::Value *SizeInChars; 841 auto *ElemType = 842 cast<llvm::PointerType>(OrigAddresses[N].first.getPointer(CGF)->getType()) 843 ->getElementType(); 844 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 845 if (AsArraySection) { 846 Size = CGF.Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF), 847 OrigAddresses[N].first.getPointer(CGF)); 848 Size = CGF.Builder.CreateNUWAdd( 849 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 850 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 851 } else { 852 SizeInChars = 853 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()); 854 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 855 } 856 Sizes.emplace_back(SizeInChars, Size); 857 CodeGenFunction::OpaqueValueMapping OpaqueMap( 858 CGF, 859 cast<OpaqueValueExpr>( 860 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 861 RValue::get(Size)); 862 CGF.EmitVariablyModifiedType(PrivateType); 863 } 864 865 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 866 llvm::Value *Size) { 867 const auto *PrivateVD = 868 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 869 QualType PrivateType = PrivateVD->getType(); 870 if (!PrivateType->isVariablyModifiedType()) { 871 assert(!Size && !Sizes[N].second && 872 "Size should be nullptr for non-variably modified reduction " 873 "items."); 874 return; 875 } 876 CodeGenFunction::OpaqueValueMapping OpaqueMap( 877 CGF, 878 cast<OpaqueValueExpr>( 879 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 880 RValue::get(Size)); 881 CGF.EmitVariablyModifiedType(PrivateType); 882 } 883 884 void ReductionCodeGen::emitInitialization( 885 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 886 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 887 assert(SharedAddresses.size() > N && "No variable was generated"); 888 const auto *PrivateVD = 889 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 890 const OMPDeclareReductionDecl *DRD = 891 getReductionInit(ClausesData[N].ReductionOp); 892 QualType PrivateType = PrivateVD->getType(); 893 PrivateAddr = CGF.Builder.CreateElementBitCast( 894 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 895 QualType SharedType = SharedAddresses[N].first.getType(); 896 SharedLVal = CGF.MakeAddrLValue( 897 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 898 CGF.ConvertTypeForMem(SharedType)), 899 SharedType, SharedAddresses[N].first.getBaseInfo(), 900 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 901 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 902 if (DRD && DRD->getInitializer()) 903 (void)DefaultInit(CGF); 904 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 905 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 906 (void)DefaultInit(CGF); 907 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 908 PrivateAddr, SharedLVal.getAddress(CGF), 909 SharedLVal.getType()); 910 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 911 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 912 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 913 PrivateVD->getType().getQualifiers(), 914 /*IsInitializer=*/false); 915 } 916 } 917 918 bool ReductionCodeGen::needCleanups(unsigned N) { 919 const auto *PrivateVD = 920 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 921 QualType PrivateType = PrivateVD->getType(); 922 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 923 return DTorKind != QualType::DK_none; 924 } 925 926 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 927 Address PrivateAddr) { 928 const auto *PrivateVD = 929 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 930 QualType PrivateType = PrivateVD->getType(); 931 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 932 if (needCleanups(N)) { 933 PrivateAddr = CGF.Builder.CreateElementBitCast( 934 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 935 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 936 } 937 } 938 939 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 940 LValue BaseLV) { 941 BaseTy = BaseTy.getNonReferenceType(); 942 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 943 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 944 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 945 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 946 } else { 947 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 948 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 949 } 950 BaseTy = BaseTy->getPointeeType(); 951 } 952 return CGF.MakeAddrLValue( 953 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 954 CGF.ConvertTypeForMem(ElTy)), 955 BaseLV.getType(), BaseLV.getBaseInfo(), 956 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 957 } 958 959 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 960 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 961 llvm::Value *Addr) { 962 Address Tmp = Address::invalid(); 963 Address TopTmp = Address::invalid(); 964 Address MostTopTmp = Address::invalid(); 965 BaseTy = BaseTy.getNonReferenceType(); 966 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 967 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 968 Tmp = CGF.CreateMemTemp(BaseTy); 969 if (TopTmp.isValid()) 970 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 971 else 972 MostTopTmp = Tmp; 973 TopTmp = Tmp; 974 BaseTy = BaseTy->getPointeeType(); 975 } 976 llvm::Type *Ty = BaseLVType; 977 if (Tmp.isValid()) 978 Ty = Tmp.getElementType(); 979 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 980 if (Tmp.isValid()) { 981 CGF.Builder.CreateStore(Addr, Tmp); 982 return MostTopTmp; 983 } 984 return Address(Addr, BaseLVAlignment); 985 } 986 987 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 988 const VarDecl *OrigVD = nullptr; 989 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 990 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 991 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 992 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 993 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 994 Base = TempASE->getBase()->IgnoreParenImpCasts(); 995 DE = cast<DeclRefExpr>(Base); 996 OrigVD = cast<VarDecl>(DE->getDecl()); 997 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 998 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 999 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1000 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1001 DE = cast<DeclRefExpr>(Base); 1002 OrigVD = cast<VarDecl>(DE->getDecl()); 1003 } 1004 return OrigVD; 1005 } 1006 1007 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1008 Address PrivateAddr) { 1009 const DeclRefExpr *DE; 1010 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1011 BaseDecls.emplace_back(OrigVD); 1012 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1013 LValue BaseLValue = 1014 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1015 OriginalBaseLValue); 1016 Address SharedAddr = SharedAddresses[N].first.getAddress(CGF); 1017 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1018 BaseLValue.getPointer(CGF), SharedAddr.getPointer()); 1019 llvm::Value *PrivatePointer = 1020 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1021 PrivateAddr.getPointer(), SharedAddr.getType()); 1022 llvm::Value *Ptr = CGF.Builder.CreateGEP( 1023 SharedAddr.getElementType(), PrivatePointer, Adjustment); 1024 return castToBase(CGF, OrigVD->getType(), 1025 SharedAddresses[N].first.getType(), 1026 OriginalBaseLValue.getAddress(CGF).getType(), 1027 OriginalBaseLValue.getAlignment(), Ptr); 1028 } 1029 BaseDecls.emplace_back( 1030 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1031 return PrivateAddr; 1032 } 1033 1034 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1035 const OMPDeclareReductionDecl *DRD = 1036 getReductionInit(ClausesData[N].ReductionOp); 1037 return DRD && DRD->getInitializer(); 1038 } 1039 1040 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1041 return CGF.EmitLoadOfPointerLValue( 1042 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1043 getThreadIDVariable()->getType()->castAs<PointerType>()); 1044 } 1045 1046 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt *S) { 1047 if (!CGF.HaveInsertPoint()) 1048 return; 1049 // 1.2.2 OpenMP Language Terminology 1050 // Structured block - An executable statement with a single entry at the 1051 // top and a single exit at the bottom. 1052 // The point of exit cannot be a branch out of the structured block. 1053 // longjmp() and throw() must not violate the entry/exit criteria. 1054 CGF.EHStack.pushTerminate(); 1055 if (S) 1056 CGF.incrementProfileCounter(S); 1057 CodeGen(CGF); 1058 CGF.EHStack.popTerminate(); 1059 } 1060 1061 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1062 CodeGenFunction &CGF) { 1063 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1064 getThreadIDVariable()->getType(), 1065 AlignmentSource::Decl); 1066 } 1067 1068 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1069 QualType FieldTy) { 1070 auto *Field = FieldDecl::Create( 1071 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1072 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1073 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1074 Field->setAccess(AS_public); 1075 DC->addDecl(Field); 1076 return Field; 1077 } 1078 1079 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1080 StringRef Separator) 1081 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1082 OMPBuilder(CGM.getModule()), OffloadEntriesInfoManager(CGM) { 1083 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1084 1085 // Initialize Types used in OpenMPIRBuilder from OMPKinds.def 1086 OMPBuilder.initialize(); 1087 loadOffloadInfoMetadata(); 1088 } 1089 1090 void CGOpenMPRuntime::clear() { 1091 InternalVars.clear(); 1092 // Clean non-target variable declarations possibly used only in debug info. 1093 for (const auto &Data : EmittedNonTargetVariables) { 1094 if (!Data.getValue().pointsToAliveValue()) 1095 continue; 1096 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1097 if (!GV) 1098 continue; 1099 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1100 continue; 1101 GV->eraseFromParent(); 1102 } 1103 } 1104 1105 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1106 SmallString<128> Buffer; 1107 llvm::raw_svector_ostream OS(Buffer); 1108 StringRef Sep = FirstSeparator; 1109 for (StringRef Part : Parts) { 1110 OS << Sep << Part; 1111 Sep = Separator; 1112 } 1113 return std::string(OS.str()); 1114 } 1115 1116 static llvm::Function * 1117 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1118 const Expr *CombinerInitializer, const VarDecl *In, 1119 const VarDecl *Out, bool IsCombiner) { 1120 // void .omp_combiner.(Ty *in, Ty *out); 1121 ASTContext &C = CGM.getContext(); 1122 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1123 FunctionArgList Args; 1124 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1125 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1126 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1127 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1128 Args.push_back(&OmpOutParm); 1129 Args.push_back(&OmpInParm); 1130 const CGFunctionInfo &FnInfo = 1131 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1132 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1133 std::string Name = CGM.getOpenMPRuntime().getName( 1134 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1135 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1136 Name, &CGM.getModule()); 1137 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1138 if (CGM.getLangOpts().Optimize) { 1139 Fn->removeFnAttr(llvm::Attribute::NoInline); 1140 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1141 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1142 } 1143 CodeGenFunction CGF(CGM); 1144 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1145 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1146 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1147 Out->getLocation()); 1148 CodeGenFunction::OMPPrivateScope Scope(CGF); 1149 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1150 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1151 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1152 .getAddress(CGF); 1153 }); 1154 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1155 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1156 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1157 .getAddress(CGF); 1158 }); 1159 (void)Scope.Privatize(); 1160 if (!IsCombiner && Out->hasInit() && 1161 !CGF.isTrivialInitializer(Out->getInit())) { 1162 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1163 Out->getType().getQualifiers(), 1164 /*IsInitializer=*/true); 1165 } 1166 if (CombinerInitializer) 1167 CGF.EmitIgnoredExpr(CombinerInitializer); 1168 Scope.ForceCleanup(); 1169 CGF.FinishFunction(); 1170 return Fn; 1171 } 1172 1173 void CGOpenMPRuntime::emitUserDefinedReduction( 1174 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1175 if (UDRMap.count(D) > 0) 1176 return; 1177 llvm::Function *Combiner = emitCombinerOrInitializer( 1178 CGM, D->getType(), D->getCombiner(), 1179 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1180 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1181 /*IsCombiner=*/true); 1182 llvm::Function *Initializer = nullptr; 1183 if (const Expr *Init = D->getInitializer()) { 1184 Initializer = emitCombinerOrInitializer( 1185 CGM, D->getType(), 1186 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1187 : nullptr, 1188 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1189 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1190 /*IsCombiner=*/false); 1191 } 1192 UDRMap.try_emplace(D, Combiner, Initializer); 1193 if (CGF) { 1194 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1195 Decls.second.push_back(D); 1196 } 1197 } 1198 1199 std::pair<llvm::Function *, llvm::Function *> 1200 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1201 auto I = UDRMap.find(D); 1202 if (I != UDRMap.end()) 1203 return I->second; 1204 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1205 return UDRMap.lookup(D); 1206 } 1207 1208 namespace { 1209 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1210 // Builder if one is present. 1211 struct PushAndPopStackRAII { 1212 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1213 bool HasCancel, llvm::omp::Directive Kind) 1214 : OMPBuilder(OMPBuilder) { 1215 if (!OMPBuilder) 1216 return; 1217 1218 // The following callback is the crucial part of clangs cleanup process. 1219 // 1220 // NOTE: 1221 // Once the OpenMPIRBuilder is used to create parallel regions (and 1222 // similar), the cancellation destination (Dest below) is determined via 1223 // IP. That means if we have variables to finalize we split the block at IP, 1224 // use the new block (=BB) as destination to build a JumpDest (via 1225 // getJumpDestInCurrentScope(BB)) which then is fed to 1226 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1227 // to push & pop an FinalizationInfo object. 1228 // The FiniCB will still be needed but at the point where the 1229 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1230 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1231 assert(IP.getBlock()->end() == IP.getPoint() && 1232 "Clang CG should cause non-terminated block!"); 1233 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1234 CGF.Builder.restoreIP(IP); 1235 CodeGenFunction::JumpDest Dest = 1236 CGF.getOMPCancelDestination(OMPD_parallel); 1237 CGF.EmitBranchThroughCleanup(Dest); 1238 }; 1239 1240 // TODO: Remove this once we emit parallel regions through the 1241 // OpenMPIRBuilder as it can do this setup internally. 1242 llvm::OpenMPIRBuilder::FinalizationInfo FI({FiniCB, Kind, HasCancel}); 1243 OMPBuilder->pushFinalizationCB(std::move(FI)); 1244 } 1245 ~PushAndPopStackRAII() { 1246 if (OMPBuilder) 1247 OMPBuilder->popFinalizationCB(); 1248 } 1249 llvm::OpenMPIRBuilder *OMPBuilder; 1250 }; 1251 } // namespace 1252 1253 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1254 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1255 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1256 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1257 assert(ThreadIDVar->getType()->isPointerType() && 1258 "thread id variable must be of type kmp_int32 *"); 1259 CodeGenFunction CGF(CGM, true); 1260 bool HasCancel = false; 1261 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1262 HasCancel = OPD->hasCancel(); 1263 else if (const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D)) 1264 HasCancel = OPD->hasCancel(); 1265 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1266 HasCancel = OPSD->hasCancel(); 1267 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1268 HasCancel = OPFD->hasCancel(); 1269 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1270 HasCancel = OPFD->hasCancel(); 1271 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1272 HasCancel = OPFD->hasCancel(); 1273 else if (const auto *OPFD = 1274 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1275 HasCancel = OPFD->hasCancel(); 1276 else if (const auto *OPFD = 1277 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1278 HasCancel = OPFD->hasCancel(); 1279 1280 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1281 // parallel region to make cancellation barriers work properly. 1282 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); 1283 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel, InnermostKind); 1284 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1285 HasCancel, OutlinedHelperName); 1286 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1287 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1288 } 1289 1290 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1291 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1292 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1293 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1294 return emitParallelOrTeamsOutlinedFunction( 1295 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1296 } 1297 1298 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1299 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1300 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1301 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1302 return emitParallelOrTeamsOutlinedFunction( 1303 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1304 } 1305 1306 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1307 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1308 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1309 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1310 bool Tied, unsigned &NumberOfParts) { 1311 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1312 PrePostActionTy &) { 1313 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1314 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1315 llvm::Value *TaskArgs[] = { 1316 UpLoc, ThreadID, 1317 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1318 TaskTVar->getType()->castAs<PointerType>()) 1319 .getPointer(CGF)}; 1320 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1321 CGM.getModule(), OMPRTL___kmpc_omp_task), 1322 TaskArgs); 1323 }; 1324 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1325 UntiedCodeGen); 1326 CodeGen.setAction(Action); 1327 assert(!ThreadIDVar->getType()->isPointerType() && 1328 "thread id variable must be of type kmp_int32 for tasks"); 1329 const OpenMPDirectiveKind Region = 1330 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1331 : OMPD_task; 1332 const CapturedStmt *CS = D.getCapturedStmt(Region); 1333 bool HasCancel = false; 1334 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1335 HasCancel = TD->hasCancel(); 1336 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1337 HasCancel = TD->hasCancel(); 1338 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1339 HasCancel = TD->hasCancel(); 1340 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1341 HasCancel = TD->hasCancel(); 1342 1343 CodeGenFunction CGF(CGM, true); 1344 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1345 InnermostKind, HasCancel, Action); 1346 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1347 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1348 if (!Tied) 1349 NumberOfParts = Action.getNumberOfParts(); 1350 return Res; 1351 } 1352 1353 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1354 const RecordDecl *RD, const CGRecordLayout &RL, 1355 ArrayRef<llvm::Constant *> Data) { 1356 llvm::StructType *StructTy = RL.getLLVMType(); 1357 unsigned PrevIdx = 0; 1358 ConstantInitBuilder CIBuilder(CGM); 1359 auto DI = Data.begin(); 1360 for (const FieldDecl *FD : RD->fields()) { 1361 unsigned Idx = RL.getLLVMFieldNo(FD); 1362 // Fill the alignment. 1363 for (unsigned I = PrevIdx; I < Idx; ++I) 1364 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1365 PrevIdx = Idx + 1; 1366 Fields.add(*DI); 1367 ++DI; 1368 } 1369 } 1370 1371 template <class... As> 1372 static llvm::GlobalVariable * 1373 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1374 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1375 As &&... Args) { 1376 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1377 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1378 ConstantInitBuilder CIBuilder(CGM); 1379 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1380 buildStructValue(Fields, CGM, RD, RL, Data); 1381 return Fields.finishAndCreateGlobal( 1382 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1383 std::forward<As>(Args)...); 1384 } 1385 1386 template <typename T> 1387 static void 1388 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1389 ArrayRef<llvm::Constant *> Data, 1390 T &Parent) { 1391 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1392 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1393 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1394 buildStructValue(Fields, CGM, RD, RL, Data); 1395 Fields.finishAndAddTo(Parent); 1396 } 1397 1398 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1399 bool AtCurrentPoint) { 1400 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1401 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1402 1403 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1404 if (AtCurrentPoint) { 1405 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1406 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1407 } else { 1408 Elem.second.ServiceInsertPt = 1409 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1410 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1411 } 1412 } 1413 1414 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1415 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1416 if (Elem.second.ServiceInsertPt) { 1417 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1418 Elem.second.ServiceInsertPt = nullptr; 1419 Ptr->eraseFromParent(); 1420 } 1421 } 1422 1423 static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, 1424 SourceLocation Loc, 1425 SmallString<128> &Buffer) { 1426 llvm::raw_svector_ostream OS(Buffer); 1427 // Build debug location 1428 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1429 OS << ";" << PLoc.getFilename() << ";"; 1430 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1431 OS << FD->getQualifiedNameAsString(); 1432 OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1433 return OS.str(); 1434 } 1435 1436 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1437 SourceLocation Loc, 1438 unsigned Flags) { 1439 llvm::Constant *SrcLocStr; 1440 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1441 Loc.isInvalid()) { 1442 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(); 1443 } else { 1444 std::string FunctionName = ""; 1445 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1446 FunctionName = FD->getQualifiedNameAsString(); 1447 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1448 const char *FileName = PLoc.getFilename(); 1449 unsigned Line = PLoc.getLine(); 1450 unsigned Column = PLoc.getColumn(); 1451 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FunctionName.c_str(), FileName, 1452 Line, Column); 1453 } 1454 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1455 return OMPBuilder.getOrCreateIdent(SrcLocStr, llvm::omp::IdentFlag(Flags), 1456 Reserved2Flags); 1457 } 1458 1459 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1460 SourceLocation Loc) { 1461 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1462 // If the OpenMPIRBuilder is used we need to use it for all thread id calls as 1463 // the clang invariants used below might be broken. 1464 if (CGM.getLangOpts().OpenMPIRBuilder) { 1465 SmallString<128> Buffer; 1466 OMPBuilder.updateToLocation(CGF.Builder.saveIP()); 1467 auto *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr( 1468 getIdentStringFromSourceLocation(CGF, Loc, Buffer)); 1469 return OMPBuilder.getOrCreateThreadID( 1470 OMPBuilder.getOrCreateIdent(SrcLocStr)); 1471 } 1472 1473 llvm::Value *ThreadID = nullptr; 1474 // Check whether we've already cached a load of the thread id in this 1475 // function. 1476 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1477 if (I != OpenMPLocThreadIDMap.end()) { 1478 ThreadID = I->second.ThreadID; 1479 if (ThreadID != nullptr) 1480 return ThreadID; 1481 } 1482 // If exceptions are enabled, do not use parameter to avoid possible crash. 1483 if (auto *OMPRegionInfo = 1484 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1485 if (OMPRegionInfo->getThreadIDVariable()) { 1486 // Check if this an outlined function with thread id passed as argument. 1487 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1488 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1489 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1490 !CGF.getLangOpts().CXXExceptions || 1491 CGF.Builder.GetInsertBlock() == TopBlock || 1492 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1493 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1494 TopBlock || 1495 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1496 CGF.Builder.GetInsertBlock()) { 1497 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1498 // If value loaded in entry block, cache it and use it everywhere in 1499 // function. 1500 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1501 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1502 Elem.second.ThreadID = ThreadID; 1503 } 1504 return ThreadID; 1505 } 1506 } 1507 } 1508 1509 // This is not an outlined function region - need to call __kmpc_int32 1510 // kmpc_global_thread_num(ident_t *loc). 1511 // Generate thread id value and cache this value for use across the 1512 // function. 1513 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1514 if (!Elem.second.ServiceInsertPt) 1515 setLocThreadIdInsertPt(CGF); 1516 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1517 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1518 llvm::CallInst *Call = CGF.Builder.CreateCall( 1519 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 1520 OMPRTL___kmpc_global_thread_num), 1521 emitUpdateLocation(CGF, Loc)); 1522 Call->setCallingConv(CGF.getRuntimeCC()); 1523 Elem.second.ThreadID = Call; 1524 return Call; 1525 } 1526 1527 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1528 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1529 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1530 clearLocThreadIdInsertPt(CGF); 1531 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1532 } 1533 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1534 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1535 UDRMap.erase(D); 1536 FunctionUDRMap.erase(CGF.CurFn); 1537 } 1538 auto I = FunctionUDMMap.find(CGF.CurFn); 1539 if (I != FunctionUDMMap.end()) { 1540 for(const auto *D : I->second) 1541 UDMMap.erase(D); 1542 FunctionUDMMap.erase(I); 1543 } 1544 LastprivateConditionalToTypes.erase(CGF.CurFn); 1545 FunctionToUntiedTaskStackMap.erase(CGF.CurFn); 1546 } 1547 1548 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1549 return OMPBuilder.IdentPtr; 1550 } 1551 1552 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1553 if (!Kmpc_MicroTy) { 1554 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1555 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1556 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1557 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1558 } 1559 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1560 } 1561 1562 llvm::FunctionCallee 1563 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 1564 assert((IVSize == 32 || IVSize == 64) && 1565 "IV size is not compatible with the omp runtime"); 1566 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 1567 : "__kmpc_for_static_init_4u") 1568 : (IVSigned ? "__kmpc_for_static_init_8" 1569 : "__kmpc_for_static_init_8u"); 1570 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1571 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1572 llvm::Type *TypeParams[] = { 1573 getIdentTyPointerTy(), // loc 1574 CGM.Int32Ty, // tid 1575 CGM.Int32Ty, // schedtype 1576 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1577 PtrTy, // p_lower 1578 PtrTy, // p_upper 1579 PtrTy, // p_stride 1580 ITy, // incr 1581 ITy // chunk 1582 }; 1583 auto *FnTy = 1584 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1585 return CGM.CreateRuntimeFunction(FnTy, Name); 1586 } 1587 1588 llvm::FunctionCallee 1589 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 1590 assert((IVSize == 32 || IVSize == 64) && 1591 "IV size is not compatible with the omp runtime"); 1592 StringRef Name = 1593 IVSize == 32 1594 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 1595 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 1596 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1597 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 1598 CGM.Int32Ty, // tid 1599 CGM.Int32Ty, // schedtype 1600 ITy, // lower 1601 ITy, // upper 1602 ITy, // stride 1603 ITy // chunk 1604 }; 1605 auto *FnTy = 1606 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1607 return CGM.CreateRuntimeFunction(FnTy, Name); 1608 } 1609 1610 llvm::FunctionCallee 1611 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 1612 assert((IVSize == 32 || IVSize == 64) && 1613 "IV size is not compatible with the omp runtime"); 1614 StringRef Name = 1615 IVSize == 32 1616 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 1617 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 1618 llvm::Type *TypeParams[] = { 1619 getIdentTyPointerTy(), // loc 1620 CGM.Int32Ty, // tid 1621 }; 1622 auto *FnTy = 1623 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1624 return CGM.CreateRuntimeFunction(FnTy, Name); 1625 } 1626 1627 llvm::FunctionCallee 1628 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 1629 assert((IVSize == 32 || IVSize == 64) && 1630 "IV size is not compatible with the omp runtime"); 1631 StringRef Name = 1632 IVSize == 32 1633 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 1634 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 1635 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1636 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1637 llvm::Type *TypeParams[] = { 1638 getIdentTyPointerTy(), // loc 1639 CGM.Int32Ty, // tid 1640 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1641 PtrTy, // p_lower 1642 PtrTy, // p_upper 1643 PtrTy // p_stride 1644 }; 1645 auto *FnTy = 1646 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1647 return CGM.CreateRuntimeFunction(FnTy, Name); 1648 } 1649 1650 /// Obtain information that uniquely identifies a target entry. This 1651 /// consists of the file and device IDs as well as line number associated with 1652 /// the relevant entry source location. 1653 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 1654 unsigned &DeviceID, unsigned &FileID, 1655 unsigned &LineNum) { 1656 SourceManager &SM = C.getSourceManager(); 1657 1658 // The loc should be always valid and have a file ID (the user cannot use 1659 // #pragma directives in macros) 1660 1661 assert(Loc.isValid() && "Source location is expected to be always valid."); 1662 1663 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 1664 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1665 1666 llvm::sys::fs::UniqueID ID; 1667 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) { 1668 PLoc = SM.getPresumedLoc(Loc, /*UseLineDirectives=*/false); 1669 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1670 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 1671 SM.getDiagnostics().Report(diag::err_cannot_open_file) 1672 << PLoc.getFilename() << EC.message(); 1673 } 1674 1675 DeviceID = ID.getDevice(); 1676 FileID = ID.getFile(); 1677 LineNum = PLoc.getLine(); 1678 } 1679 1680 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 1681 if (CGM.getLangOpts().OpenMPSimd) 1682 return Address::invalid(); 1683 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1684 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1685 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 1686 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1687 HasRequiresUnifiedSharedMemory))) { 1688 SmallString<64> PtrName; 1689 { 1690 llvm::raw_svector_ostream OS(PtrName); 1691 OS << CGM.getMangledName(GlobalDecl(VD)); 1692 if (!VD->isExternallyVisible()) { 1693 unsigned DeviceID, FileID, Line; 1694 getTargetEntryUniqueInfo(CGM.getContext(), 1695 VD->getCanonicalDecl()->getBeginLoc(), 1696 DeviceID, FileID, Line); 1697 OS << llvm::format("_%x", FileID); 1698 } 1699 OS << "_decl_tgt_ref_ptr"; 1700 } 1701 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 1702 if (!Ptr) { 1703 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 1704 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 1705 PtrName); 1706 1707 auto *GV = cast<llvm::GlobalVariable>(Ptr); 1708 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 1709 1710 if (!CGM.getLangOpts().OpenMPIsDevice) 1711 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 1712 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 1713 } 1714 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 1715 } 1716 return Address::invalid(); 1717 } 1718 1719 llvm::Constant * 1720 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 1721 assert(!CGM.getLangOpts().OpenMPUseTLS || 1722 !CGM.getContext().getTargetInfo().isTLSSupported()); 1723 // Lookup the entry, lazily creating it if necessary. 1724 std::string Suffix = getName({"cache", ""}); 1725 return getOrCreateInternalVariable( 1726 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 1727 } 1728 1729 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 1730 const VarDecl *VD, 1731 Address VDAddr, 1732 SourceLocation Loc) { 1733 if (CGM.getLangOpts().OpenMPUseTLS && 1734 CGM.getContext().getTargetInfo().isTLSSupported()) 1735 return VDAddr; 1736 1737 llvm::Type *VarTy = VDAddr.getElementType(); 1738 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1739 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1740 CGM.Int8PtrTy), 1741 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 1742 getOrCreateThreadPrivateCache(VD)}; 1743 return Address(CGF.EmitRuntimeCall( 1744 OMPBuilder.getOrCreateRuntimeFunction( 1745 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 1746 Args), 1747 VDAddr.getAlignment()); 1748 } 1749 1750 void CGOpenMPRuntime::emitThreadPrivateVarInit( 1751 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 1752 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 1753 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 1754 // library. 1755 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 1756 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1757 CGM.getModule(), OMPRTL___kmpc_global_thread_num), 1758 OMPLoc); 1759 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 1760 // to register constructor/destructor for variable. 1761 llvm::Value *Args[] = { 1762 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 1763 Ctor, CopyCtor, Dtor}; 1764 CGF.EmitRuntimeCall( 1765 OMPBuilder.getOrCreateRuntimeFunction( 1766 CGM.getModule(), OMPRTL___kmpc_threadprivate_register), 1767 Args); 1768 } 1769 1770 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 1771 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 1772 bool PerformInit, CodeGenFunction *CGF) { 1773 if (CGM.getLangOpts().OpenMPUseTLS && 1774 CGM.getContext().getTargetInfo().isTLSSupported()) 1775 return nullptr; 1776 1777 VD = VD->getDefinition(CGM.getContext()); 1778 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 1779 QualType ASTTy = VD->getType(); 1780 1781 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 1782 const Expr *Init = VD->getAnyInitializer(); 1783 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1784 // Generate function that re-emits the declaration's initializer into the 1785 // threadprivate copy of the variable VD 1786 CodeGenFunction CtorCGF(CGM); 1787 FunctionArgList Args; 1788 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1789 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1790 ImplicitParamDecl::Other); 1791 Args.push_back(&Dst); 1792 1793 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1794 CGM.getContext().VoidPtrTy, Args); 1795 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1796 std::string Name = getName({"__kmpc_global_ctor_", ""}); 1797 llvm::Function *Fn = 1798 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1799 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 1800 Args, Loc, Loc); 1801 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 1802 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1803 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1804 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 1805 Arg = CtorCGF.Builder.CreateElementBitCast( 1806 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 1807 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1808 /*IsInitializer=*/true); 1809 ArgVal = CtorCGF.EmitLoadOfScalar( 1810 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1811 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1812 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1813 CtorCGF.FinishFunction(); 1814 Ctor = Fn; 1815 } 1816 if (VD->getType().isDestructedType() != QualType::DK_none) { 1817 // Generate function that emits destructor call for the threadprivate copy 1818 // of the variable VD 1819 CodeGenFunction DtorCGF(CGM); 1820 FunctionArgList Args; 1821 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1822 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1823 ImplicitParamDecl::Other); 1824 Args.push_back(&Dst); 1825 1826 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1827 CGM.getContext().VoidTy, Args); 1828 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1829 std::string Name = getName({"__kmpc_global_dtor_", ""}); 1830 llvm::Function *Fn = 1831 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1832 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1833 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1834 Loc, Loc); 1835 // Create a scope with an artificial location for the body of this function. 1836 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1837 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 1838 DtorCGF.GetAddrOfLocalVar(&Dst), 1839 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 1840 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 1841 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1842 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1843 DtorCGF.FinishFunction(); 1844 Dtor = Fn; 1845 } 1846 // Do not emit init function if it is not required. 1847 if (!Ctor && !Dtor) 1848 return nullptr; 1849 1850 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1851 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1852 /*isVarArg=*/false) 1853 ->getPointerTo(); 1854 // Copying constructor for the threadprivate variable. 1855 // Must be NULL - reserved by runtime, but currently it requires that this 1856 // parameter is always NULL. Otherwise it fires assertion. 1857 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1858 if (Ctor == nullptr) { 1859 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1860 /*isVarArg=*/false) 1861 ->getPointerTo(); 1862 Ctor = llvm::Constant::getNullValue(CtorTy); 1863 } 1864 if (Dtor == nullptr) { 1865 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1866 /*isVarArg=*/false) 1867 ->getPointerTo(); 1868 Dtor = llvm::Constant::getNullValue(DtorTy); 1869 } 1870 if (!CGF) { 1871 auto *InitFunctionTy = 1872 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1873 std::string Name = getName({"__omp_threadprivate_init_", ""}); 1874 llvm::Function *InitFunction = CGM.CreateGlobalInitOrCleanUpFunction( 1875 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 1876 CodeGenFunction InitCGF(CGM); 1877 FunctionArgList ArgList; 1878 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1879 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1880 Loc, Loc); 1881 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1882 InitCGF.FinishFunction(); 1883 return InitFunction; 1884 } 1885 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1886 } 1887 return nullptr; 1888 } 1889 1890 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 1891 llvm::GlobalVariable *Addr, 1892 bool PerformInit) { 1893 if (CGM.getLangOpts().OMPTargetTriples.empty() && 1894 !CGM.getLangOpts().OpenMPIsDevice) 1895 return false; 1896 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1897 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1898 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 1899 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1900 HasRequiresUnifiedSharedMemory)) 1901 return CGM.getLangOpts().OpenMPIsDevice; 1902 VD = VD->getDefinition(CGM.getContext()); 1903 assert(VD && "Unknown VarDecl"); 1904 1905 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 1906 return CGM.getLangOpts().OpenMPIsDevice; 1907 1908 QualType ASTTy = VD->getType(); 1909 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 1910 1911 // Produce the unique prefix to identify the new target regions. We use 1912 // the source location of the variable declaration which we know to not 1913 // conflict with any target region. 1914 unsigned DeviceID; 1915 unsigned FileID; 1916 unsigned Line; 1917 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 1918 SmallString<128> Buffer, Out; 1919 { 1920 llvm::raw_svector_ostream OS(Buffer); 1921 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 1922 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 1923 } 1924 1925 const Expr *Init = VD->getAnyInitializer(); 1926 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1927 llvm::Constant *Ctor; 1928 llvm::Constant *ID; 1929 if (CGM.getLangOpts().OpenMPIsDevice) { 1930 // Generate function that re-emits the declaration's initializer into 1931 // the threadprivate copy of the variable VD 1932 CodeGenFunction CtorCGF(CGM); 1933 1934 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1935 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1936 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1937 FTy, Twine(Buffer, "_ctor"), FI, Loc); 1938 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 1939 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1940 FunctionArgList(), Loc, Loc); 1941 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 1942 CtorCGF.EmitAnyExprToMem(Init, 1943 Address(Addr, CGM.getContext().getDeclAlign(VD)), 1944 Init->getType().getQualifiers(), 1945 /*IsInitializer=*/true); 1946 CtorCGF.FinishFunction(); 1947 Ctor = Fn; 1948 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1949 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 1950 } else { 1951 Ctor = new llvm::GlobalVariable( 1952 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1953 llvm::GlobalValue::PrivateLinkage, 1954 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 1955 ID = Ctor; 1956 } 1957 1958 // Register the information for the entry associated with the constructor. 1959 Out.clear(); 1960 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 1961 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 1962 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 1963 } 1964 if (VD->getType().isDestructedType() != QualType::DK_none) { 1965 llvm::Constant *Dtor; 1966 llvm::Constant *ID; 1967 if (CGM.getLangOpts().OpenMPIsDevice) { 1968 // Generate function that emits destructor call for the threadprivate 1969 // copy of the variable VD 1970 CodeGenFunction DtorCGF(CGM); 1971 1972 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1973 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1974 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1975 FTy, Twine(Buffer, "_dtor"), FI, Loc); 1976 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1977 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1978 FunctionArgList(), Loc, Loc); 1979 // Create a scope with an artificial location for the body of this 1980 // function. 1981 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1982 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 1983 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1984 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1985 DtorCGF.FinishFunction(); 1986 Dtor = Fn; 1987 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1988 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 1989 } else { 1990 Dtor = new llvm::GlobalVariable( 1991 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1992 llvm::GlobalValue::PrivateLinkage, 1993 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 1994 ID = Dtor; 1995 } 1996 // Register the information for the entry associated with the destructor. 1997 Out.clear(); 1998 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 1999 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2000 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2001 } 2002 return CGM.getLangOpts().OpenMPIsDevice; 2003 } 2004 2005 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2006 QualType VarType, 2007 StringRef Name) { 2008 std::string Suffix = getName({"artificial", ""}); 2009 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2010 llvm::Value *GAddr = 2011 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2012 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 2013 CGM.getTarget().isTLSSupported()) { 2014 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 2015 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 2016 } 2017 std::string CacheSuffix = getName({"cache", ""}); 2018 llvm::Value *Args[] = { 2019 emitUpdateLocation(CGF, SourceLocation()), 2020 getThreadID(CGF, SourceLocation()), 2021 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2022 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2023 /*isSigned=*/false), 2024 getOrCreateInternalVariable( 2025 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2026 return Address( 2027 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2028 CGF.EmitRuntimeCall( 2029 OMPBuilder.getOrCreateRuntimeFunction( 2030 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 2031 Args), 2032 VarLVType->getPointerTo(/*AddrSpace=*/0)), 2033 CGM.getContext().getTypeAlignInChars(VarType)); 2034 } 2035 2036 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 2037 const RegionCodeGenTy &ThenGen, 2038 const RegionCodeGenTy &ElseGen) { 2039 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 2040 2041 // If the condition constant folds and can be elided, try to avoid emitting 2042 // the condition and the dead arm of the if/else. 2043 bool CondConstant; 2044 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 2045 if (CondConstant) 2046 ThenGen(CGF); 2047 else 2048 ElseGen(CGF); 2049 return; 2050 } 2051 2052 // Otherwise, the condition did not fold, or we couldn't elide it. Just 2053 // emit the conditional branch. 2054 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2055 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 2056 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 2057 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 2058 2059 // Emit the 'then' code. 2060 CGF.EmitBlock(ThenBlock); 2061 ThenGen(CGF); 2062 CGF.EmitBranch(ContBlock); 2063 // Emit the 'else' code if present. 2064 // There is no need to emit line number for unconditional branch. 2065 (void)ApplyDebugLocation::CreateEmpty(CGF); 2066 CGF.EmitBlock(ElseBlock); 2067 ElseGen(CGF); 2068 // There is no need to emit line number for unconditional branch. 2069 (void)ApplyDebugLocation::CreateEmpty(CGF); 2070 CGF.EmitBranch(ContBlock); 2071 // Emit the continuation block for code after the if. 2072 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 2073 } 2074 2075 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 2076 llvm::Function *OutlinedFn, 2077 ArrayRef<llvm::Value *> CapturedVars, 2078 const Expr *IfCond) { 2079 if (!CGF.HaveInsertPoint()) 2080 return; 2081 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 2082 auto &M = CGM.getModule(); 2083 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc, 2084 this](CodeGenFunction &CGF, PrePostActionTy &) { 2085 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 2086 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2087 llvm::Value *Args[] = { 2088 RTLoc, 2089 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 2090 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 2091 llvm::SmallVector<llvm::Value *, 16> RealArgs; 2092 RealArgs.append(std::begin(Args), std::end(Args)); 2093 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 2094 2095 llvm::FunctionCallee RTLFn = 2096 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call); 2097 CGF.EmitRuntimeCall(RTLFn, RealArgs); 2098 }; 2099 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc, 2100 this](CodeGenFunction &CGF, PrePostActionTy &) { 2101 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2102 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 2103 // Build calls: 2104 // __kmpc_serialized_parallel(&Loc, GTid); 2105 llvm::Value *Args[] = {RTLoc, ThreadID}; 2106 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2107 M, OMPRTL___kmpc_serialized_parallel), 2108 Args); 2109 2110 // OutlinedFn(>id, &zero_bound, CapturedStruct); 2111 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 2112 Address ZeroAddrBound = 2113 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 2114 /*Name=*/".bound.zero.addr"); 2115 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 2116 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 2117 // ThreadId for serialized parallels is 0. 2118 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 2119 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 2120 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 2121 2122 // Ensure we do not inline the function. This is trivially true for the ones 2123 // passed to __kmpc_fork_call but the ones calles in serialized regions 2124 // could be inlined. This is not a perfect but it is closer to the invariant 2125 // we want, namely, every data environment starts with a new function. 2126 // TODO: We should pass the if condition to the runtime function and do the 2127 // handling there. Much cleaner code. 2128 OutlinedFn->addFnAttr(llvm::Attribute::NoInline); 2129 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 2130 2131 // __kmpc_end_serialized_parallel(&Loc, GTid); 2132 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 2133 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2134 M, OMPRTL___kmpc_end_serialized_parallel), 2135 EndArgs); 2136 }; 2137 if (IfCond) { 2138 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 2139 } else { 2140 RegionCodeGenTy ThenRCG(ThenGen); 2141 ThenRCG(CGF); 2142 } 2143 } 2144 2145 // If we're inside an (outlined) parallel region, use the region info's 2146 // thread-ID variable (it is passed in a first argument of the outlined function 2147 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 2148 // regular serial code region, get thread ID by calling kmp_int32 2149 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 2150 // return the address of that temp. 2151 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 2152 SourceLocation Loc) { 2153 if (auto *OMPRegionInfo = 2154 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2155 if (OMPRegionInfo->getThreadIDVariable()) 2156 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 2157 2158 llvm::Value *ThreadID = getThreadID(CGF, Loc); 2159 QualType Int32Ty = 2160 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 2161 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 2162 CGF.EmitStoreOfScalar(ThreadID, 2163 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 2164 2165 return ThreadIDTemp; 2166 } 2167 2168 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 2169 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 2170 SmallString<256> Buffer; 2171 llvm::raw_svector_ostream Out(Buffer); 2172 Out << Name; 2173 StringRef RuntimeName = Out.str(); 2174 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 2175 if (Elem.second) { 2176 assert(Elem.second->getType()->getPointerElementType() == Ty && 2177 "OMP internal variable has different type than requested"); 2178 return &*Elem.second; 2179 } 2180 2181 return Elem.second = new llvm::GlobalVariable( 2182 CGM.getModule(), Ty, /*IsConstant*/ false, 2183 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 2184 Elem.first(), /*InsertBefore=*/nullptr, 2185 llvm::GlobalValue::NotThreadLocal, AddressSpace); 2186 } 2187 2188 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 2189 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 2190 std::string Name = getName({Prefix, "var"}); 2191 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 2192 } 2193 2194 namespace { 2195 /// Common pre(post)-action for different OpenMP constructs. 2196 class CommonActionTy final : public PrePostActionTy { 2197 llvm::FunctionCallee EnterCallee; 2198 ArrayRef<llvm::Value *> EnterArgs; 2199 llvm::FunctionCallee ExitCallee; 2200 ArrayRef<llvm::Value *> ExitArgs; 2201 bool Conditional; 2202 llvm::BasicBlock *ContBlock = nullptr; 2203 2204 public: 2205 CommonActionTy(llvm::FunctionCallee EnterCallee, 2206 ArrayRef<llvm::Value *> EnterArgs, 2207 llvm::FunctionCallee ExitCallee, 2208 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 2209 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 2210 ExitArgs(ExitArgs), Conditional(Conditional) {} 2211 void Enter(CodeGenFunction &CGF) override { 2212 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 2213 if (Conditional) { 2214 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 2215 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2216 ContBlock = CGF.createBasicBlock("omp_if.end"); 2217 // Generate the branch (If-stmt) 2218 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 2219 CGF.EmitBlock(ThenBlock); 2220 } 2221 } 2222 void Done(CodeGenFunction &CGF) { 2223 // Emit the rest of blocks/branches 2224 CGF.EmitBranch(ContBlock); 2225 CGF.EmitBlock(ContBlock, true); 2226 } 2227 void Exit(CodeGenFunction &CGF) override { 2228 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 2229 } 2230 }; 2231 } // anonymous namespace 2232 2233 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 2234 StringRef CriticalName, 2235 const RegionCodeGenTy &CriticalOpGen, 2236 SourceLocation Loc, const Expr *Hint) { 2237 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 2238 // CriticalOpGen(); 2239 // __kmpc_end_critical(ident_t *, gtid, Lock); 2240 // Prepare arguments and build a call to __kmpc_critical 2241 if (!CGF.HaveInsertPoint()) 2242 return; 2243 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2244 getCriticalRegionLock(CriticalName)}; 2245 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 2246 std::end(Args)); 2247 if (Hint) { 2248 EnterArgs.push_back(CGF.Builder.CreateIntCast( 2249 CGF.EmitScalarExpr(Hint), CGM.Int32Ty, /*isSigned=*/false)); 2250 } 2251 CommonActionTy Action( 2252 OMPBuilder.getOrCreateRuntimeFunction( 2253 CGM.getModule(), 2254 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical), 2255 EnterArgs, 2256 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2257 OMPRTL___kmpc_end_critical), 2258 Args); 2259 CriticalOpGen.setAction(Action); 2260 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 2261 } 2262 2263 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 2264 const RegionCodeGenTy &MasterOpGen, 2265 SourceLocation Loc) { 2266 if (!CGF.HaveInsertPoint()) 2267 return; 2268 // if(__kmpc_master(ident_t *, gtid)) { 2269 // MasterOpGen(); 2270 // __kmpc_end_master(ident_t *, gtid); 2271 // } 2272 // Prepare arguments and build a call to __kmpc_master 2273 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2274 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2275 CGM.getModule(), OMPRTL___kmpc_master), 2276 Args, 2277 OMPBuilder.getOrCreateRuntimeFunction( 2278 CGM.getModule(), OMPRTL___kmpc_end_master), 2279 Args, 2280 /*Conditional=*/true); 2281 MasterOpGen.setAction(Action); 2282 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 2283 Action.Done(CGF); 2284 } 2285 2286 void CGOpenMPRuntime::emitMaskedRegion(CodeGenFunction &CGF, 2287 const RegionCodeGenTy &MaskedOpGen, 2288 SourceLocation Loc, const Expr *Filter) { 2289 if (!CGF.HaveInsertPoint()) 2290 return; 2291 // if(__kmpc_masked(ident_t *, gtid, filter)) { 2292 // MaskedOpGen(); 2293 // __kmpc_end_masked(iden_t *, gtid); 2294 // } 2295 // Prepare arguments and build a call to __kmpc_masked 2296 llvm::Value *FilterVal = Filter 2297 ? CGF.EmitScalarExpr(Filter, CGF.Int32Ty) 2298 : llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/0); 2299 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2300 FilterVal}; 2301 llvm::Value *ArgsEnd[] = {emitUpdateLocation(CGF, Loc), 2302 getThreadID(CGF, Loc)}; 2303 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2304 CGM.getModule(), OMPRTL___kmpc_masked), 2305 Args, 2306 OMPBuilder.getOrCreateRuntimeFunction( 2307 CGM.getModule(), OMPRTL___kmpc_end_masked), 2308 ArgsEnd, 2309 /*Conditional=*/true); 2310 MaskedOpGen.setAction(Action); 2311 emitInlinedDirective(CGF, OMPD_masked, MaskedOpGen); 2312 Action.Done(CGF); 2313 } 2314 2315 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 2316 SourceLocation Loc) { 2317 if (!CGF.HaveInsertPoint()) 2318 return; 2319 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2320 OMPBuilder.createTaskyield(CGF.Builder); 2321 } else { 2322 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 2323 llvm::Value *Args[] = { 2324 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2325 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 2326 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2327 CGM.getModule(), OMPRTL___kmpc_omp_taskyield), 2328 Args); 2329 } 2330 2331 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2332 Region->emitUntiedSwitch(CGF); 2333 } 2334 2335 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 2336 const RegionCodeGenTy &TaskgroupOpGen, 2337 SourceLocation Loc) { 2338 if (!CGF.HaveInsertPoint()) 2339 return; 2340 // __kmpc_taskgroup(ident_t *, gtid); 2341 // TaskgroupOpGen(); 2342 // __kmpc_end_taskgroup(ident_t *, gtid); 2343 // Prepare arguments and build a call to __kmpc_taskgroup 2344 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2345 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2346 CGM.getModule(), OMPRTL___kmpc_taskgroup), 2347 Args, 2348 OMPBuilder.getOrCreateRuntimeFunction( 2349 CGM.getModule(), OMPRTL___kmpc_end_taskgroup), 2350 Args); 2351 TaskgroupOpGen.setAction(Action); 2352 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 2353 } 2354 2355 /// Given an array of pointers to variables, project the address of a 2356 /// given variable. 2357 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 2358 unsigned Index, const VarDecl *Var) { 2359 // Pull out the pointer to the variable. 2360 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 2361 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 2362 2363 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 2364 Addr = CGF.Builder.CreateElementBitCast( 2365 Addr, CGF.ConvertTypeForMem(Var->getType())); 2366 return Addr; 2367 } 2368 2369 static llvm::Value *emitCopyprivateCopyFunction( 2370 CodeGenModule &CGM, llvm::Type *ArgsType, 2371 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 2372 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 2373 SourceLocation Loc) { 2374 ASTContext &C = CGM.getContext(); 2375 // void copy_func(void *LHSArg, void *RHSArg); 2376 FunctionArgList Args; 2377 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2378 ImplicitParamDecl::Other); 2379 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2380 ImplicitParamDecl::Other); 2381 Args.push_back(&LHSArg); 2382 Args.push_back(&RHSArg); 2383 const auto &CGFI = 2384 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2385 std::string Name = 2386 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 2387 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 2388 llvm::GlobalValue::InternalLinkage, Name, 2389 &CGM.getModule()); 2390 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 2391 Fn->setDoesNotRecurse(); 2392 CodeGenFunction CGF(CGM); 2393 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 2394 // Dest = (void*[n])(LHSArg); 2395 // Src = (void*[n])(RHSArg); 2396 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2397 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 2398 ArgsType), CGF.getPointerAlign()); 2399 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2400 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 2401 ArgsType), CGF.getPointerAlign()); 2402 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 2403 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 2404 // ... 2405 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 2406 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 2407 const auto *DestVar = 2408 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 2409 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 2410 2411 const auto *SrcVar = 2412 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 2413 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 2414 2415 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 2416 QualType Type = VD->getType(); 2417 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 2418 } 2419 CGF.FinishFunction(); 2420 return Fn; 2421 } 2422 2423 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 2424 const RegionCodeGenTy &SingleOpGen, 2425 SourceLocation Loc, 2426 ArrayRef<const Expr *> CopyprivateVars, 2427 ArrayRef<const Expr *> SrcExprs, 2428 ArrayRef<const Expr *> DstExprs, 2429 ArrayRef<const Expr *> AssignmentOps) { 2430 if (!CGF.HaveInsertPoint()) 2431 return; 2432 assert(CopyprivateVars.size() == SrcExprs.size() && 2433 CopyprivateVars.size() == DstExprs.size() && 2434 CopyprivateVars.size() == AssignmentOps.size()); 2435 ASTContext &C = CGM.getContext(); 2436 // int32 did_it = 0; 2437 // if(__kmpc_single(ident_t *, gtid)) { 2438 // SingleOpGen(); 2439 // __kmpc_end_single(ident_t *, gtid); 2440 // did_it = 1; 2441 // } 2442 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2443 // <copy_func>, did_it); 2444 2445 Address DidIt = Address::invalid(); 2446 if (!CopyprivateVars.empty()) { 2447 // int32 did_it = 0; 2448 QualType KmpInt32Ty = 2449 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2450 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 2451 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 2452 } 2453 // Prepare arguments and build a call to __kmpc_single 2454 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2455 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2456 CGM.getModule(), OMPRTL___kmpc_single), 2457 Args, 2458 OMPBuilder.getOrCreateRuntimeFunction( 2459 CGM.getModule(), OMPRTL___kmpc_end_single), 2460 Args, 2461 /*Conditional=*/true); 2462 SingleOpGen.setAction(Action); 2463 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 2464 if (DidIt.isValid()) { 2465 // did_it = 1; 2466 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 2467 } 2468 Action.Done(CGF); 2469 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2470 // <copy_func>, did_it); 2471 if (DidIt.isValid()) { 2472 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 2473 QualType CopyprivateArrayTy = C.getConstantArrayType( 2474 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 2475 /*IndexTypeQuals=*/0); 2476 // Create a list of all private variables for copyprivate. 2477 Address CopyprivateList = 2478 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 2479 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 2480 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 2481 CGF.Builder.CreateStore( 2482 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2483 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 2484 CGF.VoidPtrTy), 2485 Elem); 2486 } 2487 // Build function that copies private values from single region to all other 2488 // threads in the corresponding parallel region. 2489 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 2490 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 2491 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 2492 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 2493 Address CL = 2494 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 2495 CGF.VoidPtrTy); 2496 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 2497 llvm::Value *Args[] = { 2498 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 2499 getThreadID(CGF, Loc), // i32 <gtid> 2500 BufSize, // size_t <buf_size> 2501 CL.getPointer(), // void *<copyprivate list> 2502 CpyFn, // void (*) (void *, void *) <copy_func> 2503 DidItVal // i32 did_it 2504 }; 2505 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2506 CGM.getModule(), OMPRTL___kmpc_copyprivate), 2507 Args); 2508 } 2509 } 2510 2511 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 2512 const RegionCodeGenTy &OrderedOpGen, 2513 SourceLocation Loc, bool IsThreads) { 2514 if (!CGF.HaveInsertPoint()) 2515 return; 2516 // __kmpc_ordered(ident_t *, gtid); 2517 // OrderedOpGen(); 2518 // __kmpc_end_ordered(ident_t *, gtid); 2519 // Prepare arguments and build a call to __kmpc_ordered 2520 if (IsThreads) { 2521 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2522 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2523 CGM.getModule(), OMPRTL___kmpc_ordered), 2524 Args, 2525 OMPBuilder.getOrCreateRuntimeFunction( 2526 CGM.getModule(), OMPRTL___kmpc_end_ordered), 2527 Args); 2528 OrderedOpGen.setAction(Action); 2529 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2530 return; 2531 } 2532 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2533 } 2534 2535 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 2536 unsigned Flags; 2537 if (Kind == OMPD_for) 2538 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 2539 else if (Kind == OMPD_sections) 2540 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 2541 else if (Kind == OMPD_single) 2542 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 2543 else if (Kind == OMPD_barrier) 2544 Flags = OMP_IDENT_BARRIER_EXPL; 2545 else 2546 Flags = OMP_IDENT_BARRIER_IMPL; 2547 return Flags; 2548 } 2549 2550 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 2551 CodeGenFunction &CGF, const OMPLoopDirective &S, 2552 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 2553 // Check if the loop directive is actually a doacross loop directive. In this 2554 // case choose static, 1 schedule. 2555 if (llvm::any_of( 2556 S.getClausesOfKind<OMPOrderedClause>(), 2557 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 2558 ScheduleKind = OMPC_SCHEDULE_static; 2559 // Chunk size is 1 in this case. 2560 llvm::APInt ChunkSize(32, 1); 2561 ChunkExpr = IntegerLiteral::Create( 2562 CGF.getContext(), ChunkSize, 2563 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 2564 SourceLocation()); 2565 } 2566 } 2567 2568 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 2569 OpenMPDirectiveKind Kind, bool EmitChecks, 2570 bool ForceSimpleCall) { 2571 // Check if we should use the OMPBuilder 2572 auto *OMPRegionInfo = 2573 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 2574 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2575 CGF.Builder.restoreIP(OMPBuilder.createBarrier( 2576 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 2577 return; 2578 } 2579 2580 if (!CGF.HaveInsertPoint()) 2581 return; 2582 // Build call __kmpc_cancel_barrier(loc, thread_id); 2583 // Build call __kmpc_barrier(loc, thread_id); 2584 unsigned Flags = getDefaultFlagsForBarriers(Kind); 2585 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 2586 // thread_id); 2587 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 2588 getThreadID(CGF, Loc)}; 2589 if (OMPRegionInfo) { 2590 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 2591 llvm::Value *Result = CGF.EmitRuntimeCall( 2592 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2593 OMPRTL___kmpc_cancel_barrier), 2594 Args); 2595 if (EmitChecks) { 2596 // if (__kmpc_cancel_barrier()) { 2597 // exit from construct; 2598 // } 2599 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2600 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 2601 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 2602 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2603 CGF.EmitBlock(ExitBB); 2604 // exit from construct; 2605 CodeGenFunction::JumpDest CancelDestination = 2606 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2607 CGF.EmitBranchThroughCleanup(CancelDestination); 2608 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2609 } 2610 return; 2611 } 2612 } 2613 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2614 CGM.getModule(), OMPRTL___kmpc_barrier), 2615 Args); 2616 } 2617 2618 /// Map the OpenMP loop schedule to the runtime enumeration. 2619 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 2620 bool Chunked, bool Ordered) { 2621 switch (ScheduleKind) { 2622 case OMPC_SCHEDULE_static: 2623 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 2624 : (Ordered ? OMP_ord_static : OMP_sch_static); 2625 case OMPC_SCHEDULE_dynamic: 2626 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 2627 case OMPC_SCHEDULE_guided: 2628 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 2629 case OMPC_SCHEDULE_runtime: 2630 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 2631 case OMPC_SCHEDULE_auto: 2632 return Ordered ? OMP_ord_auto : OMP_sch_auto; 2633 case OMPC_SCHEDULE_unknown: 2634 assert(!Chunked && "chunk was specified but schedule kind not known"); 2635 return Ordered ? OMP_ord_static : OMP_sch_static; 2636 } 2637 llvm_unreachable("Unexpected runtime schedule"); 2638 } 2639 2640 /// Map the OpenMP distribute schedule to the runtime enumeration. 2641 static OpenMPSchedType 2642 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 2643 // only static is allowed for dist_schedule 2644 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 2645 } 2646 2647 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 2648 bool Chunked) const { 2649 OpenMPSchedType Schedule = 2650 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2651 return Schedule == OMP_sch_static; 2652 } 2653 2654 bool CGOpenMPRuntime::isStaticNonchunked( 2655 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2656 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2657 return Schedule == OMP_dist_sch_static; 2658 } 2659 2660 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 2661 bool Chunked) const { 2662 OpenMPSchedType Schedule = 2663 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2664 return Schedule == OMP_sch_static_chunked; 2665 } 2666 2667 bool CGOpenMPRuntime::isStaticChunked( 2668 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2669 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2670 return Schedule == OMP_dist_sch_static_chunked; 2671 } 2672 2673 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 2674 OpenMPSchedType Schedule = 2675 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 2676 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 2677 return Schedule != OMP_sch_static; 2678 } 2679 2680 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 2681 OpenMPScheduleClauseModifier M1, 2682 OpenMPScheduleClauseModifier M2) { 2683 int Modifier = 0; 2684 switch (M1) { 2685 case OMPC_SCHEDULE_MODIFIER_monotonic: 2686 Modifier = OMP_sch_modifier_monotonic; 2687 break; 2688 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2689 Modifier = OMP_sch_modifier_nonmonotonic; 2690 break; 2691 case OMPC_SCHEDULE_MODIFIER_simd: 2692 if (Schedule == OMP_sch_static_chunked) 2693 Schedule = OMP_sch_static_balanced_chunked; 2694 break; 2695 case OMPC_SCHEDULE_MODIFIER_last: 2696 case OMPC_SCHEDULE_MODIFIER_unknown: 2697 break; 2698 } 2699 switch (M2) { 2700 case OMPC_SCHEDULE_MODIFIER_monotonic: 2701 Modifier = OMP_sch_modifier_monotonic; 2702 break; 2703 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2704 Modifier = OMP_sch_modifier_nonmonotonic; 2705 break; 2706 case OMPC_SCHEDULE_MODIFIER_simd: 2707 if (Schedule == OMP_sch_static_chunked) 2708 Schedule = OMP_sch_static_balanced_chunked; 2709 break; 2710 case OMPC_SCHEDULE_MODIFIER_last: 2711 case OMPC_SCHEDULE_MODIFIER_unknown: 2712 break; 2713 } 2714 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 2715 // If the static schedule kind is specified or if the ordered clause is 2716 // specified, and if the nonmonotonic modifier is not specified, the effect is 2717 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 2718 // modifier is specified, the effect is as if the nonmonotonic modifier is 2719 // specified. 2720 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 2721 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 2722 Schedule == OMP_sch_static_balanced_chunked || 2723 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 2724 Schedule == OMP_dist_sch_static_chunked || 2725 Schedule == OMP_dist_sch_static)) 2726 Modifier = OMP_sch_modifier_nonmonotonic; 2727 } 2728 return Schedule | Modifier; 2729 } 2730 2731 void CGOpenMPRuntime::emitForDispatchInit( 2732 CodeGenFunction &CGF, SourceLocation Loc, 2733 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 2734 bool Ordered, const DispatchRTInput &DispatchValues) { 2735 if (!CGF.HaveInsertPoint()) 2736 return; 2737 OpenMPSchedType Schedule = getRuntimeSchedule( 2738 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 2739 assert(Ordered || 2740 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 2741 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 2742 Schedule != OMP_sch_static_balanced_chunked)); 2743 // Call __kmpc_dispatch_init( 2744 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 2745 // kmp_int[32|64] lower, kmp_int[32|64] upper, 2746 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 2747 2748 // If the Chunk was not specified in the clause - use default value 1. 2749 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 2750 : CGF.Builder.getIntN(IVSize, 1); 2751 llvm::Value *Args[] = { 2752 emitUpdateLocation(CGF, Loc), 2753 getThreadID(CGF, Loc), 2754 CGF.Builder.getInt32(addMonoNonMonoModifier( 2755 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 2756 DispatchValues.LB, // Lower 2757 DispatchValues.UB, // Upper 2758 CGF.Builder.getIntN(IVSize, 1), // Stride 2759 Chunk // Chunk 2760 }; 2761 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 2762 } 2763 2764 static void emitForStaticInitCall( 2765 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 2766 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 2767 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 2768 const CGOpenMPRuntime::StaticRTInput &Values) { 2769 if (!CGF.HaveInsertPoint()) 2770 return; 2771 2772 assert(!Values.Ordered); 2773 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 2774 Schedule == OMP_sch_static_balanced_chunked || 2775 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 2776 Schedule == OMP_dist_sch_static || 2777 Schedule == OMP_dist_sch_static_chunked); 2778 2779 // Call __kmpc_for_static_init( 2780 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 2781 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 2782 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 2783 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 2784 llvm::Value *Chunk = Values.Chunk; 2785 if (Chunk == nullptr) { 2786 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 2787 Schedule == OMP_dist_sch_static) && 2788 "expected static non-chunked schedule"); 2789 // If the Chunk was not specified in the clause - use default value 1. 2790 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 2791 } else { 2792 assert((Schedule == OMP_sch_static_chunked || 2793 Schedule == OMP_sch_static_balanced_chunked || 2794 Schedule == OMP_ord_static_chunked || 2795 Schedule == OMP_dist_sch_static_chunked) && 2796 "expected static chunked schedule"); 2797 } 2798 llvm::Value *Args[] = { 2799 UpdateLocation, 2800 ThreadId, 2801 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 2802 M2)), // Schedule type 2803 Values.IL.getPointer(), // &isLastIter 2804 Values.LB.getPointer(), // &LB 2805 Values.UB.getPointer(), // &UB 2806 Values.ST.getPointer(), // &Stride 2807 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 2808 Chunk // Chunk 2809 }; 2810 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 2811 } 2812 2813 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 2814 SourceLocation Loc, 2815 OpenMPDirectiveKind DKind, 2816 const OpenMPScheduleTy &ScheduleKind, 2817 const StaticRTInput &Values) { 2818 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 2819 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 2820 assert(isOpenMPWorksharingDirective(DKind) && 2821 "Expected loop-based or sections-based directive."); 2822 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 2823 isOpenMPLoopDirective(DKind) 2824 ? OMP_IDENT_WORK_LOOP 2825 : OMP_IDENT_WORK_SECTIONS); 2826 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2827 llvm::FunctionCallee StaticInitFunction = 2828 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 2829 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2830 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2831 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 2832 } 2833 2834 void CGOpenMPRuntime::emitDistributeStaticInit( 2835 CodeGenFunction &CGF, SourceLocation Loc, 2836 OpenMPDistScheduleClauseKind SchedKind, 2837 const CGOpenMPRuntime::StaticRTInput &Values) { 2838 OpenMPSchedType ScheduleNum = 2839 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 2840 llvm::Value *UpdatedLocation = 2841 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 2842 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2843 llvm::FunctionCallee StaticInitFunction = 2844 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 2845 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2846 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 2847 OMPC_SCHEDULE_MODIFIER_unknown, Values); 2848 } 2849 2850 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 2851 SourceLocation Loc, 2852 OpenMPDirectiveKind DKind) { 2853 if (!CGF.HaveInsertPoint()) 2854 return; 2855 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 2856 llvm::Value *Args[] = { 2857 emitUpdateLocation(CGF, Loc, 2858 isOpenMPDistributeDirective(DKind) 2859 ? OMP_IDENT_WORK_DISTRIBUTE 2860 : isOpenMPLoopDirective(DKind) 2861 ? OMP_IDENT_WORK_LOOP 2862 : OMP_IDENT_WORK_SECTIONS), 2863 getThreadID(CGF, Loc)}; 2864 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2865 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2866 CGM.getModule(), OMPRTL___kmpc_for_static_fini), 2867 Args); 2868 } 2869 2870 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 2871 SourceLocation Loc, 2872 unsigned IVSize, 2873 bool IVSigned) { 2874 if (!CGF.HaveInsertPoint()) 2875 return; 2876 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 2877 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2878 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 2879 } 2880 2881 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 2882 SourceLocation Loc, unsigned IVSize, 2883 bool IVSigned, Address IL, 2884 Address LB, Address UB, 2885 Address ST) { 2886 // Call __kmpc_dispatch_next( 2887 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 2888 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 2889 // kmp_int[32|64] *p_stride); 2890 llvm::Value *Args[] = { 2891 emitUpdateLocation(CGF, Loc), 2892 getThreadID(CGF, Loc), 2893 IL.getPointer(), // &isLastIter 2894 LB.getPointer(), // &Lower 2895 UB.getPointer(), // &Upper 2896 ST.getPointer() // &Stride 2897 }; 2898 llvm::Value *Call = 2899 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 2900 return CGF.EmitScalarConversion( 2901 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 2902 CGF.getContext().BoolTy, Loc); 2903 } 2904 2905 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 2906 llvm::Value *NumThreads, 2907 SourceLocation Loc) { 2908 if (!CGF.HaveInsertPoint()) 2909 return; 2910 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 2911 llvm::Value *Args[] = { 2912 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2913 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 2914 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2915 CGM.getModule(), OMPRTL___kmpc_push_num_threads), 2916 Args); 2917 } 2918 2919 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 2920 ProcBindKind ProcBind, 2921 SourceLocation Loc) { 2922 if (!CGF.HaveInsertPoint()) 2923 return; 2924 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 2925 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 2926 llvm::Value *Args[] = { 2927 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2928 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 2929 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2930 CGM.getModule(), OMPRTL___kmpc_push_proc_bind), 2931 Args); 2932 } 2933 2934 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 2935 SourceLocation Loc, llvm::AtomicOrdering AO) { 2936 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2937 OMPBuilder.createFlush(CGF.Builder); 2938 } else { 2939 if (!CGF.HaveInsertPoint()) 2940 return; 2941 // Build call void __kmpc_flush(ident_t *loc) 2942 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2943 CGM.getModule(), OMPRTL___kmpc_flush), 2944 emitUpdateLocation(CGF, Loc)); 2945 } 2946 } 2947 2948 namespace { 2949 /// Indexes of fields for type kmp_task_t. 2950 enum KmpTaskTFields { 2951 /// List of shared variables. 2952 KmpTaskTShareds, 2953 /// Task routine. 2954 KmpTaskTRoutine, 2955 /// Partition id for the untied tasks. 2956 KmpTaskTPartId, 2957 /// Function with call of destructors for private variables. 2958 Data1, 2959 /// Task priority. 2960 Data2, 2961 /// (Taskloops only) Lower bound. 2962 KmpTaskTLowerBound, 2963 /// (Taskloops only) Upper bound. 2964 KmpTaskTUpperBound, 2965 /// (Taskloops only) Stride. 2966 KmpTaskTStride, 2967 /// (Taskloops only) Is last iteration flag. 2968 KmpTaskTLastIter, 2969 /// (Taskloops only) Reduction data. 2970 KmpTaskTReductions, 2971 }; 2972 } // anonymous namespace 2973 2974 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 2975 return OffloadEntriesTargetRegion.empty() && 2976 OffloadEntriesDeviceGlobalVar.empty(); 2977 } 2978 2979 /// Initialize target region entry. 2980 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2981 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2982 StringRef ParentName, unsigned LineNum, 2983 unsigned Order) { 2984 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 2985 "only required for the device " 2986 "code generation."); 2987 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 2988 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 2989 OMPTargetRegionEntryTargetRegion); 2990 ++OffloadingEntriesNum; 2991 } 2992 2993 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2994 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2995 StringRef ParentName, unsigned LineNum, 2996 llvm::Constant *Addr, llvm::Constant *ID, 2997 OMPTargetRegionEntryKind Flags) { 2998 // If we are emitting code for a target, the entry is already initialized, 2999 // only has to be registered. 3000 if (CGM.getLangOpts().OpenMPIsDevice) { 3001 // This could happen if the device compilation is invoked standalone. 3002 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) 3003 return; 3004 auto &Entry = 3005 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3006 Entry.setAddress(Addr); 3007 Entry.setID(ID); 3008 Entry.setFlags(Flags); 3009 } else { 3010 if (Flags == 3011 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion && 3012 hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum, 3013 /*IgnoreAddressId*/ true)) 3014 return; 3015 assert(!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) && 3016 "Target region entry already registered!"); 3017 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3018 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3019 ++OffloadingEntriesNum; 3020 } 3021 } 3022 3023 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3024 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum, 3025 bool IgnoreAddressId) const { 3026 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3027 if (PerDevice == OffloadEntriesTargetRegion.end()) 3028 return false; 3029 auto PerFile = PerDevice->second.find(FileID); 3030 if (PerFile == PerDevice->second.end()) 3031 return false; 3032 auto PerParentName = PerFile->second.find(ParentName); 3033 if (PerParentName == PerFile->second.end()) 3034 return false; 3035 auto PerLine = PerParentName->second.find(LineNum); 3036 if (PerLine == PerParentName->second.end()) 3037 return false; 3038 // Fail if this entry is already registered. 3039 if (!IgnoreAddressId && 3040 (PerLine->second.getAddress() || PerLine->second.getID())) 3041 return false; 3042 return true; 3043 } 3044 3045 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3046 const OffloadTargetRegionEntryInfoActTy &Action) { 3047 // Scan all target region entries and perform the provided action. 3048 for (const auto &D : OffloadEntriesTargetRegion) 3049 for (const auto &F : D.second) 3050 for (const auto &P : F.second) 3051 for (const auto &L : P.second) 3052 Action(D.first, F.first, P.first(), L.first, L.second); 3053 } 3054 3055 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3056 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3057 OMPTargetGlobalVarEntryKind Flags, 3058 unsigned Order) { 3059 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3060 "only required for the device " 3061 "code generation."); 3062 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3063 ++OffloadingEntriesNum; 3064 } 3065 3066 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3067 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3068 CharUnits VarSize, 3069 OMPTargetGlobalVarEntryKind Flags, 3070 llvm::GlobalValue::LinkageTypes Linkage) { 3071 if (CGM.getLangOpts().OpenMPIsDevice) { 3072 // This could happen if the device compilation is invoked standalone. 3073 if (!hasDeviceGlobalVarEntryInfo(VarName)) 3074 return; 3075 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3076 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3077 if (Entry.getVarSize().isZero()) { 3078 Entry.setVarSize(VarSize); 3079 Entry.setLinkage(Linkage); 3080 } 3081 return; 3082 } 3083 Entry.setVarSize(VarSize); 3084 Entry.setLinkage(Linkage); 3085 Entry.setAddress(Addr); 3086 } else { 3087 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3088 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3089 assert(Entry.isValid() && Entry.getFlags() == Flags && 3090 "Entry not initialized!"); 3091 if (Entry.getVarSize().isZero()) { 3092 Entry.setVarSize(VarSize); 3093 Entry.setLinkage(Linkage); 3094 } 3095 return; 3096 } 3097 OffloadEntriesDeviceGlobalVar.try_emplace( 3098 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3099 ++OffloadingEntriesNum; 3100 } 3101 } 3102 3103 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3104 actOnDeviceGlobalVarEntriesInfo( 3105 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 3106 // Scan all target region entries and perform the provided action. 3107 for (const auto &E : OffloadEntriesDeviceGlobalVar) 3108 Action(E.getKey(), E.getValue()); 3109 } 3110 3111 void CGOpenMPRuntime::createOffloadEntry( 3112 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 3113 llvm::GlobalValue::LinkageTypes Linkage) { 3114 StringRef Name = Addr->getName(); 3115 llvm::Module &M = CGM.getModule(); 3116 llvm::LLVMContext &C = M.getContext(); 3117 3118 // Create constant string with the name. 3119 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 3120 3121 std::string StringName = getName({"omp_offloading", "entry_name"}); 3122 auto *Str = new llvm::GlobalVariable( 3123 M, StrPtrInit->getType(), /*isConstant=*/true, 3124 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 3125 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 3126 3127 llvm::Constant *Data[] = { 3128 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(ID, CGM.VoidPtrTy), 3129 llvm::ConstantExpr::getPointerBitCastOrAddrSpaceCast(Str, CGM.Int8PtrTy), 3130 llvm::ConstantInt::get(CGM.SizeTy, Size), 3131 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 3132 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 3133 std::string EntryName = getName({"omp_offloading", "entry", ""}); 3134 llvm::GlobalVariable *Entry = createGlobalStruct( 3135 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 3136 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 3137 3138 // The entry has to be created in the section the linker expects it to be. 3139 Entry->setSection("omp_offloading_entries"); 3140 } 3141 3142 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 3143 // Emit the offloading entries and metadata so that the device codegen side 3144 // can easily figure out what to emit. The produced metadata looks like 3145 // this: 3146 // 3147 // !omp_offload.info = !{!1, ...} 3148 // 3149 // Right now we only generate metadata for function that contain target 3150 // regions. 3151 3152 // If we are in simd mode or there are no entries, we don't need to do 3153 // anything. 3154 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 3155 return; 3156 3157 llvm::Module &M = CGM.getModule(); 3158 llvm::LLVMContext &C = M.getContext(); 3159 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 3160 SourceLocation, StringRef>, 3161 16> 3162 OrderedEntries(OffloadEntriesInfoManager.size()); 3163 llvm::SmallVector<StringRef, 16> ParentFunctions( 3164 OffloadEntriesInfoManager.size()); 3165 3166 // Auxiliary methods to create metadata values and strings. 3167 auto &&GetMDInt = [this](unsigned V) { 3168 return llvm::ConstantAsMetadata::get( 3169 llvm::ConstantInt::get(CGM.Int32Ty, V)); 3170 }; 3171 3172 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 3173 3174 // Create the offloading info metadata node. 3175 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 3176 3177 // Create function that emits metadata for each target region entry; 3178 auto &&TargetRegionMetadataEmitter = 3179 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 3180 &GetMDString]( 3181 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3182 unsigned Line, 3183 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 3184 // Generate metadata for target regions. Each entry of this metadata 3185 // contains: 3186 // - Entry 0 -> Kind of this type of metadata (0). 3187 // - Entry 1 -> Device ID of the file where the entry was identified. 3188 // - Entry 2 -> File ID of the file where the entry was identified. 3189 // - Entry 3 -> Mangled name of the function where the entry was 3190 // identified. 3191 // - Entry 4 -> Line in the file where the entry was identified. 3192 // - Entry 5 -> Order the entry was created. 3193 // The first element of the metadata node is the kind. 3194 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 3195 GetMDInt(FileID), GetMDString(ParentName), 3196 GetMDInt(Line), GetMDInt(E.getOrder())}; 3197 3198 SourceLocation Loc; 3199 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 3200 E = CGM.getContext().getSourceManager().fileinfo_end(); 3201 I != E; ++I) { 3202 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 3203 I->getFirst()->getUniqueID().getFile() == FileID) { 3204 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 3205 I->getFirst(), Line, 1); 3206 break; 3207 } 3208 } 3209 // Save this entry in the right position of the ordered entries array. 3210 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 3211 ParentFunctions[E.getOrder()] = ParentName; 3212 3213 // Add metadata to the named metadata node. 3214 MD->addOperand(llvm::MDNode::get(C, Ops)); 3215 }; 3216 3217 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 3218 TargetRegionMetadataEmitter); 3219 3220 // Create function that emits metadata for each device global variable entry; 3221 auto &&DeviceGlobalVarMetadataEmitter = 3222 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 3223 MD](StringRef MangledName, 3224 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 3225 &E) { 3226 // Generate metadata for global variables. Each entry of this metadata 3227 // contains: 3228 // - Entry 0 -> Kind of this type of metadata (1). 3229 // - Entry 1 -> Mangled name of the variable. 3230 // - Entry 2 -> Declare target kind. 3231 // - Entry 3 -> Order the entry was created. 3232 // The first element of the metadata node is the kind. 3233 llvm::Metadata *Ops[] = { 3234 GetMDInt(E.getKind()), GetMDString(MangledName), 3235 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 3236 3237 // Save this entry in the right position of the ordered entries array. 3238 OrderedEntries[E.getOrder()] = 3239 std::make_tuple(&E, SourceLocation(), MangledName); 3240 3241 // Add metadata to the named metadata node. 3242 MD->addOperand(llvm::MDNode::get(C, Ops)); 3243 }; 3244 3245 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 3246 DeviceGlobalVarMetadataEmitter); 3247 3248 for (const auto &E : OrderedEntries) { 3249 assert(std::get<0>(E) && "All ordered entries must exist!"); 3250 if (const auto *CE = 3251 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 3252 std::get<0>(E))) { 3253 if (!CE->getID() || !CE->getAddress()) { 3254 // Do not blame the entry if the parent funtion is not emitted. 3255 StringRef FnName = ParentFunctions[CE->getOrder()]; 3256 if (!CGM.GetGlobalValue(FnName)) 3257 continue; 3258 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3259 DiagnosticsEngine::Error, 3260 "Offloading entry for target region in %0 is incorrect: either the " 3261 "address or the ID is invalid."); 3262 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 3263 continue; 3264 } 3265 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 3266 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 3267 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 3268 OffloadEntryInfoDeviceGlobalVar>( 3269 std::get<0>(E))) { 3270 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 3271 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3272 CE->getFlags()); 3273 switch (Flags) { 3274 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 3275 if (CGM.getLangOpts().OpenMPIsDevice && 3276 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 3277 continue; 3278 if (!CE->getAddress()) { 3279 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3280 DiagnosticsEngine::Error, "Offloading entry for declare target " 3281 "variable %0 is incorrect: the " 3282 "address is invalid."); 3283 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 3284 continue; 3285 } 3286 // The vaiable has no definition - no need to add the entry. 3287 if (CE->getVarSize().isZero()) 3288 continue; 3289 break; 3290 } 3291 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 3292 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 3293 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 3294 "Declaret target link address is set."); 3295 if (CGM.getLangOpts().OpenMPIsDevice) 3296 continue; 3297 if (!CE->getAddress()) { 3298 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3299 DiagnosticsEngine::Error, 3300 "Offloading entry for declare target variable is incorrect: the " 3301 "address is invalid."); 3302 CGM.getDiags().Report(DiagID); 3303 continue; 3304 } 3305 break; 3306 } 3307 createOffloadEntry(CE->getAddress(), CE->getAddress(), 3308 CE->getVarSize().getQuantity(), Flags, 3309 CE->getLinkage()); 3310 } else { 3311 llvm_unreachable("Unsupported entry kind."); 3312 } 3313 } 3314 } 3315 3316 /// Loads all the offload entries information from the host IR 3317 /// metadata. 3318 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 3319 // If we are in target mode, load the metadata from the host IR. This code has 3320 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 3321 3322 if (!CGM.getLangOpts().OpenMPIsDevice) 3323 return; 3324 3325 if (CGM.getLangOpts().OMPHostIRFile.empty()) 3326 return; 3327 3328 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 3329 if (auto EC = Buf.getError()) { 3330 CGM.getDiags().Report(diag::err_cannot_open_file) 3331 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3332 return; 3333 } 3334 3335 llvm::LLVMContext C; 3336 auto ME = expectedToErrorOrAndEmitErrors( 3337 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 3338 3339 if (auto EC = ME.getError()) { 3340 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3341 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 3342 CGM.getDiags().Report(DiagID) 3343 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3344 return; 3345 } 3346 3347 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 3348 if (!MD) 3349 return; 3350 3351 for (llvm::MDNode *MN : MD->operands()) { 3352 auto &&GetMDInt = [MN](unsigned Idx) { 3353 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 3354 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 3355 }; 3356 3357 auto &&GetMDString = [MN](unsigned Idx) { 3358 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 3359 return V->getString(); 3360 }; 3361 3362 switch (GetMDInt(0)) { 3363 default: 3364 llvm_unreachable("Unexpected metadata!"); 3365 break; 3366 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3367 OffloadingEntryInfoTargetRegion: 3368 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 3369 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 3370 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 3371 /*Order=*/GetMDInt(5)); 3372 break; 3373 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3374 OffloadingEntryInfoDeviceGlobalVar: 3375 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 3376 /*MangledName=*/GetMDString(1), 3377 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3378 /*Flags=*/GetMDInt(2)), 3379 /*Order=*/GetMDInt(3)); 3380 break; 3381 } 3382 } 3383 } 3384 3385 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 3386 if (!KmpRoutineEntryPtrTy) { 3387 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 3388 ASTContext &C = CGM.getContext(); 3389 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 3390 FunctionProtoType::ExtProtoInfo EPI; 3391 KmpRoutineEntryPtrQTy = C.getPointerType( 3392 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 3393 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 3394 } 3395 } 3396 3397 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 3398 // Make sure the type of the entry is already created. This is the type we 3399 // have to create: 3400 // struct __tgt_offload_entry{ 3401 // void *addr; // Pointer to the offload entry info. 3402 // // (function or global) 3403 // char *name; // Name of the function or global. 3404 // size_t size; // Size of the entry info (0 if it a function). 3405 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 3406 // int32_t reserved; // Reserved, to use by the runtime library. 3407 // }; 3408 if (TgtOffloadEntryQTy.isNull()) { 3409 ASTContext &C = CGM.getContext(); 3410 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 3411 RD->startDefinition(); 3412 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3413 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 3414 addFieldToRecordDecl(C, RD, C.getSizeType()); 3415 addFieldToRecordDecl( 3416 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3417 addFieldToRecordDecl( 3418 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3419 RD->completeDefinition(); 3420 RD->addAttr(PackedAttr::CreateImplicit(C)); 3421 TgtOffloadEntryQTy = C.getRecordType(RD); 3422 } 3423 return TgtOffloadEntryQTy; 3424 } 3425 3426 namespace { 3427 struct PrivateHelpersTy { 3428 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original, 3429 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit) 3430 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy), 3431 PrivateElemInit(PrivateElemInit) {} 3432 PrivateHelpersTy(const VarDecl *Original) : Original(Original) {} 3433 const Expr *OriginalRef = nullptr; 3434 const VarDecl *Original = nullptr; 3435 const VarDecl *PrivateCopy = nullptr; 3436 const VarDecl *PrivateElemInit = nullptr; 3437 bool isLocalPrivate() const { 3438 return !OriginalRef && !PrivateCopy && !PrivateElemInit; 3439 } 3440 }; 3441 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 3442 } // anonymous namespace 3443 3444 static bool isAllocatableDecl(const VarDecl *VD) { 3445 const VarDecl *CVD = VD->getCanonicalDecl(); 3446 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 3447 return false; 3448 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 3449 // Use the default allocation. 3450 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc || 3451 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) && 3452 !AA->getAllocator()); 3453 } 3454 3455 static RecordDecl * 3456 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 3457 if (!Privates.empty()) { 3458 ASTContext &C = CGM.getContext(); 3459 // Build struct .kmp_privates_t. { 3460 // /* private vars */ 3461 // }; 3462 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 3463 RD->startDefinition(); 3464 for (const auto &Pair : Privates) { 3465 const VarDecl *VD = Pair.second.Original; 3466 QualType Type = VD->getType().getNonReferenceType(); 3467 // If the private variable is a local variable with lvalue ref type, 3468 // allocate the pointer instead of the pointee type. 3469 if (Pair.second.isLocalPrivate()) { 3470 if (VD->getType()->isLValueReferenceType()) 3471 Type = C.getPointerType(Type); 3472 if (isAllocatableDecl(VD)) 3473 Type = C.getPointerType(Type); 3474 } 3475 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 3476 if (VD->hasAttrs()) { 3477 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 3478 E(VD->getAttrs().end()); 3479 I != E; ++I) 3480 FD->addAttr(*I); 3481 } 3482 } 3483 RD->completeDefinition(); 3484 return RD; 3485 } 3486 return nullptr; 3487 } 3488 3489 static RecordDecl * 3490 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 3491 QualType KmpInt32Ty, 3492 QualType KmpRoutineEntryPointerQTy) { 3493 ASTContext &C = CGM.getContext(); 3494 // Build struct kmp_task_t { 3495 // void * shareds; 3496 // kmp_routine_entry_t routine; 3497 // kmp_int32 part_id; 3498 // kmp_cmplrdata_t data1; 3499 // kmp_cmplrdata_t data2; 3500 // For taskloops additional fields: 3501 // kmp_uint64 lb; 3502 // kmp_uint64 ub; 3503 // kmp_int64 st; 3504 // kmp_int32 liter; 3505 // void * reductions; 3506 // }; 3507 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 3508 UD->startDefinition(); 3509 addFieldToRecordDecl(C, UD, KmpInt32Ty); 3510 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 3511 UD->completeDefinition(); 3512 QualType KmpCmplrdataTy = C.getRecordType(UD); 3513 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 3514 RD->startDefinition(); 3515 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3516 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 3517 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3518 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3519 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3520 if (isOpenMPTaskLoopDirective(Kind)) { 3521 QualType KmpUInt64Ty = 3522 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 3523 QualType KmpInt64Ty = 3524 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 3525 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3526 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3527 addFieldToRecordDecl(C, RD, KmpInt64Ty); 3528 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3529 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3530 } 3531 RD->completeDefinition(); 3532 return RD; 3533 } 3534 3535 static RecordDecl * 3536 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 3537 ArrayRef<PrivateDataTy> Privates) { 3538 ASTContext &C = CGM.getContext(); 3539 // Build struct kmp_task_t_with_privates { 3540 // kmp_task_t task_data; 3541 // .kmp_privates_t. privates; 3542 // }; 3543 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 3544 RD->startDefinition(); 3545 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 3546 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 3547 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 3548 RD->completeDefinition(); 3549 return RD; 3550 } 3551 3552 /// Emit a proxy function which accepts kmp_task_t as the second 3553 /// argument. 3554 /// \code 3555 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 3556 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 3557 /// For taskloops: 3558 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3559 /// tt->reductions, tt->shareds); 3560 /// return 0; 3561 /// } 3562 /// \endcode 3563 static llvm::Function * 3564 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 3565 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 3566 QualType KmpTaskTWithPrivatesPtrQTy, 3567 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 3568 QualType SharedsPtrTy, llvm::Function *TaskFunction, 3569 llvm::Value *TaskPrivatesMap) { 3570 ASTContext &C = CGM.getContext(); 3571 FunctionArgList Args; 3572 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3573 ImplicitParamDecl::Other); 3574 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3575 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3576 ImplicitParamDecl::Other); 3577 Args.push_back(&GtidArg); 3578 Args.push_back(&TaskTypeArg); 3579 const auto &TaskEntryFnInfo = 3580 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3581 llvm::FunctionType *TaskEntryTy = 3582 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 3583 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 3584 auto *TaskEntry = llvm::Function::Create( 3585 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3586 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 3587 TaskEntry->setDoesNotRecurse(); 3588 CodeGenFunction CGF(CGM); 3589 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 3590 Loc, Loc); 3591 3592 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 3593 // tt, 3594 // For taskloops: 3595 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3596 // tt->task_data.shareds); 3597 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 3598 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 3599 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3600 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3601 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3602 const auto *KmpTaskTWithPrivatesQTyRD = 3603 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3604 LValue Base = 3605 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3606 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3607 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 3608 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 3609 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 3610 3611 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 3612 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 3613 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3614 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 3615 CGF.ConvertTypeForMem(SharedsPtrTy)); 3616 3617 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 3618 llvm::Value *PrivatesParam; 3619 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 3620 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 3621 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3622 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 3623 } else { 3624 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3625 } 3626 3627 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 3628 TaskPrivatesMap, 3629 CGF.Builder 3630 .CreatePointerBitCastOrAddrSpaceCast( 3631 TDBase.getAddress(CGF), CGF.VoidPtrTy) 3632 .getPointer()}; 3633 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 3634 std::end(CommonArgs)); 3635 if (isOpenMPTaskLoopDirective(Kind)) { 3636 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 3637 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 3638 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 3639 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 3640 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 3641 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 3642 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 3643 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 3644 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 3645 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3646 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3647 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 3648 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 3649 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 3650 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 3651 CallArgs.push_back(LBParam); 3652 CallArgs.push_back(UBParam); 3653 CallArgs.push_back(StParam); 3654 CallArgs.push_back(LIParam); 3655 CallArgs.push_back(RParam); 3656 } 3657 CallArgs.push_back(SharedsParam); 3658 3659 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 3660 CallArgs); 3661 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 3662 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 3663 CGF.FinishFunction(); 3664 return TaskEntry; 3665 } 3666 3667 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 3668 SourceLocation Loc, 3669 QualType KmpInt32Ty, 3670 QualType KmpTaskTWithPrivatesPtrQTy, 3671 QualType KmpTaskTWithPrivatesQTy) { 3672 ASTContext &C = CGM.getContext(); 3673 FunctionArgList Args; 3674 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3675 ImplicitParamDecl::Other); 3676 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3677 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3678 ImplicitParamDecl::Other); 3679 Args.push_back(&GtidArg); 3680 Args.push_back(&TaskTypeArg); 3681 const auto &DestructorFnInfo = 3682 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3683 llvm::FunctionType *DestructorFnTy = 3684 CGM.getTypes().GetFunctionType(DestructorFnInfo); 3685 std::string Name = 3686 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 3687 auto *DestructorFn = 3688 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 3689 Name, &CGM.getModule()); 3690 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 3691 DestructorFnInfo); 3692 DestructorFn->setDoesNotRecurse(); 3693 CodeGenFunction CGF(CGM); 3694 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 3695 Args, Loc, Loc); 3696 3697 LValue Base = CGF.EmitLoadOfPointerLValue( 3698 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3699 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3700 const auto *KmpTaskTWithPrivatesQTyRD = 3701 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3702 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3703 Base = CGF.EmitLValueForField(Base, *FI); 3704 for (const auto *Field : 3705 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 3706 if (QualType::DestructionKind DtorKind = 3707 Field->getType().isDestructedType()) { 3708 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 3709 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 3710 } 3711 } 3712 CGF.FinishFunction(); 3713 return DestructorFn; 3714 } 3715 3716 /// Emit a privates mapping function for correct handling of private and 3717 /// firstprivate variables. 3718 /// \code 3719 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 3720 /// **noalias priv1,..., <tyn> **noalias privn) { 3721 /// *priv1 = &.privates.priv1; 3722 /// ...; 3723 /// *privn = &.privates.privn; 3724 /// } 3725 /// \endcode 3726 static llvm::Value * 3727 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 3728 const OMPTaskDataTy &Data, QualType PrivatesQTy, 3729 ArrayRef<PrivateDataTy> Privates) { 3730 ASTContext &C = CGM.getContext(); 3731 FunctionArgList Args; 3732 ImplicitParamDecl TaskPrivatesArg( 3733 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3734 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 3735 ImplicitParamDecl::Other); 3736 Args.push_back(&TaskPrivatesArg); 3737 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, unsigned> PrivateVarsPos; 3738 unsigned Counter = 1; 3739 for (const Expr *E : Data.PrivateVars) { 3740 Args.push_back(ImplicitParamDecl::Create( 3741 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3742 C.getPointerType(C.getPointerType(E->getType())) 3743 .withConst() 3744 .withRestrict(), 3745 ImplicitParamDecl::Other)); 3746 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3747 PrivateVarsPos[VD] = Counter; 3748 ++Counter; 3749 } 3750 for (const Expr *E : Data.FirstprivateVars) { 3751 Args.push_back(ImplicitParamDecl::Create( 3752 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3753 C.getPointerType(C.getPointerType(E->getType())) 3754 .withConst() 3755 .withRestrict(), 3756 ImplicitParamDecl::Other)); 3757 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3758 PrivateVarsPos[VD] = Counter; 3759 ++Counter; 3760 } 3761 for (const Expr *E : Data.LastprivateVars) { 3762 Args.push_back(ImplicitParamDecl::Create( 3763 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3764 C.getPointerType(C.getPointerType(E->getType())) 3765 .withConst() 3766 .withRestrict(), 3767 ImplicitParamDecl::Other)); 3768 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3769 PrivateVarsPos[VD] = Counter; 3770 ++Counter; 3771 } 3772 for (const VarDecl *VD : Data.PrivateLocals) { 3773 QualType Ty = VD->getType().getNonReferenceType(); 3774 if (VD->getType()->isLValueReferenceType()) 3775 Ty = C.getPointerType(Ty); 3776 if (isAllocatableDecl(VD)) 3777 Ty = C.getPointerType(Ty); 3778 Args.push_back(ImplicitParamDecl::Create( 3779 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3780 C.getPointerType(C.getPointerType(Ty)).withConst().withRestrict(), 3781 ImplicitParamDecl::Other)); 3782 PrivateVarsPos[VD] = Counter; 3783 ++Counter; 3784 } 3785 const auto &TaskPrivatesMapFnInfo = 3786 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3787 llvm::FunctionType *TaskPrivatesMapTy = 3788 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 3789 std::string Name = 3790 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 3791 auto *TaskPrivatesMap = llvm::Function::Create( 3792 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 3793 &CGM.getModule()); 3794 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 3795 TaskPrivatesMapFnInfo); 3796 if (CGM.getLangOpts().Optimize) { 3797 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 3798 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 3799 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 3800 } 3801 CodeGenFunction CGF(CGM); 3802 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 3803 TaskPrivatesMapFnInfo, Args, Loc, Loc); 3804 3805 // *privi = &.privates.privi; 3806 LValue Base = CGF.EmitLoadOfPointerLValue( 3807 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 3808 TaskPrivatesArg.getType()->castAs<PointerType>()); 3809 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 3810 Counter = 0; 3811 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 3812 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 3813 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 3814 LValue RefLVal = 3815 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 3816 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 3817 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 3818 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 3819 ++Counter; 3820 } 3821 CGF.FinishFunction(); 3822 return TaskPrivatesMap; 3823 } 3824 3825 /// Emit initialization for private variables in task-based directives. 3826 static void emitPrivatesInit(CodeGenFunction &CGF, 3827 const OMPExecutableDirective &D, 3828 Address KmpTaskSharedsPtr, LValue TDBase, 3829 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3830 QualType SharedsTy, QualType SharedsPtrTy, 3831 const OMPTaskDataTy &Data, 3832 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 3833 ASTContext &C = CGF.getContext(); 3834 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3835 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 3836 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 3837 ? OMPD_taskloop 3838 : OMPD_task; 3839 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 3840 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 3841 LValue SrcBase; 3842 bool IsTargetTask = 3843 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 3844 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 3845 // For target-based directives skip 4 firstprivate arrays BasePointersArray, 3846 // PointersArray, SizesArray, and MappersArray. The original variables for 3847 // these arrays are not captured and we get their addresses explicitly. 3848 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) || 3849 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 3850 SrcBase = CGF.MakeAddrLValue( 3851 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3852 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 3853 SharedsTy); 3854 } 3855 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 3856 for (const PrivateDataTy &Pair : Privates) { 3857 // Do not initialize private locals. 3858 if (Pair.second.isLocalPrivate()) { 3859 ++FI; 3860 continue; 3861 } 3862 const VarDecl *VD = Pair.second.PrivateCopy; 3863 const Expr *Init = VD->getAnyInitializer(); 3864 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 3865 !CGF.isTrivialInitializer(Init)))) { 3866 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 3867 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 3868 const VarDecl *OriginalVD = Pair.second.Original; 3869 // Check if the variable is the target-based BasePointersArray, 3870 // PointersArray, SizesArray, or MappersArray. 3871 LValue SharedRefLValue; 3872 QualType Type = PrivateLValue.getType(); 3873 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 3874 if (IsTargetTask && !SharedField) { 3875 assert(isa<ImplicitParamDecl>(OriginalVD) && 3876 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 3877 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3878 ->getNumParams() == 0 && 3879 isa<TranslationUnitDecl>( 3880 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3881 ->getDeclContext()) && 3882 "Expected artificial target data variable."); 3883 SharedRefLValue = 3884 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 3885 } else if (ForDup) { 3886 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 3887 SharedRefLValue = CGF.MakeAddrLValue( 3888 Address(SharedRefLValue.getPointer(CGF), 3889 C.getDeclAlign(OriginalVD)), 3890 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 3891 SharedRefLValue.getTBAAInfo()); 3892 } else if (CGF.LambdaCaptureFields.count( 3893 Pair.second.Original->getCanonicalDecl()) > 0 || 3894 dyn_cast_or_null<BlockDecl>(CGF.CurCodeDecl)) { 3895 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3896 } else { 3897 // Processing for implicitly captured variables. 3898 InlinedOpenMPRegionRAII Region( 3899 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown, 3900 /*HasCancel=*/false, /*NoInheritance=*/true); 3901 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3902 } 3903 if (Type->isArrayType()) { 3904 // Initialize firstprivate array. 3905 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 3906 // Perform simple memcpy. 3907 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 3908 } else { 3909 // Initialize firstprivate array using element-by-element 3910 // initialization. 3911 CGF.EmitOMPAggregateAssign( 3912 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 3913 Type, 3914 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 3915 Address SrcElement) { 3916 // Clean up any temporaries needed by the initialization. 3917 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3918 InitScope.addPrivate( 3919 Elem, [SrcElement]() -> Address { return SrcElement; }); 3920 (void)InitScope.Privatize(); 3921 // Emit initialization for single element. 3922 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 3923 CGF, &CapturesInfo); 3924 CGF.EmitAnyExprToMem(Init, DestElement, 3925 Init->getType().getQualifiers(), 3926 /*IsInitializer=*/false); 3927 }); 3928 } 3929 } else { 3930 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3931 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 3932 return SharedRefLValue.getAddress(CGF); 3933 }); 3934 (void)InitScope.Privatize(); 3935 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 3936 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 3937 /*capturedByInit=*/false); 3938 } 3939 } else { 3940 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 3941 } 3942 } 3943 ++FI; 3944 } 3945 } 3946 3947 /// Check if duplication function is required for taskloops. 3948 static bool checkInitIsRequired(CodeGenFunction &CGF, 3949 ArrayRef<PrivateDataTy> Privates) { 3950 bool InitRequired = false; 3951 for (const PrivateDataTy &Pair : Privates) { 3952 if (Pair.second.isLocalPrivate()) 3953 continue; 3954 const VarDecl *VD = Pair.second.PrivateCopy; 3955 const Expr *Init = VD->getAnyInitializer(); 3956 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 3957 !CGF.isTrivialInitializer(Init)); 3958 if (InitRequired) 3959 break; 3960 } 3961 return InitRequired; 3962 } 3963 3964 3965 /// Emit task_dup function (for initialization of 3966 /// private/firstprivate/lastprivate vars and last_iter flag) 3967 /// \code 3968 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 3969 /// lastpriv) { 3970 /// // setup lastprivate flag 3971 /// task_dst->last = lastpriv; 3972 /// // could be constructor calls here... 3973 /// } 3974 /// \endcode 3975 static llvm::Value * 3976 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 3977 const OMPExecutableDirective &D, 3978 QualType KmpTaskTWithPrivatesPtrQTy, 3979 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3980 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 3981 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 3982 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 3983 ASTContext &C = CGM.getContext(); 3984 FunctionArgList Args; 3985 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3986 KmpTaskTWithPrivatesPtrQTy, 3987 ImplicitParamDecl::Other); 3988 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3989 KmpTaskTWithPrivatesPtrQTy, 3990 ImplicitParamDecl::Other); 3991 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 3992 ImplicitParamDecl::Other); 3993 Args.push_back(&DstArg); 3994 Args.push_back(&SrcArg); 3995 Args.push_back(&LastprivArg); 3996 const auto &TaskDupFnInfo = 3997 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3998 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 3999 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4000 auto *TaskDup = llvm::Function::Create( 4001 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4002 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4003 TaskDup->setDoesNotRecurse(); 4004 CodeGenFunction CGF(CGM); 4005 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4006 Loc); 4007 4008 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4009 CGF.GetAddrOfLocalVar(&DstArg), 4010 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4011 // task_dst->liter = lastpriv; 4012 if (WithLastIter) { 4013 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4014 LValue Base = CGF.EmitLValueForField( 4015 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4016 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4017 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4018 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4019 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4020 } 4021 4022 // Emit initial values for private copies (if any). 4023 assert(!Privates.empty()); 4024 Address KmpTaskSharedsPtr = Address::invalid(); 4025 if (!Data.FirstprivateVars.empty()) { 4026 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4027 CGF.GetAddrOfLocalVar(&SrcArg), 4028 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4029 LValue Base = CGF.EmitLValueForField( 4030 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4031 KmpTaskSharedsPtr = Address( 4032 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4033 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4034 KmpTaskTShareds)), 4035 Loc), 4036 CGM.getNaturalTypeAlignment(SharedsTy)); 4037 } 4038 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4039 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4040 CGF.FinishFunction(); 4041 return TaskDup; 4042 } 4043 4044 /// Checks if destructor function is required to be generated. 4045 /// \return true if cleanups are required, false otherwise. 4046 static bool 4047 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4048 ArrayRef<PrivateDataTy> Privates) { 4049 for (const PrivateDataTy &P : Privates) { 4050 if (P.second.isLocalPrivate()) 4051 continue; 4052 QualType Ty = P.second.Original->getType().getNonReferenceType(); 4053 if (Ty.isDestructedType()) 4054 return true; 4055 } 4056 return false; 4057 } 4058 4059 namespace { 4060 /// Loop generator for OpenMP iterator expression. 4061 class OMPIteratorGeneratorScope final 4062 : public CodeGenFunction::OMPPrivateScope { 4063 CodeGenFunction &CGF; 4064 const OMPIteratorExpr *E = nullptr; 4065 SmallVector<CodeGenFunction::JumpDest, 4> ContDests; 4066 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests; 4067 OMPIteratorGeneratorScope() = delete; 4068 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete; 4069 4070 public: 4071 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E) 4072 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) { 4073 if (!E) 4074 return; 4075 SmallVector<llvm::Value *, 4> Uppers; 4076 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4077 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper)); 4078 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I)); 4079 addPrivate(VD, [&CGF, VD]() { 4080 return CGF.CreateMemTemp(VD->getType(), VD->getName()); 4081 }); 4082 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4083 addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() { 4084 return CGF.CreateMemTemp(HelperData.CounterVD->getType(), 4085 "counter.addr"); 4086 }); 4087 } 4088 Privatize(); 4089 4090 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4091 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4092 LValue CLVal = 4093 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD), 4094 HelperData.CounterVD->getType()); 4095 // Counter = 0; 4096 CGF.EmitStoreOfScalar( 4097 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0), 4098 CLVal); 4099 CodeGenFunction::JumpDest &ContDest = 4100 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont")); 4101 CodeGenFunction::JumpDest &ExitDest = 4102 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit")); 4103 // N = <number-of_iterations>; 4104 llvm::Value *N = Uppers[I]; 4105 // cont: 4106 // if (Counter < N) goto body; else goto exit; 4107 CGF.EmitBlock(ContDest.getBlock()); 4108 auto *CVal = 4109 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation()); 4110 llvm::Value *Cmp = 4111 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType() 4112 ? CGF.Builder.CreateICmpSLT(CVal, N) 4113 : CGF.Builder.CreateICmpULT(CVal, N); 4114 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body"); 4115 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock()); 4116 // body: 4117 CGF.EmitBlock(BodyBB); 4118 // Iteri = Begini + Counter * Stepi; 4119 CGF.EmitIgnoredExpr(HelperData.Update); 4120 } 4121 } 4122 ~OMPIteratorGeneratorScope() { 4123 if (!E) 4124 return; 4125 for (unsigned I = E->numOfIterators(); I > 0; --I) { 4126 // Counter = Counter + 1; 4127 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1); 4128 CGF.EmitIgnoredExpr(HelperData.CounterUpdate); 4129 // goto cont; 4130 CGF.EmitBranchThroughCleanup(ContDests[I - 1]); 4131 // exit: 4132 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1); 4133 } 4134 } 4135 }; 4136 } // namespace 4137 4138 static std::pair<llvm::Value *, llvm::Value *> 4139 getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { 4140 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E); 4141 llvm::Value *Addr; 4142 if (OASE) { 4143 const Expr *Base = OASE->getBase(); 4144 Addr = CGF.EmitScalarExpr(Base); 4145 } else { 4146 Addr = CGF.EmitLValue(E).getPointer(CGF); 4147 } 4148 llvm::Value *SizeVal; 4149 QualType Ty = E->getType(); 4150 if (OASE) { 4151 SizeVal = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType()); 4152 for (const Expr *SE : OASE->getDimensions()) { 4153 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 4154 Sz = CGF.EmitScalarConversion( 4155 Sz, SE->getType(), CGF.getContext().getSizeType(), SE->getExprLoc()); 4156 SizeVal = CGF.Builder.CreateNUWMul(SizeVal, Sz); 4157 } 4158 } else if (const auto *ASE = 4159 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 4160 LValue UpAddrLVal = 4161 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 4162 Address UpAddrAddress = UpAddrLVal.getAddress(CGF); 4163 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 4164 UpAddrAddress.getElementType(), UpAddrAddress.getPointer(), /*Idx0=*/1); 4165 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); 4166 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); 4167 SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 4168 } else { 4169 SizeVal = CGF.getTypeSize(Ty); 4170 } 4171 return std::make_pair(Addr, SizeVal); 4172 } 4173 4174 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4175 static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) { 4176 QualType FlagsTy = C.getIntTypeForBitwidth(32, /*Signed=*/false); 4177 if (KmpTaskAffinityInfoTy.isNull()) { 4178 RecordDecl *KmpAffinityInfoRD = 4179 C.buildImplicitRecord("kmp_task_affinity_info_t"); 4180 KmpAffinityInfoRD->startDefinition(); 4181 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getIntPtrType()); 4182 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType()); 4183 addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy); 4184 KmpAffinityInfoRD->completeDefinition(); 4185 KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD); 4186 } 4187 } 4188 4189 CGOpenMPRuntime::TaskResultTy 4190 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4191 const OMPExecutableDirective &D, 4192 llvm::Function *TaskFunction, QualType SharedsTy, 4193 Address Shareds, const OMPTaskDataTy &Data) { 4194 ASTContext &C = CGM.getContext(); 4195 llvm::SmallVector<PrivateDataTy, 4> Privates; 4196 // Aggregate privates and sort them by the alignment. 4197 const auto *I = Data.PrivateCopies.begin(); 4198 for (const Expr *E : Data.PrivateVars) { 4199 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4200 Privates.emplace_back( 4201 C.getDeclAlign(VD), 4202 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4203 /*PrivateElemInit=*/nullptr)); 4204 ++I; 4205 } 4206 I = Data.FirstprivateCopies.begin(); 4207 const auto *IElemInitRef = Data.FirstprivateInits.begin(); 4208 for (const Expr *E : Data.FirstprivateVars) { 4209 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4210 Privates.emplace_back( 4211 C.getDeclAlign(VD), 4212 PrivateHelpersTy( 4213 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4214 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4215 ++I; 4216 ++IElemInitRef; 4217 } 4218 I = Data.LastprivateCopies.begin(); 4219 for (const Expr *E : Data.LastprivateVars) { 4220 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4221 Privates.emplace_back( 4222 C.getDeclAlign(VD), 4223 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4224 /*PrivateElemInit=*/nullptr)); 4225 ++I; 4226 } 4227 for (const VarDecl *VD : Data.PrivateLocals) { 4228 if (isAllocatableDecl(VD)) 4229 Privates.emplace_back(CGM.getPointerAlign(), PrivateHelpersTy(VD)); 4230 else 4231 Privates.emplace_back(C.getDeclAlign(VD), PrivateHelpersTy(VD)); 4232 } 4233 llvm::stable_sort(Privates, 4234 [](const PrivateDataTy &L, const PrivateDataTy &R) { 4235 return L.first > R.first; 4236 }); 4237 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4238 // Build type kmp_routine_entry_t (if not built yet). 4239 emitKmpRoutineEntryT(KmpInt32Ty); 4240 // Build type kmp_task_t (if not built yet). 4241 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 4242 if (SavedKmpTaskloopTQTy.isNull()) { 4243 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4244 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4245 } 4246 KmpTaskTQTy = SavedKmpTaskloopTQTy; 4247 } else { 4248 assert((D.getDirectiveKind() == OMPD_task || 4249 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 4250 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 4251 "Expected taskloop, task or target directive"); 4252 if (SavedKmpTaskTQTy.isNull()) { 4253 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4254 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4255 } 4256 KmpTaskTQTy = SavedKmpTaskTQTy; 4257 } 4258 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4259 // Build particular struct kmp_task_t for the given task. 4260 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 4261 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 4262 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 4263 QualType KmpTaskTWithPrivatesPtrQTy = 4264 C.getPointerType(KmpTaskTWithPrivatesQTy); 4265 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 4266 llvm::Type *KmpTaskTWithPrivatesPtrTy = 4267 KmpTaskTWithPrivatesTy->getPointerTo(); 4268 llvm::Value *KmpTaskTWithPrivatesTySize = 4269 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 4270 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 4271 4272 // Emit initial values for private copies (if any). 4273 llvm::Value *TaskPrivatesMap = nullptr; 4274 llvm::Type *TaskPrivatesMapTy = 4275 std::next(TaskFunction->arg_begin(), 3)->getType(); 4276 if (!Privates.empty()) { 4277 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4278 TaskPrivatesMap = 4279 emitTaskPrivateMappingFunction(CGM, Loc, Data, FI->getType(), Privates); 4280 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4281 TaskPrivatesMap, TaskPrivatesMapTy); 4282 } else { 4283 TaskPrivatesMap = llvm::ConstantPointerNull::get( 4284 cast<llvm::PointerType>(TaskPrivatesMapTy)); 4285 } 4286 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 4287 // kmp_task_t *tt); 4288 llvm::Function *TaskEntry = emitProxyTaskFunction( 4289 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4290 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 4291 TaskPrivatesMap); 4292 4293 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 4294 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 4295 // kmp_routine_entry_t *task_entry); 4296 // Task flags. Format is taken from 4297 // https://github.com/llvm/llvm-project/blob/main/openmp/runtime/src/kmp.h, 4298 // description of kmp_tasking_flags struct. 4299 enum { 4300 TiedFlag = 0x1, 4301 FinalFlag = 0x2, 4302 DestructorsFlag = 0x8, 4303 PriorityFlag = 0x20, 4304 DetachableFlag = 0x40, 4305 }; 4306 unsigned Flags = Data.Tied ? TiedFlag : 0; 4307 bool NeedsCleanup = false; 4308 if (!Privates.empty()) { 4309 NeedsCleanup = 4310 checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD, Privates); 4311 if (NeedsCleanup) 4312 Flags = Flags | DestructorsFlag; 4313 } 4314 if (Data.Priority.getInt()) 4315 Flags = Flags | PriorityFlag; 4316 if (D.hasClausesOfKind<OMPDetachClause>()) 4317 Flags = Flags | DetachableFlag; 4318 llvm::Value *TaskFlags = 4319 Data.Final.getPointer() 4320 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 4321 CGF.Builder.getInt32(FinalFlag), 4322 CGF.Builder.getInt32(/*C=*/0)) 4323 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 4324 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 4325 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 4326 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 4327 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 4328 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4329 TaskEntry, KmpRoutineEntryPtrTy)}; 4330 llvm::Value *NewTask; 4331 if (D.hasClausesOfKind<OMPNowaitClause>()) { 4332 // Check if we have any device clause associated with the directive. 4333 const Expr *Device = nullptr; 4334 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 4335 Device = C->getDevice(); 4336 // Emit device ID if any otherwise use default value. 4337 llvm::Value *DeviceID; 4338 if (Device) 4339 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 4340 CGF.Int64Ty, /*isSigned=*/true); 4341 else 4342 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 4343 AllocArgs.push_back(DeviceID); 4344 NewTask = CGF.EmitRuntimeCall( 4345 OMPBuilder.getOrCreateRuntimeFunction( 4346 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc), 4347 AllocArgs); 4348 } else { 4349 NewTask = 4350 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 4351 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc), 4352 AllocArgs); 4353 } 4354 // Emit detach clause initialization. 4355 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid, 4356 // task_descriptor); 4357 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) { 4358 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts(); 4359 LValue EvtLVal = CGF.EmitLValue(Evt); 4360 4361 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 4362 // int gtid, kmp_task_t *task); 4363 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc()); 4364 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc()); 4365 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false); 4366 llvm::Value *EvtVal = CGF.EmitRuntimeCall( 4367 OMPBuilder.getOrCreateRuntimeFunction( 4368 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event), 4369 {Loc, Tid, NewTask}); 4370 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(), 4371 Evt->getExprLoc()); 4372 CGF.EmitStoreOfScalar(EvtVal, EvtLVal); 4373 } 4374 // Process affinity clauses. 4375 if (D.hasClausesOfKind<OMPAffinityClause>()) { 4376 // Process list of affinity data. 4377 ASTContext &C = CGM.getContext(); 4378 Address AffinitiesArray = Address::invalid(); 4379 // Calculate number of elements to form the array of affinity data. 4380 llvm::Value *NumOfElements = nullptr; 4381 unsigned NumAffinities = 0; 4382 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4383 if (const Expr *Modifier = C->getModifier()) { 4384 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts()); 4385 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4386 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4387 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4388 NumOfElements = 4389 NumOfElements ? CGF.Builder.CreateNUWMul(NumOfElements, Sz) : Sz; 4390 } 4391 } else { 4392 NumAffinities += C->varlist_size(); 4393 } 4394 } 4395 getKmpAffinityType(CGM.getContext(), KmpTaskAffinityInfoTy); 4396 // Fields ids in kmp_task_affinity_info record. 4397 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags }; 4398 4399 QualType KmpTaskAffinityInfoArrayTy; 4400 if (NumOfElements) { 4401 NumOfElements = CGF.Builder.CreateNUWAdd( 4402 llvm::ConstantInt::get(CGF.SizeTy, NumAffinities), NumOfElements); 4403 OpaqueValueExpr OVE( 4404 Loc, 4405 C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0), 4406 VK_PRValue); 4407 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 4408 RValue::get(NumOfElements)); 4409 KmpTaskAffinityInfoArrayTy = 4410 C.getVariableArrayType(KmpTaskAffinityInfoTy, &OVE, ArrayType::Normal, 4411 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4412 // Properly emit variable-sized array. 4413 auto *PD = ImplicitParamDecl::Create(C, KmpTaskAffinityInfoArrayTy, 4414 ImplicitParamDecl::Other); 4415 CGF.EmitVarDecl(*PD); 4416 AffinitiesArray = CGF.GetAddrOfLocalVar(PD); 4417 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4418 /*isSigned=*/false); 4419 } else { 4420 KmpTaskAffinityInfoArrayTy = C.getConstantArrayType( 4421 KmpTaskAffinityInfoTy, 4422 llvm::APInt(C.getTypeSize(C.getSizeType()), NumAffinities), nullptr, 4423 ArrayType::Normal, /*IndexTypeQuals=*/0); 4424 AffinitiesArray = 4425 CGF.CreateMemTemp(KmpTaskAffinityInfoArrayTy, ".affs.arr.addr"); 4426 AffinitiesArray = CGF.Builder.CreateConstArrayGEP(AffinitiesArray, 0); 4427 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumAffinities, 4428 /*isSigned=*/false); 4429 } 4430 4431 const auto *KmpAffinityInfoRD = KmpTaskAffinityInfoTy->getAsRecordDecl(); 4432 // Fill array by elements without iterators. 4433 unsigned Pos = 0; 4434 bool HasIterator = false; 4435 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4436 if (C->getModifier()) { 4437 HasIterator = true; 4438 continue; 4439 } 4440 for (const Expr *E : C->varlists()) { 4441 llvm::Value *Addr; 4442 llvm::Value *Size; 4443 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4444 LValue Base = 4445 CGF.MakeAddrLValue(CGF.Builder.CreateConstGEP(AffinitiesArray, Pos), 4446 KmpTaskAffinityInfoTy); 4447 // affs[i].base_addr = &<Affinities[i].second>; 4448 LValue BaseAddrLVal = CGF.EmitLValueForField( 4449 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4450 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4451 BaseAddrLVal); 4452 // affs[i].len = sizeof(<Affinities[i].second>); 4453 LValue LenLVal = CGF.EmitLValueForField( 4454 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4455 CGF.EmitStoreOfScalar(Size, LenLVal); 4456 ++Pos; 4457 } 4458 } 4459 LValue PosLVal; 4460 if (HasIterator) { 4461 PosLVal = CGF.MakeAddrLValue( 4462 CGF.CreateMemTemp(C.getSizeType(), "affs.counter.addr"), 4463 C.getSizeType()); 4464 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4465 } 4466 // Process elements with iterators. 4467 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4468 const Expr *Modifier = C->getModifier(); 4469 if (!Modifier) 4470 continue; 4471 OMPIteratorGeneratorScope IteratorScope( 4472 CGF, cast_or_null<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts())); 4473 for (const Expr *E : C->varlists()) { 4474 llvm::Value *Addr; 4475 llvm::Value *Size; 4476 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4477 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4478 LValue Base = CGF.MakeAddrLValue( 4479 Address(CGF.Builder.CreateGEP(AffinitiesArray.getElementType(), 4480 AffinitiesArray.getPointer(), Idx), 4481 AffinitiesArray.getAlignment()), 4482 KmpTaskAffinityInfoTy); 4483 // affs[i].base_addr = &<Affinities[i].second>; 4484 LValue BaseAddrLVal = CGF.EmitLValueForField( 4485 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4486 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4487 BaseAddrLVal); 4488 // affs[i].len = sizeof(<Affinities[i].second>); 4489 LValue LenLVal = CGF.EmitLValueForField( 4490 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4491 CGF.EmitStoreOfScalar(Size, LenLVal); 4492 Idx = CGF.Builder.CreateNUWAdd( 4493 Idx, llvm::ConstantInt::get(Idx->getType(), 1)); 4494 CGF.EmitStoreOfScalar(Idx, PosLVal); 4495 } 4496 } 4497 // Call to kmp_int32 __kmpc_omp_reg_task_with_affinity(ident_t *loc_ref, 4498 // kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 4499 // naffins, kmp_task_affinity_info_t *affin_list); 4500 llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); 4501 llvm::Value *GTid = getThreadID(CGF, Loc); 4502 llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4503 AffinitiesArray.getPointer(), CGM.VoidPtrTy); 4504 // FIXME: Emit the function and ignore its result for now unless the 4505 // runtime function is properly implemented. 4506 (void)CGF.EmitRuntimeCall( 4507 OMPBuilder.getOrCreateRuntimeFunction( 4508 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity), 4509 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr}); 4510 } 4511 llvm::Value *NewTaskNewTaskTTy = 4512 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4513 NewTask, KmpTaskTWithPrivatesPtrTy); 4514 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 4515 KmpTaskTWithPrivatesQTy); 4516 LValue TDBase = 4517 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4518 // Fill the data in the resulting kmp_task_t record. 4519 // Copy shareds if there are any. 4520 Address KmpTaskSharedsPtr = Address::invalid(); 4521 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 4522 KmpTaskSharedsPtr = 4523 Address(CGF.EmitLoadOfScalar( 4524 CGF.EmitLValueForField( 4525 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 4526 KmpTaskTShareds)), 4527 Loc), 4528 CGM.getNaturalTypeAlignment(SharedsTy)); 4529 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 4530 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 4531 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 4532 } 4533 // Emit initial values for private copies (if any). 4534 TaskResultTy Result; 4535 if (!Privates.empty()) { 4536 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 4537 SharedsTy, SharedsPtrTy, Data, Privates, 4538 /*ForDup=*/false); 4539 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 4540 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 4541 Result.TaskDupFn = emitTaskDupFunction( 4542 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 4543 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 4544 /*WithLastIter=*/!Data.LastprivateVars.empty()); 4545 } 4546 } 4547 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 4548 enum { Priority = 0, Destructors = 1 }; 4549 // Provide pointer to function with destructors for privates. 4550 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 4551 const RecordDecl *KmpCmplrdataUD = 4552 (*FI)->getType()->getAsUnionType()->getDecl(); 4553 if (NeedsCleanup) { 4554 llvm::Value *DestructorFn = emitDestructorsFunction( 4555 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4556 KmpTaskTWithPrivatesQTy); 4557 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 4558 LValue DestructorsLV = CGF.EmitLValueForField( 4559 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 4560 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4561 DestructorFn, KmpRoutineEntryPtrTy), 4562 DestructorsLV); 4563 } 4564 // Set priority. 4565 if (Data.Priority.getInt()) { 4566 LValue Data2LV = CGF.EmitLValueForField( 4567 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 4568 LValue PriorityLV = CGF.EmitLValueForField( 4569 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 4570 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 4571 } 4572 Result.NewTask = NewTask; 4573 Result.TaskEntry = TaskEntry; 4574 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 4575 Result.TDBase = TDBase; 4576 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 4577 return Result; 4578 } 4579 4580 namespace { 4581 /// Dependence kind for RTL. 4582 enum RTLDependenceKindTy { 4583 DepIn = 0x01, 4584 DepInOut = 0x3, 4585 DepMutexInOutSet = 0x4 4586 }; 4587 /// Fields ids in kmp_depend_info record. 4588 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 4589 } // namespace 4590 4591 /// Translates internal dependency kind into the runtime kind. 4592 static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { 4593 RTLDependenceKindTy DepKind; 4594 switch (K) { 4595 case OMPC_DEPEND_in: 4596 DepKind = DepIn; 4597 break; 4598 // Out and InOut dependencies must use the same code. 4599 case OMPC_DEPEND_out: 4600 case OMPC_DEPEND_inout: 4601 DepKind = DepInOut; 4602 break; 4603 case OMPC_DEPEND_mutexinoutset: 4604 DepKind = DepMutexInOutSet; 4605 break; 4606 case OMPC_DEPEND_source: 4607 case OMPC_DEPEND_sink: 4608 case OMPC_DEPEND_depobj: 4609 case OMPC_DEPEND_unknown: 4610 llvm_unreachable("Unknown task dependence type"); 4611 } 4612 return DepKind; 4613 } 4614 4615 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4616 static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, 4617 QualType &FlagsTy) { 4618 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 4619 if (KmpDependInfoTy.isNull()) { 4620 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 4621 KmpDependInfoRD->startDefinition(); 4622 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 4623 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 4624 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 4625 KmpDependInfoRD->completeDefinition(); 4626 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 4627 } 4628 } 4629 4630 std::pair<llvm::Value *, LValue> 4631 CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, 4632 SourceLocation Loc) { 4633 ASTContext &C = CGM.getContext(); 4634 QualType FlagsTy; 4635 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4636 RecordDecl *KmpDependInfoRD = 4637 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4638 LValue Base = CGF.EmitLoadOfPointerLValue( 4639 DepobjLVal.getAddress(CGF), 4640 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4641 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4642 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4643 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 4644 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4645 Base.getTBAAInfo()); 4646 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4647 Addr.getElementType(), Addr.getPointer(), 4648 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4649 LValue NumDepsBase = CGF.MakeAddrLValue( 4650 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4651 Base.getBaseInfo(), Base.getTBAAInfo()); 4652 // NumDeps = deps[i].base_addr; 4653 LValue BaseAddrLVal = CGF.EmitLValueForField( 4654 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4655 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc); 4656 return std::make_pair(NumDeps, Base); 4657 } 4658 4659 static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4660 llvm::PointerUnion<unsigned *, LValue *> Pos, 4661 const OMPTaskDataTy::DependData &Data, 4662 Address DependenciesArray) { 4663 CodeGenModule &CGM = CGF.CGM; 4664 ASTContext &C = CGM.getContext(); 4665 QualType FlagsTy; 4666 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4667 RecordDecl *KmpDependInfoRD = 4668 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4669 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 4670 4671 OMPIteratorGeneratorScope IteratorScope( 4672 CGF, cast_or_null<OMPIteratorExpr>( 4673 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4674 : nullptr)); 4675 for (const Expr *E : Data.DepExprs) { 4676 llvm::Value *Addr; 4677 llvm::Value *Size; 4678 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4679 LValue Base; 4680 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4681 Base = CGF.MakeAddrLValue( 4682 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy); 4683 } else { 4684 LValue &PosLVal = *Pos.get<LValue *>(); 4685 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4686 Base = CGF.MakeAddrLValue( 4687 Address(CGF.Builder.CreateGEP(DependenciesArray.getElementType(), 4688 DependenciesArray.getPointer(), Idx), 4689 DependenciesArray.getAlignment()), 4690 KmpDependInfoTy); 4691 } 4692 // deps[i].base_addr = &<Dependencies[i].second>; 4693 LValue BaseAddrLVal = CGF.EmitLValueForField( 4694 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4695 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4696 BaseAddrLVal); 4697 // deps[i].len = sizeof(<Dependencies[i].second>); 4698 LValue LenLVal = CGF.EmitLValueForField( 4699 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 4700 CGF.EmitStoreOfScalar(Size, LenLVal); 4701 // deps[i].flags = <Dependencies[i].first>; 4702 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind); 4703 LValue FlagsLVal = CGF.EmitLValueForField( 4704 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 4705 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 4706 FlagsLVal); 4707 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4708 ++(*P); 4709 } else { 4710 LValue &PosLVal = *Pos.get<LValue *>(); 4711 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4712 Idx = CGF.Builder.CreateNUWAdd(Idx, 4713 llvm::ConstantInt::get(Idx->getType(), 1)); 4714 CGF.EmitStoreOfScalar(Idx, PosLVal); 4715 } 4716 } 4717 } 4718 4719 static SmallVector<llvm::Value *, 4> 4720 emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4721 const OMPTaskDataTy::DependData &Data) { 4722 assert(Data.DepKind == OMPC_DEPEND_depobj && 4723 "Expected depobj dependecy kind."); 4724 SmallVector<llvm::Value *, 4> Sizes; 4725 SmallVector<LValue, 4> SizeLVals; 4726 ASTContext &C = CGF.getContext(); 4727 QualType FlagsTy; 4728 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4729 RecordDecl *KmpDependInfoRD = 4730 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4731 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4732 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4733 { 4734 OMPIteratorGeneratorScope IteratorScope( 4735 CGF, cast_or_null<OMPIteratorExpr>( 4736 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4737 : nullptr)); 4738 for (const Expr *E : Data.DepExprs) { 4739 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4740 LValue Base = CGF.EmitLoadOfPointerLValue( 4741 DepobjLVal.getAddress(CGF), 4742 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4743 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4744 Base.getAddress(CGF), KmpDependInfoPtrT); 4745 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4746 Base.getTBAAInfo()); 4747 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4748 Addr.getElementType(), Addr.getPointer(), 4749 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4750 LValue NumDepsBase = CGF.MakeAddrLValue( 4751 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4752 Base.getBaseInfo(), Base.getTBAAInfo()); 4753 // NumDeps = deps[i].base_addr; 4754 LValue BaseAddrLVal = CGF.EmitLValueForField( 4755 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4756 llvm::Value *NumDeps = 4757 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4758 LValue NumLVal = CGF.MakeAddrLValue( 4759 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"), 4760 C.getUIntPtrType()); 4761 CGF.InitTempAlloca(NumLVal.getAddress(CGF), 4762 llvm::ConstantInt::get(CGF.IntPtrTy, 0)); 4763 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc()); 4764 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps); 4765 CGF.EmitStoreOfScalar(Add, NumLVal); 4766 SizeLVals.push_back(NumLVal); 4767 } 4768 } 4769 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) { 4770 llvm::Value *Size = 4771 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc()); 4772 Sizes.push_back(Size); 4773 } 4774 return Sizes; 4775 } 4776 4777 static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4778 LValue PosLVal, 4779 const OMPTaskDataTy::DependData &Data, 4780 Address DependenciesArray) { 4781 assert(Data.DepKind == OMPC_DEPEND_depobj && 4782 "Expected depobj dependecy kind."); 4783 ASTContext &C = CGF.getContext(); 4784 QualType FlagsTy; 4785 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4786 RecordDecl *KmpDependInfoRD = 4787 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4788 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4789 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4790 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy); 4791 { 4792 OMPIteratorGeneratorScope IteratorScope( 4793 CGF, cast_or_null<OMPIteratorExpr>( 4794 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4795 : nullptr)); 4796 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) { 4797 const Expr *E = Data.DepExprs[I]; 4798 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4799 LValue Base = CGF.EmitLoadOfPointerLValue( 4800 DepobjLVal.getAddress(CGF), 4801 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4802 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4803 Base.getAddress(CGF), KmpDependInfoPtrT); 4804 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4805 Base.getTBAAInfo()); 4806 4807 // Get number of elements in a single depobj. 4808 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4809 Addr.getElementType(), Addr.getPointer(), 4810 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4811 LValue NumDepsBase = CGF.MakeAddrLValue( 4812 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4813 Base.getBaseInfo(), Base.getTBAAInfo()); 4814 // NumDeps = deps[i].base_addr; 4815 LValue BaseAddrLVal = CGF.EmitLValueForField( 4816 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4817 llvm::Value *NumDeps = 4818 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4819 4820 // memcopy dependency data. 4821 llvm::Value *Size = CGF.Builder.CreateNUWMul( 4822 ElSize, 4823 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); 4824 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4825 Address DepAddr = 4826 Address(CGF.Builder.CreateGEP(DependenciesArray.getElementType(), 4827 DependenciesArray.getPointer(), Pos), 4828 DependenciesArray.getAlignment()); 4829 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); 4830 4831 // Increase pos. 4832 // pos += size; 4833 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps); 4834 CGF.EmitStoreOfScalar(Add, PosLVal); 4835 } 4836 } 4837 } 4838 4839 std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause( 4840 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies, 4841 SourceLocation Loc) { 4842 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) { 4843 return D.DepExprs.empty(); 4844 })) 4845 return std::make_pair(nullptr, Address::invalid()); 4846 // Process list of dependencies. 4847 ASTContext &C = CGM.getContext(); 4848 Address DependenciesArray = Address::invalid(); 4849 llvm::Value *NumOfElements = nullptr; 4850 unsigned NumDependencies = std::accumulate( 4851 Dependencies.begin(), Dependencies.end(), 0, 4852 [](unsigned V, const OMPTaskDataTy::DependData &D) { 4853 return D.DepKind == OMPC_DEPEND_depobj 4854 ? V 4855 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size())); 4856 }); 4857 QualType FlagsTy; 4858 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4859 bool HasDepobjDeps = false; 4860 bool HasRegularWithIterators = false; 4861 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0); 4862 llvm::Value *NumOfRegularWithIterators = 4863 llvm::ConstantInt::get(CGF.IntPtrTy, 1); 4864 // Calculate number of depobj dependecies and regular deps with the iterators. 4865 for (const OMPTaskDataTy::DependData &D : Dependencies) { 4866 if (D.DepKind == OMPC_DEPEND_depobj) { 4867 SmallVector<llvm::Value *, 4> Sizes = 4868 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D); 4869 for (llvm::Value *Size : Sizes) { 4870 NumOfDepobjElements = 4871 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size); 4872 } 4873 HasDepobjDeps = true; 4874 continue; 4875 } 4876 // Include number of iterations, if any. 4877 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) { 4878 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4879 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4880 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false); 4881 NumOfRegularWithIterators = 4882 CGF.Builder.CreateNUWMul(NumOfRegularWithIterators, Sz); 4883 } 4884 HasRegularWithIterators = true; 4885 continue; 4886 } 4887 } 4888 4889 QualType KmpDependInfoArrayTy; 4890 if (HasDepobjDeps || HasRegularWithIterators) { 4891 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies, 4892 /*isSigned=*/false); 4893 if (HasDepobjDeps) { 4894 NumOfElements = 4895 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements); 4896 } 4897 if (HasRegularWithIterators) { 4898 NumOfElements = 4899 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements); 4900 } 4901 OpaqueValueExpr OVE(Loc, 4902 C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0), 4903 VK_PRValue); 4904 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 4905 RValue::get(NumOfElements)); 4906 KmpDependInfoArrayTy = 4907 C.getVariableArrayType(KmpDependInfoTy, &OVE, ArrayType::Normal, 4908 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4909 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy); 4910 // Properly emit variable-sized array. 4911 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy, 4912 ImplicitParamDecl::Other); 4913 CGF.EmitVarDecl(*PD); 4914 DependenciesArray = CGF.GetAddrOfLocalVar(PD); 4915 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4916 /*isSigned=*/false); 4917 } else { 4918 KmpDependInfoArrayTy = C.getConstantArrayType( 4919 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr, 4920 ArrayType::Normal, /*IndexTypeQuals=*/0); 4921 DependenciesArray = 4922 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 4923 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0); 4924 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 4925 /*isSigned=*/false); 4926 } 4927 unsigned Pos = 0; 4928 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4929 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4930 Dependencies[I].IteratorExpr) 4931 continue; 4932 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I], 4933 DependenciesArray); 4934 } 4935 // Copy regular dependecies with iterators. 4936 LValue PosLVal = CGF.MakeAddrLValue( 4937 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType()); 4938 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4939 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4940 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4941 !Dependencies[I].IteratorExpr) 4942 continue; 4943 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I], 4944 DependenciesArray); 4945 } 4946 // Copy final depobj arrays without iterators. 4947 if (HasDepobjDeps) { 4948 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4949 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj) 4950 continue; 4951 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I], 4952 DependenciesArray); 4953 } 4954 } 4955 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4956 DependenciesArray, CGF.VoidPtrTy); 4957 return std::make_pair(NumOfElements, DependenciesArray); 4958 } 4959 4960 Address CGOpenMPRuntime::emitDepobjDependClause( 4961 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, 4962 SourceLocation Loc) { 4963 if (Dependencies.DepExprs.empty()) 4964 return Address::invalid(); 4965 // Process list of dependencies. 4966 ASTContext &C = CGM.getContext(); 4967 Address DependenciesArray = Address::invalid(); 4968 unsigned NumDependencies = Dependencies.DepExprs.size(); 4969 QualType FlagsTy; 4970 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4971 RecordDecl *KmpDependInfoRD = 4972 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4973 4974 llvm::Value *Size; 4975 // Define type kmp_depend_info[<Dependencies.size()>]; 4976 // For depobj reserve one extra element to store the number of elements. 4977 // It is required to handle depobj(x) update(in) construct. 4978 // kmp_depend_info[<Dependencies.size()>] deps; 4979 llvm::Value *NumDepsVal; 4980 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy); 4981 if (const auto *IE = 4982 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) { 4983 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1); 4984 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4985 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4986 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4987 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz); 4988 } 4989 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1), 4990 NumDepsVal); 4991 CharUnits SizeInBytes = 4992 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align); 4993 llvm::Value *RecSize = CGM.getSize(SizeInBytes); 4994 Size = CGF.Builder.CreateNUWMul(Size, RecSize); 4995 NumDepsVal = 4996 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false); 4997 } else { 4998 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 4999 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1), 5000 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5001 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy); 5002 Size = CGM.getSize(Sz.alignTo(Align)); 5003 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies); 5004 } 5005 // Need to allocate on the dynamic memory. 5006 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5007 // Use default allocator. 5008 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5009 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 5010 5011 llvm::Value *Addr = 5012 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5013 CGM.getModule(), OMPRTL___kmpc_alloc), 5014 Args, ".dep.arr.addr"); 5015 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5016 Addr, CGF.ConvertTypeForMem(KmpDependInfoTy)->getPointerTo()); 5017 DependenciesArray = Address(Addr, Align); 5018 // Write number of elements in the first element of array for depobj. 5019 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy); 5020 // deps[i].base_addr = NumDependencies; 5021 LValue BaseAddrLVal = CGF.EmitLValueForField( 5022 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5023 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal); 5024 llvm::PointerUnion<unsigned *, LValue *> Pos; 5025 unsigned Idx = 1; 5026 LValue PosLVal; 5027 if (Dependencies.IteratorExpr) { 5028 PosLVal = CGF.MakeAddrLValue( 5029 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"), 5030 C.getSizeType()); 5031 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal, 5032 /*IsInit=*/true); 5033 Pos = &PosLVal; 5034 } else { 5035 Pos = &Idx; 5036 } 5037 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray); 5038 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5039 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy); 5040 return DependenciesArray; 5041 } 5042 5043 void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 5044 SourceLocation Loc) { 5045 ASTContext &C = CGM.getContext(); 5046 QualType FlagsTy; 5047 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5048 LValue Base = CGF.EmitLoadOfPointerLValue( 5049 DepobjLVal.getAddress(CGF), 5050 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5051 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5052 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5053 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 5054 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5055 Addr.getElementType(), Addr.getPointer(), 5056 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5057 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, 5058 CGF.VoidPtrTy); 5059 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5060 // Use default allocator. 5061 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5062 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator}; 5063 5064 // _kmpc_free(gtid, addr, nullptr); 5065 (void)CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5066 CGM.getModule(), OMPRTL___kmpc_free), 5067 Args); 5068 } 5069 5070 void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 5071 OpenMPDependClauseKind NewDepKind, 5072 SourceLocation Loc) { 5073 ASTContext &C = CGM.getContext(); 5074 QualType FlagsTy; 5075 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5076 RecordDecl *KmpDependInfoRD = 5077 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5078 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5079 llvm::Value *NumDeps; 5080 LValue Base; 5081 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 5082 5083 Address Begin = Base.getAddress(CGF); 5084 // Cast from pointer to array type to pointer to single element. 5085 llvm::Value *End = CGF.Builder.CreateGEP( 5086 Begin.getElementType(), Begin.getPointer(), NumDeps); 5087 // The basic structure here is a while-do loop. 5088 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); 5089 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); 5090 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5091 CGF.EmitBlock(BodyBB); 5092 llvm::PHINode *ElementPHI = 5093 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); 5094 ElementPHI->addIncoming(Begin.getPointer(), EntryBB); 5095 Begin = Address(ElementPHI, Begin.getAlignment()); 5096 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), 5097 Base.getTBAAInfo()); 5098 // deps[i].flags = NewDepKind; 5099 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind); 5100 LValue FlagsLVal = CGF.EmitLValueForField( 5101 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5102 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5103 FlagsLVal); 5104 5105 // Shift the address forward by one element. 5106 Address ElementNext = 5107 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); 5108 ElementPHI->addIncoming(ElementNext.getPointer(), 5109 CGF.Builder.GetInsertBlock()); 5110 llvm::Value *IsEmpty = 5111 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); 5112 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5113 // Done. 5114 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5115 } 5116 5117 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5118 const OMPExecutableDirective &D, 5119 llvm::Function *TaskFunction, 5120 QualType SharedsTy, Address Shareds, 5121 const Expr *IfCond, 5122 const OMPTaskDataTy &Data) { 5123 if (!CGF.HaveInsertPoint()) 5124 return; 5125 5126 TaskResultTy Result = 5127 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5128 llvm::Value *NewTask = Result.NewTask; 5129 llvm::Function *TaskEntry = Result.TaskEntry; 5130 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5131 LValue TDBase = Result.TDBase; 5132 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5133 // Process list of dependences. 5134 Address DependenciesArray = Address::invalid(); 5135 llvm::Value *NumOfElements; 5136 std::tie(NumOfElements, DependenciesArray) = 5137 emitDependClause(CGF, Data.Dependences, Loc); 5138 5139 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5140 // libcall. 5141 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5142 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5143 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5144 // list is not empty 5145 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5146 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5147 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5148 llvm::Value *DepTaskArgs[7]; 5149 if (!Data.Dependences.empty()) { 5150 DepTaskArgs[0] = UpLoc; 5151 DepTaskArgs[1] = ThreadID; 5152 DepTaskArgs[2] = NewTask; 5153 DepTaskArgs[3] = NumOfElements; 5154 DepTaskArgs[4] = DependenciesArray.getPointer(); 5155 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5156 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5157 } 5158 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs, 5159 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5160 if (!Data.Tied) { 5161 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5162 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5163 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5164 } 5165 if (!Data.Dependences.empty()) { 5166 CGF.EmitRuntimeCall( 5167 OMPBuilder.getOrCreateRuntimeFunction( 5168 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps), 5169 DepTaskArgs); 5170 } else { 5171 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5172 CGM.getModule(), OMPRTL___kmpc_omp_task), 5173 TaskArgs); 5174 } 5175 // Check if parent region is untied and build return for untied task; 5176 if (auto *Region = 5177 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5178 Region->emitUntiedSwitch(CGF); 5179 }; 5180 5181 llvm::Value *DepWaitTaskArgs[6]; 5182 if (!Data.Dependences.empty()) { 5183 DepWaitTaskArgs[0] = UpLoc; 5184 DepWaitTaskArgs[1] = ThreadID; 5185 DepWaitTaskArgs[2] = NumOfElements; 5186 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5187 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5188 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5189 } 5190 auto &M = CGM.getModule(); 5191 auto &&ElseCodeGen = [this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy, 5192 TaskEntry, &Data, &DepWaitTaskArgs, 5193 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5194 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5195 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5196 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5197 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5198 // is specified. 5199 if (!Data.Dependences.empty()) 5200 CGF.EmitRuntimeCall( 5201 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps), 5202 DepWaitTaskArgs); 5203 // Call proxy_task_entry(gtid, new_task); 5204 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5205 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5206 Action.Enter(CGF); 5207 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5208 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5209 OutlinedFnArgs); 5210 }; 5211 5212 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5213 // kmp_task_t *new_task); 5214 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5215 // kmp_task_t *new_task); 5216 RegionCodeGenTy RCG(CodeGen); 5217 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 5218 M, OMPRTL___kmpc_omp_task_begin_if0), 5219 TaskArgs, 5220 OMPBuilder.getOrCreateRuntimeFunction( 5221 M, OMPRTL___kmpc_omp_task_complete_if0), 5222 TaskArgs); 5223 RCG.setAction(Action); 5224 RCG(CGF); 5225 }; 5226 5227 if (IfCond) { 5228 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5229 } else { 5230 RegionCodeGenTy ThenRCG(ThenCodeGen); 5231 ThenRCG(CGF); 5232 } 5233 } 5234 5235 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5236 const OMPLoopDirective &D, 5237 llvm::Function *TaskFunction, 5238 QualType SharedsTy, Address Shareds, 5239 const Expr *IfCond, 5240 const OMPTaskDataTy &Data) { 5241 if (!CGF.HaveInsertPoint()) 5242 return; 5243 TaskResultTy Result = 5244 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5245 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5246 // libcall. 5247 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5248 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5249 // sched, kmp_uint64 grainsize, void *task_dup); 5250 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5251 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5252 llvm::Value *IfVal; 5253 if (IfCond) { 5254 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5255 /*isSigned=*/true); 5256 } else { 5257 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5258 } 5259 5260 LValue LBLVal = CGF.EmitLValueForField( 5261 Result.TDBase, 5262 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5263 const auto *LBVar = 5264 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5265 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5266 LBLVal.getQuals(), 5267 /*IsInitializer=*/true); 5268 LValue UBLVal = CGF.EmitLValueForField( 5269 Result.TDBase, 5270 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5271 const auto *UBVar = 5272 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5273 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5274 UBLVal.getQuals(), 5275 /*IsInitializer=*/true); 5276 LValue StLVal = CGF.EmitLValueForField( 5277 Result.TDBase, 5278 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5279 const auto *StVar = 5280 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5281 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5282 StLVal.getQuals(), 5283 /*IsInitializer=*/true); 5284 // Store reductions address. 5285 LValue RedLVal = CGF.EmitLValueForField( 5286 Result.TDBase, 5287 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5288 if (Data.Reductions) { 5289 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5290 } else { 5291 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5292 CGF.getContext().VoidPtrTy); 5293 } 5294 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5295 llvm::Value *TaskArgs[] = { 5296 UpLoc, 5297 ThreadID, 5298 Result.NewTask, 5299 IfVal, 5300 LBLVal.getPointer(CGF), 5301 UBLVal.getPointer(CGF), 5302 CGF.EmitLoadOfScalar(StLVal, Loc), 5303 llvm::ConstantInt::getSigned( 5304 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5305 llvm::ConstantInt::getSigned( 5306 CGF.IntTy, Data.Schedule.getPointer() 5307 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5308 : NoSchedule), 5309 Data.Schedule.getPointer() 5310 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5311 /*isSigned=*/false) 5312 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5313 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5314 Result.TaskDupFn, CGF.VoidPtrTy) 5315 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5316 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5317 CGM.getModule(), OMPRTL___kmpc_taskloop), 5318 TaskArgs); 5319 } 5320 5321 /// Emit reduction operation for each element of array (required for 5322 /// array sections) LHS op = RHS. 5323 /// \param Type Type of array. 5324 /// \param LHSVar Variable on the left side of the reduction operation 5325 /// (references element of array in original variable). 5326 /// \param RHSVar Variable on the right side of the reduction operation 5327 /// (references element of array in original variable). 5328 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5329 /// RHSVar. 5330 static void EmitOMPAggregateReduction( 5331 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5332 const VarDecl *RHSVar, 5333 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5334 const Expr *, const Expr *)> &RedOpGen, 5335 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5336 const Expr *UpExpr = nullptr) { 5337 // Perform element-by-element initialization. 5338 QualType ElementTy; 5339 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5340 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5341 5342 // Drill down to the base element type on both arrays. 5343 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5344 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5345 5346 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5347 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5348 // Cast from pointer to array type to pointer to single element. 5349 llvm::Value *LHSEnd = 5350 CGF.Builder.CreateGEP(LHSAddr.getElementType(), LHSBegin, NumElements); 5351 // The basic structure here is a while-do loop. 5352 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5353 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5354 llvm::Value *IsEmpty = 5355 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5356 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5357 5358 // Enter the loop body, making that address the current address. 5359 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5360 CGF.EmitBlock(BodyBB); 5361 5362 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5363 5364 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5365 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5366 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5367 Address RHSElementCurrent = 5368 Address(RHSElementPHI, 5369 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5370 5371 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5372 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5373 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5374 Address LHSElementCurrent = 5375 Address(LHSElementPHI, 5376 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5377 5378 // Emit copy. 5379 CodeGenFunction::OMPPrivateScope Scope(CGF); 5380 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5381 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5382 Scope.Privatize(); 5383 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5384 Scope.ForceCleanup(); 5385 5386 // Shift the address forward by one element. 5387 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5388 LHSAddr.getElementType(), LHSElementPHI, /*Idx0=*/1, 5389 "omp.arraycpy.dest.element"); 5390 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5391 RHSAddr.getElementType(), RHSElementPHI, /*Idx0=*/1, 5392 "omp.arraycpy.src.element"); 5393 // Check whether we've reached the end. 5394 llvm::Value *Done = 5395 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5396 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5397 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5398 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5399 5400 // Done. 5401 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5402 } 5403 5404 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5405 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5406 /// UDR combiner function. 5407 static void emitReductionCombiner(CodeGenFunction &CGF, 5408 const Expr *ReductionOp) { 5409 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5410 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5411 if (const auto *DRE = 5412 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5413 if (const auto *DRD = 5414 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5415 std::pair<llvm::Function *, llvm::Function *> Reduction = 5416 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5417 RValue Func = RValue::get(Reduction.first); 5418 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5419 CGF.EmitIgnoredExpr(ReductionOp); 5420 return; 5421 } 5422 CGF.EmitIgnoredExpr(ReductionOp); 5423 } 5424 5425 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5426 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5427 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5428 ArrayRef<const Expr *> ReductionOps) { 5429 ASTContext &C = CGM.getContext(); 5430 5431 // void reduction_func(void *LHSArg, void *RHSArg); 5432 FunctionArgList Args; 5433 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5434 ImplicitParamDecl::Other); 5435 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5436 ImplicitParamDecl::Other); 5437 Args.push_back(&LHSArg); 5438 Args.push_back(&RHSArg); 5439 const auto &CGFI = 5440 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5441 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5442 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5443 llvm::GlobalValue::InternalLinkage, Name, 5444 &CGM.getModule()); 5445 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5446 Fn->setDoesNotRecurse(); 5447 CodeGenFunction CGF(CGM); 5448 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5449 5450 // Dst = (void*[n])(LHSArg); 5451 // Src = (void*[n])(RHSArg); 5452 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5453 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5454 ArgsType), CGF.getPointerAlign()); 5455 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5456 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5457 ArgsType), CGF.getPointerAlign()); 5458 5459 // ... 5460 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5461 // ... 5462 CodeGenFunction::OMPPrivateScope Scope(CGF); 5463 auto IPriv = Privates.begin(); 5464 unsigned Idx = 0; 5465 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5466 const auto *RHSVar = 5467 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5468 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5469 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5470 }); 5471 const auto *LHSVar = 5472 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5473 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5474 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5475 }); 5476 QualType PrivTy = (*IPriv)->getType(); 5477 if (PrivTy->isVariablyModifiedType()) { 5478 // Get array size and emit VLA type. 5479 ++Idx; 5480 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5481 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5482 const VariableArrayType *VLA = 5483 CGF.getContext().getAsVariableArrayType(PrivTy); 5484 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5485 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5486 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5487 CGF.EmitVariablyModifiedType(PrivTy); 5488 } 5489 } 5490 Scope.Privatize(); 5491 IPriv = Privates.begin(); 5492 auto ILHS = LHSExprs.begin(); 5493 auto IRHS = RHSExprs.begin(); 5494 for (const Expr *E : ReductionOps) { 5495 if ((*IPriv)->getType()->isArrayType()) { 5496 // Emit reduction for array section. 5497 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5498 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5499 EmitOMPAggregateReduction( 5500 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5501 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5502 emitReductionCombiner(CGF, E); 5503 }); 5504 } else { 5505 // Emit reduction for array subscript or single variable. 5506 emitReductionCombiner(CGF, E); 5507 } 5508 ++IPriv; 5509 ++ILHS; 5510 ++IRHS; 5511 } 5512 Scope.ForceCleanup(); 5513 CGF.FinishFunction(); 5514 return Fn; 5515 } 5516 5517 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5518 const Expr *ReductionOp, 5519 const Expr *PrivateRef, 5520 const DeclRefExpr *LHS, 5521 const DeclRefExpr *RHS) { 5522 if (PrivateRef->getType()->isArrayType()) { 5523 // Emit reduction for array section. 5524 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5525 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5526 EmitOMPAggregateReduction( 5527 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5528 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5529 emitReductionCombiner(CGF, ReductionOp); 5530 }); 5531 } else { 5532 // Emit reduction for array subscript or single variable. 5533 emitReductionCombiner(CGF, ReductionOp); 5534 } 5535 } 5536 5537 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5538 ArrayRef<const Expr *> Privates, 5539 ArrayRef<const Expr *> LHSExprs, 5540 ArrayRef<const Expr *> RHSExprs, 5541 ArrayRef<const Expr *> ReductionOps, 5542 ReductionOptionsTy Options) { 5543 if (!CGF.HaveInsertPoint()) 5544 return; 5545 5546 bool WithNowait = Options.WithNowait; 5547 bool SimpleReduction = Options.SimpleReduction; 5548 5549 // Next code should be emitted for reduction: 5550 // 5551 // static kmp_critical_name lock = { 0 }; 5552 // 5553 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5554 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5555 // ... 5556 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5557 // *(Type<n>-1*)rhs[<n>-1]); 5558 // } 5559 // 5560 // ... 5561 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5562 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5563 // RedList, reduce_func, &<lock>)) { 5564 // case 1: 5565 // ... 5566 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5567 // ... 5568 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5569 // break; 5570 // case 2: 5571 // ... 5572 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5573 // ... 5574 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5575 // break; 5576 // default:; 5577 // } 5578 // 5579 // if SimpleReduction is true, only the next code is generated: 5580 // ... 5581 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5582 // ... 5583 5584 ASTContext &C = CGM.getContext(); 5585 5586 if (SimpleReduction) { 5587 CodeGenFunction::RunCleanupsScope Scope(CGF); 5588 auto IPriv = Privates.begin(); 5589 auto ILHS = LHSExprs.begin(); 5590 auto IRHS = RHSExprs.begin(); 5591 for (const Expr *E : ReductionOps) { 5592 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5593 cast<DeclRefExpr>(*IRHS)); 5594 ++IPriv; 5595 ++ILHS; 5596 ++IRHS; 5597 } 5598 return; 5599 } 5600 5601 // 1. Build a list of reduction variables. 5602 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5603 auto Size = RHSExprs.size(); 5604 for (const Expr *E : Privates) { 5605 if (E->getType()->isVariablyModifiedType()) 5606 // Reserve place for array size. 5607 ++Size; 5608 } 5609 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5610 QualType ReductionArrayTy = 5611 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5612 /*IndexTypeQuals=*/0); 5613 Address ReductionList = 5614 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5615 auto IPriv = Privates.begin(); 5616 unsigned Idx = 0; 5617 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5618 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5619 CGF.Builder.CreateStore( 5620 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5621 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5622 Elem); 5623 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5624 // Store array size. 5625 ++Idx; 5626 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5627 llvm::Value *Size = CGF.Builder.CreateIntCast( 5628 CGF.getVLASize( 5629 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5630 .NumElts, 5631 CGF.SizeTy, /*isSigned=*/false); 5632 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5633 Elem); 5634 } 5635 } 5636 5637 // 2. Emit reduce_func(). 5638 llvm::Function *ReductionFn = emitReductionFunction( 5639 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5640 LHSExprs, RHSExprs, ReductionOps); 5641 5642 // 3. Create static kmp_critical_name lock = { 0 }; 5643 std::string Name = getName({"reduction"}); 5644 llvm::Value *Lock = getCriticalRegionLock(Name); 5645 5646 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5647 // RedList, reduce_func, &<lock>); 5648 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5649 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5650 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5651 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5652 ReductionList.getPointer(), CGF.VoidPtrTy); 5653 llvm::Value *Args[] = { 5654 IdentTLoc, // ident_t *<loc> 5655 ThreadId, // i32 <gtid> 5656 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5657 ReductionArrayTySize, // size_type sizeof(RedList) 5658 RL, // void *RedList 5659 ReductionFn, // void (*) (void *, void *) <reduce_func> 5660 Lock // kmp_critical_name *&<lock> 5661 }; 5662 llvm::Value *Res = CGF.EmitRuntimeCall( 5663 OMPBuilder.getOrCreateRuntimeFunction( 5664 CGM.getModule(), 5665 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce), 5666 Args); 5667 5668 // 5. Build switch(res) 5669 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5670 llvm::SwitchInst *SwInst = 5671 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5672 5673 // 6. Build case 1: 5674 // ... 5675 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5676 // ... 5677 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5678 // break; 5679 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5680 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5681 CGF.EmitBlock(Case1BB); 5682 5683 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5684 llvm::Value *EndArgs[] = { 5685 IdentTLoc, // ident_t *<loc> 5686 ThreadId, // i32 <gtid> 5687 Lock // kmp_critical_name *&<lock> 5688 }; 5689 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5690 CodeGenFunction &CGF, PrePostActionTy &Action) { 5691 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5692 auto IPriv = Privates.begin(); 5693 auto ILHS = LHSExprs.begin(); 5694 auto IRHS = RHSExprs.begin(); 5695 for (const Expr *E : ReductionOps) { 5696 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5697 cast<DeclRefExpr>(*IRHS)); 5698 ++IPriv; 5699 ++ILHS; 5700 ++IRHS; 5701 } 5702 }; 5703 RegionCodeGenTy RCG(CodeGen); 5704 CommonActionTy Action( 5705 nullptr, llvm::None, 5706 OMPBuilder.getOrCreateRuntimeFunction( 5707 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait 5708 : OMPRTL___kmpc_end_reduce), 5709 EndArgs); 5710 RCG.setAction(Action); 5711 RCG(CGF); 5712 5713 CGF.EmitBranch(DefaultBB); 5714 5715 // 7. Build case 2: 5716 // ... 5717 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5718 // ... 5719 // break; 5720 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5721 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5722 CGF.EmitBlock(Case2BB); 5723 5724 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5725 CodeGenFunction &CGF, PrePostActionTy &Action) { 5726 auto ILHS = LHSExprs.begin(); 5727 auto IRHS = RHSExprs.begin(); 5728 auto IPriv = Privates.begin(); 5729 for (const Expr *E : ReductionOps) { 5730 const Expr *XExpr = nullptr; 5731 const Expr *EExpr = nullptr; 5732 const Expr *UpExpr = nullptr; 5733 BinaryOperatorKind BO = BO_Comma; 5734 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5735 if (BO->getOpcode() == BO_Assign) { 5736 XExpr = BO->getLHS(); 5737 UpExpr = BO->getRHS(); 5738 } 5739 } 5740 // Try to emit update expression as a simple atomic. 5741 const Expr *RHSExpr = UpExpr; 5742 if (RHSExpr) { 5743 // Analyze RHS part of the whole expression. 5744 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5745 RHSExpr->IgnoreParenImpCasts())) { 5746 // If this is a conditional operator, analyze its condition for 5747 // min/max reduction operator. 5748 RHSExpr = ACO->getCond(); 5749 } 5750 if (const auto *BORHS = 5751 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5752 EExpr = BORHS->getRHS(); 5753 BO = BORHS->getOpcode(); 5754 } 5755 } 5756 if (XExpr) { 5757 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5758 auto &&AtomicRedGen = [BO, VD, 5759 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5760 const Expr *EExpr, const Expr *UpExpr) { 5761 LValue X = CGF.EmitLValue(XExpr); 5762 RValue E; 5763 if (EExpr) 5764 E = CGF.EmitAnyExpr(EExpr); 5765 CGF.EmitOMPAtomicSimpleUpdateExpr( 5766 X, E, BO, /*IsXLHSInRHSPart=*/true, 5767 llvm::AtomicOrdering::Monotonic, Loc, 5768 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5769 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5770 PrivateScope.addPrivate( 5771 VD, [&CGF, VD, XRValue, Loc]() { 5772 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5773 CGF.emitOMPSimpleStore( 5774 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5775 VD->getType().getNonReferenceType(), Loc); 5776 return LHSTemp; 5777 }); 5778 (void)PrivateScope.Privatize(); 5779 return CGF.EmitAnyExpr(UpExpr); 5780 }); 5781 }; 5782 if ((*IPriv)->getType()->isArrayType()) { 5783 // Emit atomic reduction for array section. 5784 const auto *RHSVar = 5785 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5786 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5787 AtomicRedGen, XExpr, EExpr, UpExpr); 5788 } else { 5789 // Emit atomic reduction for array subscript or single variable. 5790 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5791 } 5792 } else { 5793 // Emit as a critical region. 5794 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5795 const Expr *, const Expr *) { 5796 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5797 std::string Name = RT.getName({"atomic_reduction"}); 5798 RT.emitCriticalRegion( 5799 CGF, Name, 5800 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5801 Action.Enter(CGF); 5802 emitReductionCombiner(CGF, E); 5803 }, 5804 Loc); 5805 }; 5806 if ((*IPriv)->getType()->isArrayType()) { 5807 const auto *LHSVar = 5808 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5809 const auto *RHSVar = 5810 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5811 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5812 CritRedGen); 5813 } else { 5814 CritRedGen(CGF, nullptr, nullptr, nullptr); 5815 } 5816 } 5817 ++ILHS; 5818 ++IRHS; 5819 ++IPriv; 5820 } 5821 }; 5822 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5823 if (!WithNowait) { 5824 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5825 llvm::Value *EndArgs[] = { 5826 IdentTLoc, // ident_t *<loc> 5827 ThreadId, // i32 <gtid> 5828 Lock // kmp_critical_name *&<lock> 5829 }; 5830 CommonActionTy Action(nullptr, llvm::None, 5831 OMPBuilder.getOrCreateRuntimeFunction( 5832 CGM.getModule(), OMPRTL___kmpc_end_reduce), 5833 EndArgs); 5834 AtomicRCG.setAction(Action); 5835 AtomicRCG(CGF); 5836 } else { 5837 AtomicRCG(CGF); 5838 } 5839 5840 CGF.EmitBranch(DefaultBB); 5841 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5842 } 5843 5844 /// Generates unique name for artificial threadprivate variables. 5845 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5846 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5847 const Expr *Ref) { 5848 SmallString<256> Buffer; 5849 llvm::raw_svector_ostream Out(Buffer); 5850 const clang::DeclRefExpr *DE; 5851 const VarDecl *D = ::getBaseDecl(Ref, DE); 5852 if (!D) 5853 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5854 D = D->getCanonicalDecl(); 5855 std::string Name = CGM.getOpenMPRuntime().getName( 5856 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5857 Out << Prefix << Name << "_" 5858 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5859 return std::string(Out.str()); 5860 } 5861 5862 /// Emits reduction initializer function: 5863 /// \code 5864 /// void @.red_init(void* %arg, void* %orig) { 5865 /// %0 = bitcast void* %arg to <type>* 5866 /// store <type> <init>, <type>* %0 5867 /// ret void 5868 /// } 5869 /// \endcode 5870 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 5871 SourceLocation Loc, 5872 ReductionCodeGen &RCG, unsigned N) { 5873 ASTContext &C = CGM.getContext(); 5874 QualType VoidPtrTy = C.VoidPtrTy; 5875 VoidPtrTy.addRestrict(); 5876 FunctionArgList Args; 5877 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5878 ImplicitParamDecl::Other); 5879 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5880 ImplicitParamDecl::Other); 5881 Args.emplace_back(&Param); 5882 Args.emplace_back(&ParamOrig); 5883 const auto &FnInfo = 5884 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5885 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5886 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 5887 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5888 Name, &CGM.getModule()); 5889 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5890 Fn->setDoesNotRecurse(); 5891 CodeGenFunction CGF(CGM); 5892 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5893 Address PrivateAddr = CGF.EmitLoadOfPointer( 5894 CGF.GetAddrOfLocalVar(&Param), 5895 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5896 llvm::Value *Size = nullptr; 5897 // If the size of the reduction item is non-constant, load it from global 5898 // threadprivate variable. 5899 if (RCG.getSizes(N).second) { 5900 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5901 CGF, CGM.getContext().getSizeType(), 5902 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5903 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5904 CGM.getContext().getSizeType(), Loc); 5905 } 5906 RCG.emitAggregateType(CGF, N, Size); 5907 LValue OrigLVal; 5908 // If initializer uses initializer from declare reduction construct, emit a 5909 // pointer to the address of the original reduction item (reuired by reduction 5910 // initializer) 5911 if (RCG.usesReductionInitializer(N)) { 5912 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig); 5913 SharedAddr = CGF.EmitLoadOfPointer( 5914 SharedAddr, 5915 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 5916 OrigLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 5917 } else { 5918 OrigLVal = CGF.MakeNaturalAlignAddrLValue( 5919 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 5920 CGM.getContext().VoidPtrTy); 5921 } 5922 // Emit the initializer: 5923 // %0 = bitcast void* %arg to <type>* 5924 // store <type> <init>, <type>* %0 5925 RCG.emitInitialization(CGF, N, PrivateAddr, OrigLVal, 5926 [](CodeGenFunction &) { return false; }); 5927 CGF.FinishFunction(); 5928 return Fn; 5929 } 5930 5931 /// Emits reduction combiner function: 5932 /// \code 5933 /// void @.red_comb(void* %arg0, void* %arg1) { 5934 /// %lhs = bitcast void* %arg0 to <type>* 5935 /// %rhs = bitcast void* %arg1 to <type>* 5936 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 5937 /// store <type> %2, <type>* %lhs 5938 /// ret void 5939 /// } 5940 /// \endcode 5941 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 5942 SourceLocation Loc, 5943 ReductionCodeGen &RCG, unsigned N, 5944 const Expr *ReductionOp, 5945 const Expr *LHS, const Expr *RHS, 5946 const Expr *PrivateRef) { 5947 ASTContext &C = CGM.getContext(); 5948 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 5949 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 5950 FunctionArgList Args; 5951 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 5952 C.VoidPtrTy, ImplicitParamDecl::Other); 5953 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5954 ImplicitParamDecl::Other); 5955 Args.emplace_back(&ParamInOut); 5956 Args.emplace_back(&ParamIn); 5957 const auto &FnInfo = 5958 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5959 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5960 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 5961 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5962 Name, &CGM.getModule()); 5963 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5964 Fn->setDoesNotRecurse(); 5965 CodeGenFunction CGF(CGM); 5966 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5967 llvm::Value *Size = nullptr; 5968 // If the size of the reduction item is non-constant, load it from global 5969 // threadprivate variable. 5970 if (RCG.getSizes(N).second) { 5971 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5972 CGF, CGM.getContext().getSizeType(), 5973 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5974 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5975 CGM.getContext().getSizeType(), Loc); 5976 } 5977 RCG.emitAggregateType(CGF, N, Size); 5978 // Remap lhs and rhs variables to the addresses of the function arguments. 5979 // %lhs = bitcast void* %arg0 to <type>* 5980 // %rhs = bitcast void* %arg1 to <type>* 5981 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5982 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 5983 // Pull out the pointer to the variable. 5984 Address PtrAddr = CGF.EmitLoadOfPointer( 5985 CGF.GetAddrOfLocalVar(&ParamInOut), 5986 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5987 return CGF.Builder.CreateElementBitCast( 5988 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 5989 }); 5990 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 5991 // Pull out the pointer to the variable. 5992 Address PtrAddr = CGF.EmitLoadOfPointer( 5993 CGF.GetAddrOfLocalVar(&ParamIn), 5994 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5995 return CGF.Builder.CreateElementBitCast( 5996 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 5997 }); 5998 PrivateScope.Privatize(); 5999 // Emit the combiner body: 6000 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6001 // store <type> %2, <type>* %lhs 6002 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6003 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6004 cast<DeclRefExpr>(RHS)); 6005 CGF.FinishFunction(); 6006 return Fn; 6007 } 6008 6009 /// Emits reduction finalizer function: 6010 /// \code 6011 /// void @.red_fini(void* %arg) { 6012 /// %0 = bitcast void* %arg to <type>* 6013 /// <destroy>(<type>* %0) 6014 /// ret void 6015 /// } 6016 /// \endcode 6017 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6018 SourceLocation Loc, 6019 ReductionCodeGen &RCG, unsigned N) { 6020 if (!RCG.needCleanups(N)) 6021 return nullptr; 6022 ASTContext &C = CGM.getContext(); 6023 FunctionArgList Args; 6024 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6025 ImplicitParamDecl::Other); 6026 Args.emplace_back(&Param); 6027 const auto &FnInfo = 6028 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6029 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6030 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6031 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6032 Name, &CGM.getModule()); 6033 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6034 Fn->setDoesNotRecurse(); 6035 CodeGenFunction CGF(CGM); 6036 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6037 Address PrivateAddr = CGF.EmitLoadOfPointer( 6038 CGF.GetAddrOfLocalVar(&Param), 6039 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6040 llvm::Value *Size = nullptr; 6041 // If the size of the reduction item is non-constant, load it from global 6042 // threadprivate variable. 6043 if (RCG.getSizes(N).second) { 6044 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6045 CGF, CGM.getContext().getSizeType(), 6046 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6047 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6048 CGM.getContext().getSizeType(), Loc); 6049 } 6050 RCG.emitAggregateType(CGF, N, Size); 6051 // Emit the finalizer body: 6052 // <destroy>(<type>* %0) 6053 RCG.emitCleanups(CGF, N, PrivateAddr); 6054 CGF.FinishFunction(Loc); 6055 return Fn; 6056 } 6057 6058 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6059 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6060 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6061 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6062 return nullptr; 6063 6064 // Build typedef struct: 6065 // kmp_taskred_input { 6066 // void *reduce_shar; // shared reduction item 6067 // void *reduce_orig; // original reduction item used for initialization 6068 // size_t reduce_size; // size of data item 6069 // void *reduce_init; // data initialization routine 6070 // void *reduce_fini; // data finalization routine 6071 // void *reduce_comb; // data combiner routine 6072 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6073 // } kmp_taskred_input_t; 6074 ASTContext &C = CGM.getContext(); 6075 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t"); 6076 RD->startDefinition(); 6077 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6078 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6079 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6080 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6081 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6082 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6083 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6084 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6085 RD->completeDefinition(); 6086 QualType RDType = C.getRecordType(RD); 6087 unsigned Size = Data.ReductionVars.size(); 6088 llvm::APInt ArraySize(/*numBits=*/64, Size); 6089 QualType ArrayRDType = C.getConstantArrayType( 6090 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6091 // kmp_task_red_input_t .rd_input.[Size]; 6092 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6093 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, 6094 Data.ReductionCopies, Data.ReductionOps); 6095 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6096 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6097 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6098 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6099 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6100 TaskRedInput.getPointer(), Idxs, 6101 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6102 ".rd_input.gep."); 6103 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6104 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6105 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6106 RCG.emitSharedOrigLValue(CGF, Cnt); 6107 llvm::Value *CastedShared = 6108 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6109 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6110 // ElemLVal.reduce_orig = &Origs[Cnt]; 6111 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD); 6112 llvm::Value *CastedOrig = 6113 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF)); 6114 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal); 6115 RCG.emitAggregateType(CGF, Cnt); 6116 llvm::Value *SizeValInChars; 6117 llvm::Value *SizeVal; 6118 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6119 // We use delayed creation/initialization for VLAs and array sections. It is 6120 // required because runtime does not provide the way to pass the sizes of 6121 // VLAs/array sections to initializer/combiner/finalizer functions. Instead 6122 // threadprivate global variables are used to store these values and use 6123 // them in the functions. 6124 bool DelayedCreation = !!SizeVal; 6125 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6126 /*isSigned=*/false); 6127 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6128 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6129 // ElemLVal.reduce_init = init; 6130 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6131 llvm::Value *InitAddr = 6132 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6133 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6134 // ElemLVal.reduce_fini = fini; 6135 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6136 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6137 llvm::Value *FiniAddr = Fini 6138 ? CGF.EmitCastToVoidPtr(Fini) 6139 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6140 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6141 // ElemLVal.reduce_comb = comb; 6142 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6143 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6144 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6145 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6146 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6147 // ElemLVal.flags = 0; 6148 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6149 if (DelayedCreation) { 6150 CGF.EmitStoreOfScalar( 6151 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6152 FlagsLVal); 6153 } else 6154 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6155 FlagsLVal.getType()); 6156 } 6157 if (Data.IsReductionWithTaskMod) { 6158 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6159 // is_ws, int num, void *data); 6160 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6161 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6162 CGM.IntTy, /*isSigned=*/true); 6163 llvm::Value *Args[] = { 6164 IdentTLoc, GTid, 6165 llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0, 6166 /*isSigned=*/true), 6167 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6168 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6169 TaskRedInput.getPointer(), CGM.VoidPtrTy)}; 6170 return CGF.EmitRuntimeCall( 6171 OMPBuilder.getOrCreateRuntimeFunction( 6172 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init), 6173 Args); 6174 } 6175 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data); 6176 llvm::Value *Args[] = { 6177 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6178 /*isSigned=*/true), 6179 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6180 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6181 CGM.VoidPtrTy)}; 6182 return CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6183 CGM.getModule(), OMPRTL___kmpc_taskred_init), 6184 Args); 6185 } 6186 6187 void CGOpenMPRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 6188 SourceLocation Loc, 6189 bool IsWorksharingReduction) { 6190 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6191 // is_ws, int num, void *data); 6192 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6193 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6194 CGM.IntTy, /*isSigned=*/true); 6195 llvm::Value *Args[] = {IdentTLoc, GTid, 6196 llvm::ConstantInt::get(CGM.IntTy, 6197 IsWorksharingReduction ? 1 : 0, 6198 /*isSigned=*/true)}; 6199 (void)CGF.EmitRuntimeCall( 6200 OMPBuilder.getOrCreateRuntimeFunction( 6201 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini), 6202 Args); 6203 } 6204 6205 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6206 SourceLocation Loc, 6207 ReductionCodeGen &RCG, 6208 unsigned N) { 6209 auto Sizes = RCG.getSizes(N); 6210 // Emit threadprivate global variable if the type is non-constant 6211 // (Sizes.second = nullptr). 6212 if (Sizes.second) { 6213 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6214 /*isSigned=*/false); 6215 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6216 CGF, CGM.getContext().getSizeType(), 6217 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6218 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6219 } 6220 } 6221 6222 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6223 SourceLocation Loc, 6224 llvm::Value *ReductionsPtr, 6225 LValue SharedLVal) { 6226 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6227 // *d); 6228 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6229 CGM.IntTy, 6230 /*isSigned=*/true), 6231 ReductionsPtr, 6232 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6233 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6234 return Address( 6235 CGF.EmitRuntimeCall( 6236 OMPBuilder.getOrCreateRuntimeFunction( 6237 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data), 6238 Args), 6239 SharedLVal.getAlignment()); 6240 } 6241 6242 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6243 SourceLocation Loc) { 6244 if (!CGF.HaveInsertPoint()) 6245 return; 6246 6247 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 6248 OMPBuilder.createTaskwait(CGF.Builder); 6249 } else { 6250 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6251 // global_tid); 6252 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6253 // Ignore return result until untied tasks are supported. 6254 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6255 CGM.getModule(), OMPRTL___kmpc_omp_taskwait), 6256 Args); 6257 } 6258 6259 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6260 Region->emitUntiedSwitch(CGF); 6261 } 6262 6263 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6264 OpenMPDirectiveKind InnerKind, 6265 const RegionCodeGenTy &CodeGen, 6266 bool HasCancel) { 6267 if (!CGF.HaveInsertPoint()) 6268 return; 6269 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel, 6270 InnerKind != OMPD_critical && 6271 InnerKind != OMPD_master && 6272 InnerKind != OMPD_masked); 6273 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6274 } 6275 6276 namespace { 6277 enum RTCancelKind { 6278 CancelNoreq = 0, 6279 CancelParallel = 1, 6280 CancelLoop = 2, 6281 CancelSections = 3, 6282 CancelTaskgroup = 4 6283 }; 6284 } // anonymous namespace 6285 6286 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6287 RTCancelKind CancelKind = CancelNoreq; 6288 if (CancelRegion == OMPD_parallel) 6289 CancelKind = CancelParallel; 6290 else if (CancelRegion == OMPD_for) 6291 CancelKind = CancelLoop; 6292 else if (CancelRegion == OMPD_sections) 6293 CancelKind = CancelSections; 6294 else { 6295 assert(CancelRegion == OMPD_taskgroup); 6296 CancelKind = CancelTaskgroup; 6297 } 6298 return CancelKind; 6299 } 6300 6301 void CGOpenMPRuntime::emitCancellationPointCall( 6302 CodeGenFunction &CGF, SourceLocation Loc, 6303 OpenMPDirectiveKind CancelRegion) { 6304 if (!CGF.HaveInsertPoint()) 6305 return; 6306 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6307 // global_tid, kmp_int32 cncl_kind); 6308 if (auto *OMPRegionInfo = 6309 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6310 // For 'cancellation point taskgroup', the task region info may not have a 6311 // cancel. This may instead happen in another adjacent task. 6312 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6313 llvm::Value *Args[] = { 6314 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6315 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6316 // Ignore return result until untied tasks are supported. 6317 llvm::Value *Result = CGF.EmitRuntimeCall( 6318 OMPBuilder.getOrCreateRuntimeFunction( 6319 CGM.getModule(), OMPRTL___kmpc_cancellationpoint), 6320 Args); 6321 // if (__kmpc_cancellationpoint()) { 6322 // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only 6323 // exit from construct; 6324 // } 6325 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6326 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6327 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6328 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6329 CGF.EmitBlock(ExitBB); 6330 if (CancelRegion == OMPD_parallel) 6331 emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 6332 // exit from construct; 6333 CodeGenFunction::JumpDest CancelDest = 6334 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6335 CGF.EmitBranchThroughCleanup(CancelDest); 6336 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6337 } 6338 } 6339 } 6340 6341 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6342 const Expr *IfCond, 6343 OpenMPDirectiveKind CancelRegion) { 6344 if (!CGF.HaveInsertPoint()) 6345 return; 6346 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6347 // kmp_int32 cncl_kind); 6348 auto &M = CGM.getModule(); 6349 if (auto *OMPRegionInfo = 6350 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6351 auto &&ThenGen = [this, &M, Loc, CancelRegion, 6352 OMPRegionInfo](CodeGenFunction &CGF, PrePostActionTy &) { 6353 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6354 llvm::Value *Args[] = { 6355 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6356 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6357 // Ignore return result until untied tasks are supported. 6358 llvm::Value *Result = CGF.EmitRuntimeCall( 6359 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args); 6360 // if (__kmpc_cancel()) { 6361 // call i32 @__kmpc_cancel_barrier( // for parallel cancellation only 6362 // exit from construct; 6363 // } 6364 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6365 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6366 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6367 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6368 CGF.EmitBlock(ExitBB); 6369 if (CancelRegion == OMPD_parallel) 6370 RT.emitBarrierCall(CGF, Loc, OMPD_unknown, /*EmitChecks=*/false); 6371 // exit from construct; 6372 CodeGenFunction::JumpDest CancelDest = 6373 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6374 CGF.EmitBranchThroughCleanup(CancelDest); 6375 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6376 }; 6377 if (IfCond) { 6378 emitIfClause(CGF, IfCond, ThenGen, 6379 [](CodeGenFunction &, PrePostActionTy &) {}); 6380 } else { 6381 RegionCodeGenTy ThenRCG(ThenGen); 6382 ThenRCG(CGF); 6383 } 6384 } 6385 } 6386 6387 namespace { 6388 /// Cleanup action for uses_allocators support. 6389 class OMPUsesAllocatorsActionTy final : public PrePostActionTy { 6390 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators; 6391 6392 public: 6393 OMPUsesAllocatorsActionTy( 6394 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators) 6395 : Allocators(Allocators) {} 6396 void Enter(CodeGenFunction &CGF) override { 6397 if (!CGF.HaveInsertPoint()) 6398 return; 6399 for (const auto &AllocatorData : Allocators) { 6400 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsInit( 6401 CGF, AllocatorData.first, AllocatorData.second); 6402 } 6403 } 6404 void Exit(CodeGenFunction &CGF) override { 6405 if (!CGF.HaveInsertPoint()) 6406 return; 6407 for (const auto &AllocatorData : Allocators) { 6408 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsFini(CGF, 6409 AllocatorData.first); 6410 } 6411 } 6412 }; 6413 } // namespace 6414 6415 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6416 const OMPExecutableDirective &D, StringRef ParentName, 6417 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6418 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6419 assert(!ParentName.empty() && "Invalid target region parent name!"); 6420 HasEmittedTargetRegion = true; 6421 SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators; 6422 for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) { 6423 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 6424 const OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 6425 if (!D.AllocatorTraits) 6426 continue; 6427 Allocators.emplace_back(D.Allocator, D.AllocatorTraits); 6428 } 6429 } 6430 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators); 6431 CodeGen.setAction(UsesAllocatorAction); 6432 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6433 IsOffloadEntry, CodeGen); 6434 } 6435 6436 void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, 6437 const Expr *Allocator, 6438 const Expr *AllocatorTraits) { 6439 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6440 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6441 // Use default memspace handle. 6442 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 6443 llvm::Value *NumTraits = llvm::ConstantInt::get( 6444 CGF.IntTy, cast<ConstantArrayType>( 6445 AllocatorTraits->getType()->getAsArrayTypeUnsafe()) 6446 ->getSize() 6447 .getLimitedValue()); 6448 LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits); 6449 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6450 AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy); 6451 AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, 6452 AllocatorTraitsLVal.getBaseInfo(), 6453 AllocatorTraitsLVal.getTBAAInfo()); 6454 llvm::Value *Traits = 6455 CGF.EmitLoadOfScalar(AllocatorTraitsLVal, AllocatorTraits->getExprLoc()); 6456 6457 llvm::Value *AllocatorVal = 6458 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6459 CGM.getModule(), OMPRTL___kmpc_init_allocator), 6460 {ThreadId, MemSpaceHandle, NumTraits, Traits}); 6461 // Store to allocator. 6462 CGF.EmitVarDecl(*cast<VarDecl>( 6463 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl())); 6464 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6465 AllocatorVal = 6466 CGF.EmitScalarConversion(AllocatorVal, CGF.getContext().VoidPtrTy, 6467 Allocator->getType(), Allocator->getExprLoc()); 6468 CGF.EmitStoreOfScalar(AllocatorVal, AllocatorLVal); 6469 } 6470 6471 void CGOpenMPRuntime::emitUsesAllocatorsFini(CodeGenFunction &CGF, 6472 const Expr *Allocator) { 6473 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6474 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6475 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6476 llvm::Value *AllocatorVal = 6477 CGF.EmitLoadOfScalar(AllocatorLVal, Allocator->getExprLoc()); 6478 AllocatorVal = CGF.EmitScalarConversion(AllocatorVal, Allocator->getType(), 6479 CGF.getContext().VoidPtrTy, 6480 Allocator->getExprLoc()); 6481 (void)CGF.EmitRuntimeCall( 6482 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 6483 OMPRTL___kmpc_destroy_allocator), 6484 {ThreadId, AllocatorVal}); 6485 } 6486 6487 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6488 const OMPExecutableDirective &D, StringRef ParentName, 6489 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6490 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6491 // Create a unique name for the entry function using the source location 6492 // information of the current target region. The name will be something like: 6493 // 6494 // __omp_offloading_DD_FFFF_PP_lBB 6495 // 6496 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6497 // mangled name of the function that encloses the target region and BB is the 6498 // line number of the target region. 6499 6500 unsigned DeviceID; 6501 unsigned FileID; 6502 unsigned Line; 6503 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6504 Line); 6505 SmallString<64> EntryFnName; 6506 { 6507 llvm::raw_svector_ostream OS(EntryFnName); 6508 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6509 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6510 } 6511 6512 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6513 6514 CodeGenFunction CGF(CGM, true); 6515 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6516 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6517 6518 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6519 6520 // If this target outline function is not an offload entry, we don't need to 6521 // register it. 6522 if (!IsOffloadEntry) 6523 return; 6524 6525 // The target region ID is used by the runtime library to identify the current 6526 // target region, so it only has to be unique and not necessarily point to 6527 // anything. It could be the pointer to the outlined function that implements 6528 // the target region, but we aren't using that so that the compiler doesn't 6529 // need to keep that, and could therefore inline the host function if proven 6530 // worthwhile during optimization. In the other hand, if emitting code for the 6531 // device, the ID has to be the function address so that it can retrieved from 6532 // the offloading entry and launched by the runtime library. We also mark the 6533 // outlined function to have external linkage in case we are emitting code for 6534 // the device, because these functions will be entry points to the device. 6535 6536 if (CGM.getLangOpts().OpenMPIsDevice) { 6537 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6538 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6539 OutlinedFn->setDSOLocal(false); 6540 if (CGM.getTriple().isAMDGCN()) 6541 OutlinedFn->setCallingConv(llvm::CallingConv::AMDGPU_KERNEL); 6542 } else { 6543 std::string Name = getName({EntryFnName, "region_id"}); 6544 OutlinedFnID = new llvm::GlobalVariable( 6545 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6546 llvm::GlobalValue::WeakAnyLinkage, 6547 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6548 } 6549 6550 // Register the information for the entry associated with this target region. 6551 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6552 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6553 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6554 6555 // Add NumTeams and ThreadLimit attributes to the outlined GPU function 6556 int32_t DefaultValTeams = -1; 6557 getNumTeamsExprForTargetDirective(CGF, D, DefaultValTeams); 6558 if (DefaultValTeams > 0) { 6559 OutlinedFn->addFnAttr("omp_target_num_teams", 6560 std::to_string(DefaultValTeams)); 6561 } 6562 int32_t DefaultValThreads = -1; 6563 getNumThreadsExprForTargetDirective(CGF, D, DefaultValThreads); 6564 if (DefaultValThreads > 0) { 6565 OutlinedFn->addFnAttr("omp_target_thread_limit", 6566 std::to_string(DefaultValThreads)); 6567 } 6568 } 6569 6570 /// Checks if the expression is constant or does not have non-trivial function 6571 /// calls. 6572 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6573 // We can skip constant expressions. 6574 // We can skip expressions with trivial calls or simple expressions. 6575 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6576 !E->hasNonTrivialCall(Ctx)) && 6577 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6578 } 6579 6580 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6581 const Stmt *Body) { 6582 const Stmt *Child = Body->IgnoreContainers(); 6583 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6584 Child = nullptr; 6585 for (const Stmt *S : C->body()) { 6586 if (const auto *E = dyn_cast<Expr>(S)) { 6587 if (isTrivial(Ctx, E)) 6588 continue; 6589 } 6590 // Some of the statements can be ignored. 6591 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6592 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6593 continue; 6594 // Analyze declarations. 6595 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6596 if (llvm::all_of(DS->decls(), [](const Decl *D) { 6597 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6598 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6599 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6600 isa<UsingDirectiveDecl>(D) || 6601 isa<OMPDeclareReductionDecl>(D) || 6602 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6603 return true; 6604 const auto *VD = dyn_cast<VarDecl>(D); 6605 if (!VD) 6606 return false; 6607 return VD->hasGlobalStorage() || !VD->isUsed(); 6608 })) 6609 continue; 6610 } 6611 // Found multiple children - cannot get the one child only. 6612 if (Child) 6613 return nullptr; 6614 Child = S; 6615 } 6616 if (Child) 6617 Child = Child->IgnoreContainers(); 6618 } 6619 return Child; 6620 } 6621 6622 const Expr *CGOpenMPRuntime::getNumTeamsExprForTargetDirective( 6623 CodeGenFunction &CGF, const OMPExecutableDirective &D, 6624 int32_t &DefaultVal) { 6625 6626 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6627 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6628 "Expected target-based executable directive."); 6629 switch (DirectiveKind) { 6630 case OMPD_target: { 6631 const auto *CS = D.getInnermostCapturedStmt(); 6632 const auto *Body = 6633 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6634 const Stmt *ChildStmt = 6635 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6636 if (const auto *NestedDir = 6637 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6638 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6639 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6640 const Expr *NumTeams = 6641 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6642 if (NumTeams->isIntegerConstantExpr(CGF.getContext())) 6643 if (auto Constant = 6644 NumTeams->getIntegerConstantExpr(CGF.getContext())) 6645 DefaultVal = Constant->getExtValue(); 6646 return NumTeams; 6647 } 6648 DefaultVal = 0; 6649 return nullptr; 6650 } 6651 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6652 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) { 6653 DefaultVal = 1; 6654 return nullptr; 6655 } 6656 DefaultVal = 1; 6657 return nullptr; 6658 } 6659 // A value of -1 is used to check if we need to emit no teams region 6660 DefaultVal = -1; 6661 return nullptr; 6662 } 6663 case OMPD_target_teams: 6664 case OMPD_target_teams_distribute: 6665 case OMPD_target_teams_distribute_simd: 6666 case OMPD_target_teams_distribute_parallel_for: 6667 case OMPD_target_teams_distribute_parallel_for_simd: { 6668 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6669 const Expr *NumTeams = 6670 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6671 if (NumTeams->isIntegerConstantExpr(CGF.getContext())) 6672 if (auto Constant = NumTeams->getIntegerConstantExpr(CGF.getContext())) 6673 DefaultVal = Constant->getExtValue(); 6674 return NumTeams; 6675 } 6676 DefaultVal = 0; 6677 return nullptr; 6678 } 6679 case OMPD_target_parallel: 6680 case OMPD_target_parallel_for: 6681 case OMPD_target_parallel_for_simd: 6682 case OMPD_target_simd: 6683 DefaultVal = 1; 6684 return nullptr; 6685 case OMPD_parallel: 6686 case OMPD_for: 6687 case OMPD_parallel_for: 6688 case OMPD_parallel_master: 6689 case OMPD_parallel_sections: 6690 case OMPD_for_simd: 6691 case OMPD_parallel_for_simd: 6692 case OMPD_cancel: 6693 case OMPD_cancellation_point: 6694 case OMPD_ordered: 6695 case OMPD_threadprivate: 6696 case OMPD_allocate: 6697 case OMPD_task: 6698 case OMPD_simd: 6699 case OMPD_tile: 6700 case OMPD_unroll: 6701 case OMPD_sections: 6702 case OMPD_section: 6703 case OMPD_single: 6704 case OMPD_master: 6705 case OMPD_critical: 6706 case OMPD_taskyield: 6707 case OMPD_barrier: 6708 case OMPD_taskwait: 6709 case OMPD_taskgroup: 6710 case OMPD_atomic: 6711 case OMPD_flush: 6712 case OMPD_depobj: 6713 case OMPD_scan: 6714 case OMPD_teams: 6715 case OMPD_target_data: 6716 case OMPD_target_exit_data: 6717 case OMPD_target_enter_data: 6718 case OMPD_distribute: 6719 case OMPD_distribute_simd: 6720 case OMPD_distribute_parallel_for: 6721 case OMPD_distribute_parallel_for_simd: 6722 case OMPD_teams_distribute: 6723 case OMPD_teams_distribute_simd: 6724 case OMPD_teams_distribute_parallel_for: 6725 case OMPD_teams_distribute_parallel_for_simd: 6726 case OMPD_target_update: 6727 case OMPD_declare_simd: 6728 case OMPD_declare_variant: 6729 case OMPD_begin_declare_variant: 6730 case OMPD_end_declare_variant: 6731 case OMPD_declare_target: 6732 case OMPD_end_declare_target: 6733 case OMPD_declare_reduction: 6734 case OMPD_declare_mapper: 6735 case OMPD_taskloop: 6736 case OMPD_taskloop_simd: 6737 case OMPD_master_taskloop: 6738 case OMPD_master_taskloop_simd: 6739 case OMPD_parallel_master_taskloop: 6740 case OMPD_parallel_master_taskloop_simd: 6741 case OMPD_requires: 6742 case OMPD_unknown: 6743 break; 6744 default: 6745 break; 6746 } 6747 llvm_unreachable("Unexpected directive kind."); 6748 } 6749 6750 llvm::Value *CGOpenMPRuntime::emitNumTeamsForTargetDirective( 6751 CodeGenFunction &CGF, const OMPExecutableDirective &D) { 6752 assert(!CGF.getLangOpts().OpenMPIsDevice && 6753 "Clauses associated with the teams directive expected to be emitted " 6754 "only for the host!"); 6755 CGBuilderTy &Bld = CGF.Builder; 6756 int32_t DefaultNT = -1; 6757 const Expr *NumTeams = getNumTeamsExprForTargetDirective(CGF, D, DefaultNT); 6758 if (NumTeams != nullptr) { 6759 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6760 6761 switch (DirectiveKind) { 6762 case OMPD_target: { 6763 const auto *CS = D.getInnermostCapturedStmt(); 6764 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6765 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6766 llvm::Value *NumTeamsVal = CGF.EmitScalarExpr(NumTeams, 6767 /*IgnoreResultAssign*/ true); 6768 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6769 /*isSigned=*/true); 6770 } 6771 case OMPD_target_teams: 6772 case OMPD_target_teams_distribute: 6773 case OMPD_target_teams_distribute_simd: 6774 case OMPD_target_teams_distribute_parallel_for: 6775 case OMPD_target_teams_distribute_parallel_for_simd: { 6776 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6777 llvm::Value *NumTeamsVal = CGF.EmitScalarExpr(NumTeams, 6778 /*IgnoreResultAssign*/ true); 6779 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6780 /*isSigned=*/true); 6781 } 6782 default: 6783 break; 6784 } 6785 } else if (DefaultNT == -1) { 6786 return nullptr; 6787 } 6788 6789 return Bld.getInt32(DefaultNT); 6790 } 6791 6792 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6793 llvm::Value *DefaultThreadLimitVal) { 6794 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6795 CGF.getContext(), CS->getCapturedStmt()); 6796 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6797 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6798 llvm::Value *NumThreads = nullptr; 6799 llvm::Value *CondVal = nullptr; 6800 // Handle if clause. If if clause present, the number of threads is 6801 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6802 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6803 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6804 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6805 const OMPIfClause *IfClause = nullptr; 6806 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6807 if (C->getNameModifier() == OMPD_unknown || 6808 C->getNameModifier() == OMPD_parallel) { 6809 IfClause = C; 6810 break; 6811 } 6812 } 6813 if (IfClause) { 6814 const Expr *Cond = IfClause->getCondition(); 6815 bool Result; 6816 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6817 if (!Result) 6818 return CGF.Builder.getInt32(1); 6819 } else { 6820 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6821 if (const auto *PreInit = 6822 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6823 for (const auto *I : PreInit->decls()) { 6824 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6825 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6826 } else { 6827 CodeGenFunction::AutoVarEmission Emission = 6828 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6829 CGF.EmitAutoVarCleanups(Emission); 6830 } 6831 } 6832 } 6833 CondVal = CGF.EvaluateExprAsBool(Cond); 6834 } 6835 } 6836 } 6837 // Check the value of num_threads clause iff if clause was not specified 6838 // or is not evaluated to false. 6839 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6840 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6841 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6842 const auto *NumThreadsClause = 6843 Dir->getSingleClause<OMPNumThreadsClause>(); 6844 CodeGenFunction::LexicalScope Scope( 6845 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6846 if (const auto *PreInit = 6847 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6848 for (const auto *I : PreInit->decls()) { 6849 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6850 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6851 } else { 6852 CodeGenFunction::AutoVarEmission Emission = 6853 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6854 CGF.EmitAutoVarCleanups(Emission); 6855 } 6856 } 6857 } 6858 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6859 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6860 /*isSigned=*/false); 6861 if (DefaultThreadLimitVal) 6862 NumThreads = CGF.Builder.CreateSelect( 6863 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6864 DefaultThreadLimitVal, NumThreads); 6865 } else { 6866 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6867 : CGF.Builder.getInt32(0); 6868 } 6869 // Process condition of the if clause. 6870 if (CondVal) { 6871 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6872 CGF.Builder.getInt32(1)); 6873 } 6874 return NumThreads; 6875 } 6876 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6877 return CGF.Builder.getInt32(1); 6878 return DefaultThreadLimitVal; 6879 } 6880 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6881 : CGF.Builder.getInt32(0); 6882 } 6883 6884 const Expr *CGOpenMPRuntime::getNumThreadsExprForTargetDirective( 6885 CodeGenFunction &CGF, const OMPExecutableDirective &D, 6886 int32_t &DefaultVal) { 6887 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6888 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6889 "Expected target-based executable directive."); 6890 6891 switch (DirectiveKind) { 6892 case OMPD_target: 6893 // Teams have no clause thread_limit 6894 return nullptr; 6895 case OMPD_target_teams: 6896 case OMPD_target_teams_distribute: 6897 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6898 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6899 const Expr *ThreadLimit = ThreadLimitClause->getThreadLimit(); 6900 if (ThreadLimit->isIntegerConstantExpr(CGF.getContext())) 6901 if (auto Constant = 6902 ThreadLimit->getIntegerConstantExpr(CGF.getContext())) 6903 DefaultVal = Constant->getExtValue(); 6904 return ThreadLimit; 6905 } 6906 return nullptr; 6907 case OMPD_target_parallel: 6908 case OMPD_target_parallel_for: 6909 case OMPD_target_parallel_for_simd: 6910 case OMPD_target_teams_distribute_parallel_for: 6911 case OMPD_target_teams_distribute_parallel_for_simd: { 6912 Expr *ThreadLimit = nullptr; 6913 Expr *NumThreads = nullptr; 6914 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6915 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6916 ThreadLimit = ThreadLimitClause->getThreadLimit(); 6917 if (ThreadLimit->isIntegerConstantExpr(CGF.getContext())) 6918 if (auto Constant = 6919 ThreadLimit->getIntegerConstantExpr(CGF.getContext())) 6920 DefaultVal = Constant->getExtValue(); 6921 } 6922 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6923 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6924 NumThreads = NumThreadsClause->getNumThreads(); 6925 if (NumThreads->isIntegerConstantExpr(CGF.getContext())) { 6926 if (auto Constant = 6927 NumThreads->getIntegerConstantExpr(CGF.getContext())) { 6928 if (Constant->getExtValue() < DefaultVal) { 6929 DefaultVal = Constant->getExtValue(); 6930 ThreadLimit = NumThreads; 6931 } 6932 } 6933 } 6934 } 6935 return ThreadLimit; 6936 } 6937 case OMPD_target_teams_distribute_simd: 6938 case OMPD_target_simd: 6939 DefaultVal = 1; 6940 return nullptr; 6941 case OMPD_parallel: 6942 case OMPD_for: 6943 case OMPD_parallel_for: 6944 case OMPD_parallel_master: 6945 case OMPD_parallel_sections: 6946 case OMPD_for_simd: 6947 case OMPD_parallel_for_simd: 6948 case OMPD_cancel: 6949 case OMPD_cancellation_point: 6950 case OMPD_ordered: 6951 case OMPD_threadprivate: 6952 case OMPD_allocate: 6953 case OMPD_task: 6954 case OMPD_simd: 6955 case OMPD_tile: 6956 case OMPD_unroll: 6957 case OMPD_sections: 6958 case OMPD_section: 6959 case OMPD_single: 6960 case OMPD_master: 6961 case OMPD_critical: 6962 case OMPD_taskyield: 6963 case OMPD_barrier: 6964 case OMPD_taskwait: 6965 case OMPD_taskgroup: 6966 case OMPD_atomic: 6967 case OMPD_flush: 6968 case OMPD_depobj: 6969 case OMPD_scan: 6970 case OMPD_teams: 6971 case OMPD_target_data: 6972 case OMPD_target_exit_data: 6973 case OMPD_target_enter_data: 6974 case OMPD_distribute: 6975 case OMPD_distribute_simd: 6976 case OMPD_distribute_parallel_for: 6977 case OMPD_distribute_parallel_for_simd: 6978 case OMPD_teams_distribute: 6979 case OMPD_teams_distribute_simd: 6980 case OMPD_teams_distribute_parallel_for: 6981 case OMPD_teams_distribute_parallel_for_simd: 6982 case OMPD_target_update: 6983 case OMPD_declare_simd: 6984 case OMPD_declare_variant: 6985 case OMPD_begin_declare_variant: 6986 case OMPD_end_declare_variant: 6987 case OMPD_declare_target: 6988 case OMPD_end_declare_target: 6989 case OMPD_declare_reduction: 6990 case OMPD_declare_mapper: 6991 case OMPD_taskloop: 6992 case OMPD_taskloop_simd: 6993 case OMPD_master_taskloop: 6994 case OMPD_master_taskloop_simd: 6995 case OMPD_parallel_master_taskloop: 6996 case OMPD_parallel_master_taskloop_simd: 6997 case OMPD_requires: 6998 case OMPD_unknown: 6999 break; 7000 default: 7001 break; 7002 } 7003 llvm_unreachable("Unsupported directive kind."); 7004 } 7005 7006 llvm::Value *CGOpenMPRuntime::emitNumThreadsForTargetDirective( 7007 CodeGenFunction &CGF, const OMPExecutableDirective &D) { 7008 assert(!CGF.getLangOpts().OpenMPIsDevice && 7009 "Clauses associated with the teams directive expected to be emitted " 7010 "only for the host!"); 7011 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 7012 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 7013 "Expected target-based executable directive."); 7014 CGBuilderTy &Bld = CGF.Builder; 7015 llvm::Value *ThreadLimitVal = nullptr; 7016 llvm::Value *NumThreadsVal = nullptr; 7017 switch (DirectiveKind) { 7018 case OMPD_target: { 7019 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7020 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7021 return NumThreads; 7022 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7023 CGF.getContext(), CS->getCapturedStmt()); 7024 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7025 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 7026 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7027 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7028 const auto *ThreadLimitClause = 7029 Dir->getSingleClause<OMPThreadLimitClause>(); 7030 CodeGenFunction::LexicalScope Scope( 7031 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 7032 if (const auto *PreInit = 7033 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 7034 for (const auto *I : PreInit->decls()) { 7035 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7036 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7037 } else { 7038 CodeGenFunction::AutoVarEmission Emission = 7039 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7040 CGF.EmitAutoVarCleanups(Emission); 7041 } 7042 } 7043 } 7044 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7045 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7046 ThreadLimitVal = 7047 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7048 } 7049 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 7050 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 7051 CS = Dir->getInnermostCapturedStmt(); 7052 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7053 CGF.getContext(), CS->getCapturedStmt()); 7054 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 7055 } 7056 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 7057 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 7058 CS = Dir->getInnermostCapturedStmt(); 7059 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7060 return NumThreads; 7061 } 7062 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 7063 return Bld.getInt32(1); 7064 } 7065 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7066 } 7067 case OMPD_target_teams: { 7068 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7069 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7070 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7071 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7072 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7073 ThreadLimitVal = 7074 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7075 } 7076 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7077 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7078 return NumThreads; 7079 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7080 CGF.getContext(), CS->getCapturedStmt()); 7081 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7082 if (Dir->getDirectiveKind() == OMPD_distribute) { 7083 CS = Dir->getInnermostCapturedStmt(); 7084 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7085 return NumThreads; 7086 } 7087 } 7088 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7089 } 7090 case OMPD_target_teams_distribute: 7091 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7092 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7093 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7094 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7095 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7096 ThreadLimitVal = 7097 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7098 } 7099 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 7100 case OMPD_target_parallel: 7101 case OMPD_target_parallel_for: 7102 case OMPD_target_parallel_for_simd: 7103 case OMPD_target_teams_distribute_parallel_for: 7104 case OMPD_target_teams_distribute_parallel_for_simd: { 7105 llvm::Value *CondVal = nullptr; 7106 // Handle if clause. If if clause present, the number of threads is 7107 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 7108 if (D.hasClausesOfKind<OMPIfClause>()) { 7109 const OMPIfClause *IfClause = nullptr; 7110 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 7111 if (C->getNameModifier() == OMPD_unknown || 7112 C->getNameModifier() == OMPD_parallel) { 7113 IfClause = C; 7114 break; 7115 } 7116 } 7117 if (IfClause) { 7118 const Expr *Cond = IfClause->getCondition(); 7119 bool Result; 7120 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7121 if (!Result) 7122 return Bld.getInt32(1); 7123 } else { 7124 CodeGenFunction::RunCleanupsScope Scope(CGF); 7125 CondVal = CGF.EvaluateExprAsBool(Cond); 7126 } 7127 } 7128 } 7129 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7130 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7131 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7132 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7133 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7134 ThreadLimitVal = 7135 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7136 } 7137 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 7138 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 7139 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 7140 llvm::Value *NumThreads = CGF.EmitScalarExpr( 7141 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 7142 NumThreadsVal = 7143 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 7144 ThreadLimitVal = ThreadLimitVal 7145 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 7146 ThreadLimitVal), 7147 NumThreadsVal, ThreadLimitVal) 7148 : NumThreadsVal; 7149 } 7150 if (!ThreadLimitVal) 7151 ThreadLimitVal = Bld.getInt32(0); 7152 if (CondVal) 7153 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 7154 return ThreadLimitVal; 7155 } 7156 case OMPD_target_teams_distribute_simd: 7157 case OMPD_target_simd: 7158 return Bld.getInt32(1); 7159 case OMPD_parallel: 7160 case OMPD_for: 7161 case OMPD_parallel_for: 7162 case OMPD_parallel_master: 7163 case OMPD_parallel_sections: 7164 case OMPD_for_simd: 7165 case OMPD_parallel_for_simd: 7166 case OMPD_cancel: 7167 case OMPD_cancellation_point: 7168 case OMPD_ordered: 7169 case OMPD_threadprivate: 7170 case OMPD_allocate: 7171 case OMPD_task: 7172 case OMPD_simd: 7173 case OMPD_tile: 7174 case OMPD_unroll: 7175 case OMPD_sections: 7176 case OMPD_section: 7177 case OMPD_single: 7178 case OMPD_master: 7179 case OMPD_critical: 7180 case OMPD_taskyield: 7181 case OMPD_barrier: 7182 case OMPD_taskwait: 7183 case OMPD_taskgroup: 7184 case OMPD_atomic: 7185 case OMPD_flush: 7186 case OMPD_depobj: 7187 case OMPD_scan: 7188 case OMPD_teams: 7189 case OMPD_target_data: 7190 case OMPD_target_exit_data: 7191 case OMPD_target_enter_data: 7192 case OMPD_distribute: 7193 case OMPD_distribute_simd: 7194 case OMPD_distribute_parallel_for: 7195 case OMPD_distribute_parallel_for_simd: 7196 case OMPD_teams_distribute: 7197 case OMPD_teams_distribute_simd: 7198 case OMPD_teams_distribute_parallel_for: 7199 case OMPD_teams_distribute_parallel_for_simd: 7200 case OMPD_target_update: 7201 case OMPD_declare_simd: 7202 case OMPD_declare_variant: 7203 case OMPD_begin_declare_variant: 7204 case OMPD_end_declare_variant: 7205 case OMPD_declare_target: 7206 case OMPD_end_declare_target: 7207 case OMPD_declare_reduction: 7208 case OMPD_declare_mapper: 7209 case OMPD_taskloop: 7210 case OMPD_taskloop_simd: 7211 case OMPD_master_taskloop: 7212 case OMPD_master_taskloop_simd: 7213 case OMPD_parallel_master_taskloop: 7214 case OMPD_parallel_master_taskloop_simd: 7215 case OMPD_requires: 7216 case OMPD_unknown: 7217 break; 7218 default: 7219 break; 7220 } 7221 llvm_unreachable("Unsupported directive kind."); 7222 } 7223 7224 namespace { 7225 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7226 7227 // Utility to handle information from clauses associated with a given 7228 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7229 // It provides a convenient interface to obtain the information and generate 7230 // code for that information. 7231 class MappableExprsHandler { 7232 public: 7233 /// Values for bit flags used to specify the mapping type for 7234 /// offloading. 7235 enum OpenMPOffloadMappingFlags : uint64_t { 7236 /// No flags 7237 OMP_MAP_NONE = 0x0, 7238 /// Allocate memory on the device and move data from host to device. 7239 OMP_MAP_TO = 0x01, 7240 /// Allocate memory on the device and move data from device to host. 7241 OMP_MAP_FROM = 0x02, 7242 /// Always perform the requested mapping action on the element, even 7243 /// if it was already mapped before. 7244 OMP_MAP_ALWAYS = 0x04, 7245 /// Delete the element from the device environment, ignoring the 7246 /// current reference count associated with the element. 7247 OMP_MAP_DELETE = 0x08, 7248 /// The element being mapped is a pointer-pointee pair; both the 7249 /// pointer and the pointee should be mapped. 7250 OMP_MAP_PTR_AND_OBJ = 0x10, 7251 /// This flags signals that the base address of an entry should be 7252 /// passed to the target kernel as an argument. 7253 OMP_MAP_TARGET_PARAM = 0x20, 7254 /// Signal that the runtime library has to return the device pointer 7255 /// in the current position for the data being mapped. Used when we have the 7256 /// use_device_ptr or use_device_addr clause. 7257 OMP_MAP_RETURN_PARAM = 0x40, 7258 /// This flag signals that the reference being passed is a pointer to 7259 /// private data. 7260 OMP_MAP_PRIVATE = 0x80, 7261 /// Pass the element to the device by value. 7262 OMP_MAP_LITERAL = 0x100, 7263 /// Implicit map 7264 OMP_MAP_IMPLICIT = 0x200, 7265 /// Close is a hint to the runtime to allocate memory close to 7266 /// the target device. 7267 OMP_MAP_CLOSE = 0x400, 7268 /// 0x800 is reserved for compatibility with XLC. 7269 /// Produce a runtime error if the data is not already allocated. 7270 OMP_MAP_PRESENT = 0x1000, 7271 /// Signal that the runtime library should use args as an array of 7272 /// descriptor_dim pointers and use args_size as dims. Used when we have 7273 /// non-contiguous list items in target update directive 7274 OMP_MAP_NON_CONTIG = 0x100000000000, 7275 /// The 16 MSBs of the flags indicate whether the entry is member of some 7276 /// struct/class. 7277 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7278 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7279 }; 7280 7281 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7282 static unsigned getFlagMemberOffset() { 7283 unsigned Offset = 0; 7284 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7285 Remain = Remain >> 1) 7286 Offset++; 7287 return Offset; 7288 } 7289 7290 /// Class that holds debugging information for a data mapping to be passed to 7291 /// the runtime library. 7292 class MappingExprInfo { 7293 /// The variable declaration used for the data mapping. 7294 const ValueDecl *MapDecl = nullptr; 7295 /// The original expression used in the map clause, or null if there is 7296 /// none. 7297 const Expr *MapExpr = nullptr; 7298 7299 public: 7300 MappingExprInfo(const ValueDecl *MapDecl, const Expr *MapExpr = nullptr) 7301 : MapDecl(MapDecl), MapExpr(MapExpr) {} 7302 7303 const ValueDecl *getMapDecl() const { return MapDecl; } 7304 const Expr *getMapExpr() const { return MapExpr; } 7305 }; 7306 7307 /// Class that associates information with a base pointer to be passed to the 7308 /// runtime library. 7309 class BasePointerInfo { 7310 /// The base pointer. 7311 llvm::Value *Ptr = nullptr; 7312 /// The base declaration that refers to this device pointer, or null if 7313 /// there is none. 7314 const ValueDecl *DevPtrDecl = nullptr; 7315 7316 public: 7317 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7318 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7319 llvm::Value *operator*() const { return Ptr; } 7320 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7321 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7322 }; 7323 7324 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>; 7325 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7326 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7327 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7328 using MapMappersArrayTy = SmallVector<const ValueDecl *, 4>; 7329 using MapDimArrayTy = SmallVector<uint64_t, 4>; 7330 using MapNonContiguousArrayTy = SmallVector<MapValuesArrayTy, 4>; 7331 7332 /// This structure contains combined information generated for mappable 7333 /// clauses, including base pointers, pointers, sizes, map types, user-defined 7334 /// mappers, and non-contiguous information. 7335 struct MapCombinedInfoTy { 7336 struct StructNonContiguousInfo { 7337 bool IsNonContiguous = false; 7338 MapDimArrayTy Dims; 7339 MapNonContiguousArrayTy Offsets; 7340 MapNonContiguousArrayTy Counts; 7341 MapNonContiguousArrayTy Strides; 7342 }; 7343 MapExprsArrayTy Exprs; 7344 MapBaseValuesArrayTy BasePointers; 7345 MapValuesArrayTy Pointers; 7346 MapValuesArrayTy Sizes; 7347 MapFlagsArrayTy Types; 7348 MapMappersArrayTy Mappers; 7349 StructNonContiguousInfo NonContigInfo; 7350 7351 /// Append arrays in \a CurInfo. 7352 void append(MapCombinedInfoTy &CurInfo) { 7353 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end()); 7354 BasePointers.append(CurInfo.BasePointers.begin(), 7355 CurInfo.BasePointers.end()); 7356 Pointers.append(CurInfo.Pointers.begin(), CurInfo.Pointers.end()); 7357 Sizes.append(CurInfo.Sizes.begin(), CurInfo.Sizes.end()); 7358 Types.append(CurInfo.Types.begin(), CurInfo.Types.end()); 7359 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end()); 7360 NonContigInfo.Dims.append(CurInfo.NonContigInfo.Dims.begin(), 7361 CurInfo.NonContigInfo.Dims.end()); 7362 NonContigInfo.Offsets.append(CurInfo.NonContigInfo.Offsets.begin(), 7363 CurInfo.NonContigInfo.Offsets.end()); 7364 NonContigInfo.Counts.append(CurInfo.NonContigInfo.Counts.begin(), 7365 CurInfo.NonContigInfo.Counts.end()); 7366 NonContigInfo.Strides.append(CurInfo.NonContigInfo.Strides.begin(), 7367 CurInfo.NonContigInfo.Strides.end()); 7368 } 7369 }; 7370 7371 /// Map between a struct and the its lowest & highest elements which have been 7372 /// mapped. 7373 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7374 /// HE(FieldIndex, Pointer)} 7375 struct StructRangeInfoTy { 7376 MapCombinedInfoTy PreliminaryMapData; 7377 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7378 0, Address::invalid()}; 7379 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7380 0, Address::invalid()}; 7381 Address Base = Address::invalid(); 7382 Address LB = Address::invalid(); 7383 bool IsArraySection = false; 7384 bool HasCompleteRecord = false; 7385 }; 7386 7387 private: 7388 /// Kind that defines how a device pointer has to be returned. 7389 struct MapInfo { 7390 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7391 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7392 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7393 ArrayRef<OpenMPMotionModifierKind> MotionModifiers; 7394 bool ReturnDevicePointer = false; 7395 bool IsImplicit = false; 7396 const ValueDecl *Mapper = nullptr; 7397 const Expr *VarRef = nullptr; 7398 bool ForDeviceAddr = false; 7399 7400 MapInfo() = default; 7401 MapInfo( 7402 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7403 OpenMPMapClauseKind MapType, 7404 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7405 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7406 bool ReturnDevicePointer, bool IsImplicit, 7407 const ValueDecl *Mapper = nullptr, const Expr *VarRef = nullptr, 7408 bool ForDeviceAddr = false) 7409 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7410 MotionModifiers(MotionModifiers), 7411 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit), 7412 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {} 7413 }; 7414 7415 /// If use_device_ptr or use_device_addr is used on a decl which is a struct 7416 /// member and there is no map information about it, then emission of that 7417 /// entry is deferred until the whole struct has been processed. 7418 struct DeferredDevicePtrEntryTy { 7419 const Expr *IE = nullptr; 7420 const ValueDecl *VD = nullptr; 7421 bool ForDeviceAddr = false; 7422 7423 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD, 7424 bool ForDeviceAddr) 7425 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {} 7426 }; 7427 7428 /// The target directive from where the mappable clauses were extracted. It 7429 /// is either a executable directive or a user-defined mapper directive. 7430 llvm::PointerUnion<const OMPExecutableDirective *, 7431 const OMPDeclareMapperDecl *> 7432 CurDir; 7433 7434 /// Function the directive is being generated for. 7435 CodeGenFunction &CGF; 7436 7437 /// Set of all first private variables in the current directive. 7438 /// bool data is set to true if the variable is implicitly marked as 7439 /// firstprivate, false otherwise. 7440 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7441 7442 /// Map between device pointer declarations and their expression components. 7443 /// The key value for declarations in 'this' is null. 7444 llvm::DenseMap< 7445 const ValueDecl *, 7446 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7447 DevPointersMap; 7448 7449 llvm::Value *getExprTypeSize(const Expr *E) const { 7450 QualType ExprTy = E->getType().getCanonicalType(); 7451 7452 // Calculate the size for array shaping expression. 7453 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) { 7454 llvm::Value *Size = 7455 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType()); 7456 for (const Expr *SE : OAE->getDimensions()) { 7457 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 7458 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 7459 CGF.getContext().getSizeType(), 7460 SE->getExprLoc()); 7461 Size = CGF.Builder.CreateNUWMul(Size, Sz); 7462 } 7463 return Size; 7464 } 7465 7466 // Reference types are ignored for mapping purposes. 7467 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7468 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7469 7470 // Given that an array section is considered a built-in type, we need to 7471 // do the calculation based on the length of the section instead of relying 7472 // on CGF.getTypeSize(E->getType()). 7473 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7474 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7475 OAE->getBase()->IgnoreParenImpCasts()) 7476 .getCanonicalType(); 7477 7478 // If there is no length associated with the expression and lower bound is 7479 // not specified too, that means we are using the whole length of the 7480 // base. 7481 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7482 !OAE->getLowerBound()) 7483 return CGF.getTypeSize(BaseTy); 7484 7485 llvm::Value *ElemSize; 7486 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7487 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7488 } else { 7489 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7490 assert(ATy && "Expecting array type if not a pointer type."); 7491 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7492 } 7493 7494 // If we don't have a length at this point, that is because we have an 7495 // array section with a single element. 7496 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid()) 7497 return ElemSize; 7498 7499 if (const Expr *LenExpr = OAE->getLength()) { 7500 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7501 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7502 CGF.getContext().getSizeType(), 7503 LenExpr->getExprLoc()); 7504 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7505 } 7506 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7507 OAE->getLowerBound() && "expected array_section[lb:]."); 7508 // Size = sizetype - lb * elemtype; 7509 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7510 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7511 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7512 CGF.getContext().getSizeType(), 7513 OAE->getLowerBound()->getExprLoc()); 7514 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7515 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7516 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7517 LengthVal = CGF.Builder.CreateSelect( 7518 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7519 return LengthVal; 7520 } 7521 return CGF.getTypeSize(ExprTy); 7522 } 7523 7524 /// Return the corresponding bits for a given map clause modifier. Add 7525 /// a flag marking the map as a pointer if requested. Add a flag marking the 7526 /// map as the first one of a series of maps that relate to the same map 7527 /// expression. 7528 OpenMPOffloadMappingFlags getMapTypeBits( 7529 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7530 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit, 7531 bool AddPtrFlag, bool AddIsTargetParamFlag, bool IsNonContiguous) const { 7532 OpenMPOffloadMappingFlags Bits = 7533 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7534 switch (MapType) { 7535 case OMPC_MAP_alloc: 7536 case OMPC_MAP_release: 7537 // alloc and release is the default behavior in the runtime library, i.e. 7538 // if we don't pass any bits alloc/release that is what the runtime is 7539 // going to do. Therefore, we don't need to signal anything for these two 7540 // type modifiers. 7541 break; 7542 case OMPC_MAP_to: 7543 Bits |= OMP_MAP_TO; 7544 break; 7545 case OMPC_MAP_from: 7546 Bits |= OMP_MAP_FROM; 7547 break; 7548 case OMPC_MAP_tofrom: 7549 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7550 break; 7551 case OMPC_MAP_delete: 7552 Bits |= OMP_MAP_DELETE; 7553 break; 7554 case OMPC_MAP_unknown: 7555 llvm_unreachable("Unexpected map type!"); 7556 } 7557 if (AddPtrFlag) 7558 Bits |= OMP_MAP_PTR_AND_OBJ; 7559 if (AddIsTargetParamFlag) 7560 Bits |= OMP_MAP_TARGET_PARAM; 7561 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7562 != MapModifiers.end()) 7563 Bits |= OMP_MAP_ALWAYS; 7564 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7565 != MapModifiers.end()) 7566 Bits |= OMP_MAP_CLOSE; 7567 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_present) != 7568 MapModifiers.end() || 7569 llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present) != 7570 MotionModifiers.end()) 7571 Bits |= OMP_MAP_PRESENT; 7572 if (IsNonContiguous) 7573 Bits |= OMP_MAP_NON_CONTIG; 7574 return Bits; 7575 } 7576 7577 /// Return true if the provided expression is a final array section. A 7578 /// final array section, is one whose length can't be proved to be one. 7579 bool isFinalArraySectionExpression(const Expr *E) const { 7580 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7581 7582 // It is not an array section and therefore not a unity-size one. 7583 if (!OASE) 7584 return false; 7585 7586 // An array section with no colon always refer to a single element. 7587 if (OASE->getColonLocFirst().isInvalid()) 7588 return false; 7589 7590 const Expr *Length = OASE->getLength(); 7591 7592 // If we don't have a length we have to check if the array has size 1 7593 // for this dimension. Also, we should always expect a length if the 7594 // base type is pointer. 7595 if (!Length) { 7596 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7597 OASE->getBase()->IgnoreParenImpCasts()) 7598 .getCanonicalType(); 7599 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7600 return ATy->getSize().getSExtValue() != 1; 7601 // If we don't have a constant dimension length, we have to consider 7602 // the current section as having any size, so it is not necessarily 7603 // unitary. If it happen to be unity size, that's user fault. 7604 return true; 7605 } 7606 7607 // Check if the length evaluates to 1. 7608 Expr::EvalResult Result; 7609 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7610 return true; // Can have more that size 1. 7611 7612 llvm::APSInt ConstLength = Result.Val.getInt(); 7613 return ConstLength.getSExtValue() != 1; 7614 } 7615 7616 /// Generate the base pointers, section pointers, sizes, map type bits, and 7617 /// user-defined mappers (all included in \a CombinedInfo) for the provided 7618 /// map type, map or motion modifiers, and expression components. 7619 /// \a IsFirstComponent should be set to true if the provided set of 7620 /// components is the first associated with a capture. 7621 void generateInfoForComponentList( 7622 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7623 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7624 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7625 MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct, 7626 bool IsFirstComponentList, bool IsImplicit, 7627 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false, 7628 const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr, 7629 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7630 OverlappedElements = llvm::None) const { 7631 // The following summarizes what has to be generated for each map and the 7632 // types below. The generated information is expressed in this order: 7633 // base pointer, section pointer, size, flags 7634 // (to add to the ones that come from the map type and modifier). 7635 // 7636 // double d; 7637 // int i[100]; 7638 // float *p; 7639 // 7640 // struct S1 { 7641 // int i; 7642 // float f[50]; 7643 // } 7644 // struct S2 { 7645 // int i; 7646 // float f[50]; 7647 // S1 s; 7648 // double *p; 7649 // struct S2 *ps; 7650 // int &ref; 7651 // } 7652 // S2 s; 7653 // S2 *ps; 7654 // 7655 // map(d) 7656 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7657 // 7658 // map(i) 7659 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7660 // 7661 // map(i[1:23]) 7662 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7663 // 7664 // map(p) 7665 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7666 // 7667 // map(p[1:24]) 7668 // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ 7669 // in unified shared memory mode or for local pointers 7670 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7671 // 7672 // map(s) 7673 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7674 // 7675 // map(s.i) 7676 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7677 // 7678 // map(s.s.f) 7679 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7680 // 7681 // map(s.p) 7682 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7683 // 7684 // map(to: s.p[:22]) 7685 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7686 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7687 // &(s.p), &(s.p[0]), 22*sizeof(double), 7688 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7689 // (*) alloc space for struct members, only this is a target parameter 7690 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7691 // optimizes this entry out, same in the examples below) 7692 // (***) map the pointee (map: to) 7693 // 7694 // map(to: s.ref) 7695 // &s, &(s.ref), sizeof(int*), TARGET_PARAM (*) 7696 // &s, &(s.ref), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7697 // (*) alloc space for struct members, only this is a target parameter 7698 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7699 // optimizes this entry out, same in the examples below) 7700 // (***) map the pointee (map: to) 7701 // 7702 // map(s.ps) 7703 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7704 // 7705 // map(from: s.ps->s.i) 7706 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7707 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7708 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7709 // 7710 // map(to: s.ps->ps) 7711 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7712 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7713 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7714 // 7715 // map(s.ps->ps->ps) 7716 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7717 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7718 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7719 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7720 // 7721 // map(to: s.ps->ps->s.f[:22]) 7722 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7723 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7724 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7725 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7726 // 7727 // map(ps) 7728 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7729 // 7730 // map(ps->i) 7731 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7732 // 7733 // map(ps->s.f) 7734 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7735 // 7736 // map(from: ps->p) 7737 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7738 // 7739 // map(to: ps->p[:22]) 7740 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7741 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7742 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7743 // 7744 // map(ps->ps) 7745 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7746 // 7747 // map(from: ps->ps->s.i) 7748 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7749 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7750 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7751 // 7752 // map(from: ps->ps->ps) 7753 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7754 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7755 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7756 // 7757 // map(ps->ps->ps->ps) 7758 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7759 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7760 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7761 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7762 // 7763 // map(to: ps->ps->ps->s.f[:22]) 7764 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7765 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7766 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7767 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7768 // 7769 // map(to: s.f[:22]) map(from: s.p[:33]) 7770 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7771 // sizeof(double*) (**), TARGET_PARAM 7772 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7773 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7774 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7775 // (*) allocate contiguous space needed to fit all mapped members even if 7776 // we allocate space for members not mapped (in this example, 7777 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7778 // them as well because they fall between &s.f[0] and &s.p) 7779 // 7780 // map(from: s.f[:22]) map(to: ps->p[:33]) 7781 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7782 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7783 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7784 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7785 // (*) the struct this entry pertains to is the 2nd element in the list of 7786 // arguments, hence MEMBER_OF(2) 7787 // 7788 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7789 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7790 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7791 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7792 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7793 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7794 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7795 // (*) the struct this entry pertains to is the 4th element in the list 7796 // of arguments, hence MEMBER_OF(4) 7797 7798 // Track if the map information being generated is the first for a capture. 7799 bool IsCaptureFirstInfo = IsFirstComponentList; 7800 // When the variable is on a declare target link or in a to clause with 7801 // unified memory, a reference is needed to hold the host/device address 7802 // of the variable. 7803 bool RequiresReference = false; 7804 7805 // Scan the components from the base to the complete expression. 7806 auto CI = Components.rbegin(); 7807 auto CE = Components.rend(); 7808 auto I = CI; 7809 7810 // Track if the map information being generated is the first for a list of 7811 // components. 7812 bool IsExpressionFirstInfo = true; 7813 bool FirstPointerInComplexData = false; 7814 Address BP = Address::invalid(); 7815 const Expr *AssocExpr = I->getAssociatedExpression(); 7816 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7817 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7818 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr); 7819 7820 if (isa<MemberExpr>(AssocExpr)) { 7821 // The base is the 'this' pointer. The content of the pointer is going 7822 // to be the base of the field being mapped. 7823 BP = CGF.LoadCXXThisAddress(); 7824 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7825 (OASE && 7826 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7827 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7828 } else if (OAShE && 7829 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) { 7830 BP = Address( 7831 CGF.EmitScalarExpr(OAShE->getBase()), 7832 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType())); 7833 } else { 7834 // The base is the reference to the variable. 7835 // BP = &Var. 7836 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7837 if (const auto *VD = 7838 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7839 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7840 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7841 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7842 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7843 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7844 RequiresReference = true; 7845 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7846 } 7847 } 7848 } 7849 7850 // If the variable is a pointer and is being dereferenced (i.e. is not 7851 // the last component), the base has to be the pointer itself, not its 7852 // reference. References are ignored for mapping purposes. 7853 QualType Ty = 7854 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7855 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7856 // No need to generate individual map information for the pointer, it 7857 // can be associated with the combined storage if shared memory mode is 7858 // active or the base declaration is not global variable. 7859 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration()); 7860 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 7861 !VD || VD->hasLocalStorage()) 7862 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7863 else 7864 FirstPointerInComplexData = true; 7865 ++I; 7866 } 7867 } 7868 7869 // Track whether a component of the list should be marked as MEMBER_OF some 7870 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7871 // in a component list should be marked as MEMBER_OF, all subsequent entries 7872 // do not belong to the base struct. E.g. 7873 // struct S2 s; 7874 // s.ps->ps->ps->f[:] 7875 // (1) (2) (3) (4) 7876 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7877 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7878 // is the pointee of ps(2) which is not member of struct s, so it should not 7879 // be marked as such (it is still PTR_AND_OBJ). 7880 // The variable is initialized to false so that PTR_AND_OBJ entries which 7881 // are not struct members are not considered (e.g. array of pointers to 7882 // data). 7883 bool ShouldBeMemberOf = false; 7884 7885 // Variable keeping track of whether or not we have encountered a component 7886 // in the component list which is a member expression. Useful when we have a 7887 // pointer or a final array section, in which case it is the previous 7888 // component in the list which tells us whether we have a member expression. 7889 // E.g. X.f[:] 7890 // While processing the final array section "[:]" it is "f" which tells us 7891 // whether we are dealing with a member of a declared struct. 7892 const MemberExpr *EncounteredME = nullptr; 7893 7894 // Track for the total number of dimension. Start from one for the dummy 7895 // dimension. 7896 uint64_t DimSize = 1; 7897 7898 bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous; 7899 bool IsPrevMemberReference = false; 7900 7901 for (; I != CE; ++I) { 7902 // If the current component is member of a struct (parent struct) mark it. 7903 if (!EncounteredME) { 7904 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7905 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7906 // as MEMBER_OF the parent struct. 7907 if (EncounteredME) { 7908 ShouldBeMemberOf = true; 7909 // Do not emit as complex pointer if this is actually not array-like 7910 // expression. 7911 if (FirstPointerInComplexData) { 7912 QualType Ty = std::prev(I) 7913 ->getAssociatedDeclaration() 7914 ->getType() 7915 .getNonReferenceType(); 7916 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7917 FirstPointerInComplexData = false; 7918 } 7919 } 7920 } 7921 7922 auto Next = std::next(I); 7923 7924 // We need to generate the addresses and sizes if this is the last 7925 // component, if the component is a pointer or if it is an array section 7926 // whose length can't be proved to be one. If this is a pointer, it 7927 // becomes the base address for the following components. 7928 7929 // A final array section, is one whose length can't be proved to be one. 7930 // If the map item is non-contiguous then we don't treat any array section 7931 // as final array section. 7932 bool IsFinalArraySection = 7933 !IsNonContiguous && 7934 isFinalArraySectionExpression(I->getAssociatedExpression()); 7935 7936 // If we have a declaration for the mapping use that, otherwise use 7937 // the base declaration of the map clause. 7938 const ValueDecl *MapDecl = (I->getAssociatedDeclaration()) 7939 ? I->getAssociatedDeclaration() 7940 : BaseDecl; 7941 MapExpr = (I->getAssociatedExpression()) ? I->getAssociatedExpression() 7942 : MapExpr; 7943 7944 // Get information on whether the element is a pointer. Have to do a 7945 // special treatment for array sections given that they are built-in 7946 // types. 7947 const auto *OASE = 7948 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7949 const auto *OAShE = 7950 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression()); 7951 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 7952 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 7953 bool IsPointer = 7954 OAShE || 7955 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7956 .getCanonicalType() 7957 ->isAnyPointerType()) || 7958 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7959 bool IsMemberReference = isa<MemberExpr>(I->getAssociatedExpression()) && 7960 MapDecl && 7961 MapDecl->getType()->isLValueReferenceType(); 7962 bool IsNonDerefPointer = IsPointer && !UO && !BO && !IsNonContiguous; 7963 7964 if (OASE) 7965 ++DimSize; 7966 7967 if (Next == CE || IsMemberReference || IsNonDerefPointer || 7968 IsFinalArraySection) { 7969 // If this is not the last component, we expect the pointer to be 7970 // associated with an array expression or member expression. 7971 assert((Next == CE || 7972 isa<MemberExpr>(Next->getAssociatedExpression()) || 7973 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7974 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 7975 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || 7976 isa<UnaryOperator>(Next->getAssociatedExpression()) || 7977 isa<BinaryOperator>(Next->getAssociatedExpression())) && 7978 "Unexpected expression"); 7979 7980 Address LB = Address::invalid(); 7981 Address LowestElem = Address::invalid(); 7982 auto &&EmitMemberExprBase = [](CodeGenFunction &CGF, 7983 const MemberExpr *E) { 7984 const Expr *BaseExpr = E->getBase(); 7985 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a 7986 // scalar. 7987 LValue BaseLV; 7988 if (E->isArrow()) { 7989 LValueBaseInfo BaseInfo; 7990 TBAAAccessInfo TBAAInfo; 7991 Address Addr = 7992 CGF.EmitPointerWithAlignment(BaseExpr, &BaseInfo, &TBAAInfo); 7993 QualType PtrTy = BaseExpr->getType()->getPointeeType(); 7994 BaseLV = CGF.MakeAddrLValue(Addr, PtrTy, BaseInfo, TBAAInfo); 7995 } else { 7996 BaseLV = CGF.EmitOMPSharedLValue(BaseExpr); 7997 } 7998 return BaseLV; 7999 }; 8000 if (OAShE) { 8001 LowestElem = LB = Address(CGF.EmitScalarExpr(OAShE->getBase()), 8002 CGF.getContext().getTypeAlignInChars( 8003 OAShE->getBase()->getType())); 8004 } else if (IsMemberReference) { 8005 const auto *ME = cast<MemberExpr>(I->getAssociatedExpression()); 8006 LValue BaseLVal = EmitMemberExprBase(CGF, ME); 8007 LowestElem = CGF.EmitLValueForFieldInitialization( 8008 BaseLVal, cast<FieldDecl>(MapDecl)) 8009 .getAddress(CGF); 8010 LB = CGF.EmitLoadOfReferenceLValue(LowestElem, MapDecl->getType()) 8011 .getAddress(CGF); 8012 } else { 8013 LowestElem = LB = 8014 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 8015 .getAddress(CGF); 8016 } 8017 8018 // If this component is a pointer inside the base struct then we don't 8019 // need to create any entry for it - it will be combined with the object 8020 // it is pointing to into a single PTR_AND_OBJ entry. 8021 bool IsMemberPointerOrAddr = 8022 EncounteredME && 8023 (((IsPointer || ForDeviceAddr) && 8024 I->getAssociatedExpression() == EncounteredME) || 8025 (IsPrevMemberReference && !IsPointer) || 8026 (IsMemberReference && Next != CE && 8027 !Next->getAssociatedExpression()->getType()->isPointerType())); 8028 if (!OverlappedElements.empty() && Next == CE) { 8029 // Handle base element with the info for overlapped elements. 8030 assert(!PartialStruct.Base.isValid() && "The base element is set."); 8031 assert(!IsPointer && 8032 "Unexpected base element with the pointer type."); 8033 // Mark the whole struct as the struct that requires allocation on the 8034 // device. 8035 PartialStruct.LowestElem = {0, LowestElem}; 8036 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 8037 I->getAssociatedExpression()->getType()); 8038 Address HB = CGF.Builder.CreateConstGEP( 8039 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LowestElem, 8040 CGF.VoidPtrTy), 8041 TypeSize.getQuantity() - 1); 8042 PartialStruct.HighestElem = { 8043 std::numeric_limits<decltype( 8044 PartialStruct.HighestElem.first)>::max(), 8045 HB}; 8046 PartialStruct.Base = BP; 8047 PartialStruct.LB = LB; 8048 assert( 8049 PartialStruct.PreliminaryMapData.BasePointers.empty() && 8050 "Overlapped elements must be used only once for the variable."); 8051 std::swap(PartialStruct.PreliminaryMapData, CombinedInfo); 8052 // Emit data for non-overlapped data. 8053 OpenMPOffloadMappingFlags Flags = 8054 OMP_MAP_MEMBER_OF | 8055 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, 8056 /*AddPtrFlag=*/false, 8057 /*AddIsTargetParamFlag=*/false, IsNonContiguous); 8058 llvm::Value *Size = nullptr; 8059 // Do bitcopy of all non-overlapped structure elements. 8060 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 8061 Component : OverlappedElements) { 8062 Address ComponentLB = Address::invalid(); 8063 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 8064 Component) { 8065 if (const ValueDecl *VD = MC.getAssociatedDeclaration()) { 8066 const auto *FD = dyn_cast<FieldDecl>(VD); 8067 if (FD && FD->getType()->isLValueReferenceType()) { 8068 const auto *ME = 8069 cast<MemberExpr>(MC.getAssociatedExpression()); 8070 LValue BaseLVal = EmitMemberExprBase(CGF, ME); 8071 ComponentLB = 8072 CGF.EmitLValueForFieldInitialization(BaseLVal, FD) 8073 .getAddress(CGF); 8074 } else { 8075 ComponentLB = 8076 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 8077 .getAddress(CGF); 8078 } 8079 Size = CGF.Builder.CreatePtrDiff( 8080 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 8081 CGF.EmitCastToVoidPtr(LB.getPointer())); 8082 break; 8083 } 8084 } 8085 assert(Size && "Failed to determine structure size"); 8086 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8087 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8088 CombinedInfo.Pointers.push_back(LB.getPointer()); 8089 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8090 Size, CGF.Int64Ty, /*isSigned=*/true)); 8091 CombinedInfo.Types.push_back(Flags); 8092 CombinedInfo.Mappers.push_back(nullptr); 8093 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8094 : 1); 8095 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 8096 } 8097 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8098 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8099 CombinedInfo.Pointers.push_back(LB.getPointer()); 8100 Size = CGF.Builder.CreatePtrDiff( 8101 CGF.Builder.CreateConstGEP(HB, 1).getPointer(), 8102 CGF.EmitCastToVoidPtr(LB.getPointer())); 8103 CombinedInfo.Sizes.push_back( 8104 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8105 CombinedInfo.Types.push_back(Flags); 8106 CombinedInfo.Mappers.push_back(nullptr); 8107 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8108 : 1); 8109 break; 8110 } 8111 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 8112 if (!IsMemberPointerOrAddr || 8113 (Next == CE && MapType != OMPC_MAP_unknown)) { 8114 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 8115 CombinedInfo.BasePointers.push_back(BP.getPointer()); 8116 CombinedInfo.Pointers.push_back(LB.getPointer()); 8117 CombinedInfo.Sizes.push_back( 8118 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 8119 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 8120 : 1); 8121 8122 // If Mapper is valid, the last component inherits the mapper. 8123 bool HasMapper = Mapper && Next == CE; 8124 CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr); 8125 8126 // We need to add a pointer flag for each map that comes from the 8127 // same expression except for the first one. We also need to signal 8128 // this map is the first one that relates with the current capture 8129 // (there is a set of entries for each capture). 8130 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 8131 MapType, MapModifiers, MotionModifiers, IsImplicit, 8132 !IsExpressionFirstInfo || RequiresReference || 8133 FirstPointerInComplexData || IsMemberReference, 8134 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous); 8135 8136 if (!IsExpressionFirstInfo || IsMemberReference) { 8137 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 8138 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 8139 if (IsPointer || (IsMemberReference && Next != CE)) 8140 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 8141 OMP_MAP_DELETE | OMP_MAP_CLOSE); 8142 8143 if (ShouldBeMemberOf) { 8144 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 8145 // should be later updated with the correct value of MEMBER_OF. 8146 Flags |= OMP_MAP_MEMBER_OF; 8147 // From now on, all subsequent PTR_AND_OBJ entries should not be 8148 // marked as MEMBER_OF. 8149 ShouldBeMemberOf = false; 8150 } 8151 } 8152 8153 CombinedInfo.Types.push_back(Flags); 8154 } 8155 8156 // If we have encountered a member expression so far, keep track of the 8157 // mapped member. If the parent is "*this", then the value declaration 8158 // is nullptr. 8159 if (EncounteredME) { 8160 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 8161 unsigned FieldIndex = FD->getFieldIndex(); 8162 8163 // Update info about the lowest and highest elements for this struct 8164 if (!PartialStruct.Base.isValid()) { 8165 PartialStruct.LowestElem = {FieldIndex, LowestElem}; 8166 if (IsFinalArraySection) { 8167 Address HB = 8168 CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false) 8169 .getAddress(CGF); 8170 PartialStruct.HighestElem = {FieldIndex, HB}; 8171 } else { 8172 PartialStruct.HighestElem = {FieldIndex, LowestElem}; 8173 } 8174 PartialStruct.Base = BP; 8175 PartialStruct.LB = BP; 8176 } else if (FieldIndex < PartialStruct.LowestElem.first) { 8177 PartialStruct.LowestElem = {FieldIndex, LowestElem}; 8178 } else if (FieldIndex > PartialStruct.HighestElem.first) { 8179 PartialStruct.HighestElem = {FieldIndex, LowestElem}; 8180 } 8181 } 8182 8183 // Need to emit combined struct for array sections. 8184 if (IsFinalArraySection || IsNonContiguous) 8185 PartialStruct.IsArraySection = true; 8186 8187 // If we have a final array section, we are done with this expression. 8188 if (IsFinalArraySection) 8189 break; 8190 8191 // The pointer becomes the base for the next element. 8192 if (Next != CE) 8193 BP = IsMemberReference ? LowestElem : LB; 8194 8195 IsExpressionFirstInfo = false; 8196 IsCaptureFirstInfo = false; 8197 FirstPointerInComplexData = false; 8198 IsPrevMemberReference = IsMemberReference; 8199 } else if (FirstPointerInComplexData) { 8200 QualType Ty = Components.rbegin() 8201 ->getAssociatedDeclaration() 8202 ->getType() 8203 .getNonReferenceType(); 8204 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 8205 FirstPointerInComplexData = false; 8206 } 8207 } 8208 // If ran into the whole component - allocate the space for the whole 8209 // record. 8210 if (!EncounteredME) 8211 PartialStruct.HasCompleteRecord = true; 8212 8213 if (!IsNonContiguous) 8214 return; 8215 8216 const ASTContext &Context = CGF.getContext(); 8217 8218 // For supporting stride in array section, we need to initialize the first 8219 // dimension size as 1, first offset as 0, and first count as 1 8220 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 0)}; 8221 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 8222 MapValuesArrayTy CurStrides; 8223 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 8224 uint64_t ElementTypeSize; 8225 8226 // Collect Size information for each dimension and get the element size as 8227 // the first Stride. For example, for `int arr[10][10]`, the DimSizes 8228 // should be [10, 10] and the first stride is 4 btyes. 8229 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 8230 Components) { 8231 const Expr *AssocExpr = Component.getAssociatedExpression(); 8232 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8233 8234 if (!OASE) 8235 continue; 8236 8237 QualType Ty = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase()); 8238 auto *CAT = Context.getAsConstantArrayType(Ty); 8239 auto *VAT = Context.getAsVariableArrayType(Ty); 8240 8241 // We need all the dimension size except for the last dimension. 8242 assert((VAT || CAT || &Component == &*Components.begin()) && 8243 "Should be either ConstantArray or VariableArray if not the " 8244 "first Component"); 8245 8246 // Get element size if CurStrides is empty. 8247 if (CurStrides.empty()) { 8248 const Type *ElementType = nullptr; 8249 if (CAT) 8250 ElementType = CAT->getElementType().getTypePtr(); 8251 else if (VAT) 8252 ElementType = VAT->getElementType().getTypePtr(); 8253 else 8254 assert(&Component == &*Components.begin() && 8255 "Only expect pointer (non CAT or VAT) when this is the " 8256 "first Component"); 8257 // If ElementType is null, then it means the base is a pointer 8258 // (neither CAT nor VAT) and we'll attempt to get ElementType again 8259 // for next iteration. 8260 if (ElementType) { 8261 // For the case that having pointer as base, we need to remove one 8262 // level of indirection. 8263 if (&Component != &*Components.begin()) 8264 ElementType = ElementType->getPointeeOrArrayElementType(); 8265 ElementTypeSize = 8266 Context.getTypeSizeInChars(ElementType).getQuantity(); 8267 CurStrides.push_back( 8268 llvm::ConstantInt::get(CGF.Int64Ty, ElementTypeSize)); 8269 } 8270 } 8271 // Get dimension value except for the last dimension since we don't need 8272 // it. 8273 if (DimSizes.size() < Components.size() - 1) { 8274 if (CAT) 8275 DimSizes.push_back(llvm::ConstantInt::get( 8276 CGF.Int64Ty, CAT->getSize().getZExtValue())); 8277 else if (VAT) 8278 DimSizes.push_back(CGF.Builder.CreateIntCast( 8279 CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty, 8280 /*IsSigned=*/false)); 8281 } 8282 } 8283 8284 // Skip the dummy dimension since we have already have its information. 8285 auto DI = DimSizes.begin() + 1; 8286 // Product of dimension. 8287 llvm::Value *DimProd = 8288 llvm::ConstantInt::get(CGF.CGM.Int64Ty, ElementTypeSize); 8289 8290 // Collect info for non-contiguous. Notice that offset, count, and stride 8291 // are only meaningful for array-section, so we insert a null for anything 8292 // other than array-section. 8293 // Also, the size of offset, count, and stride are not the same as 8294 // pointers, base_pointers, sizes, or dims. Instead, the size of offset, 8295 // count, and stride are the same as the number of non-contiguous 8296 // declaration in target update to/from clause. 8297 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 8298 Components) { 8299 const Expr *AssocExpr = Component.getAssociatedExpression(); 8300 8301 if (const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) { 8302 llvm::Value *Offset = CGF.Builder.CreateIntCast( 8303 CGF.EmitScalarExpr(AE->getIdx()), CGF.Int64Ty, 8304 /*isSigned=*/false); 8305 CurOffsets.push_back(Offset); 8306 CurCounts.push_back(llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/1)); 8307 CurStrides.push_back(CurStrides.back()); 8308 continue; 8309 } 8310 8311 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8312 8313 if (!OASE) 8314 continue; 8315 8316 // Offset 8317 const Expr *OffsetExpr = OASE->getLowerBound(); 8318 llvm::Value *Offset = nullptr; 8319 if (!OffsetExpr) { 8320 // If offset is absent, then we just set it to zero. 8321 Offset = llvm::ConstantInt::get(CGF.Int64Ty, 0); 8322 } else { 8323 Offset = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(OffsetExpr), 8324 CGF.Int64Ty, 8325 /*isSigned=*/false); 8326 } 8327 CurOffsets.push_back(Offset); 8328 8329 // Count 8330 const Expr *CountExpr = OASE->getLength(); 8331 llvm::Value *Count = nullptr; 8332 if (!CountExpr) { 8333 // In Clang, once a high dimension is an array section, we construct all 8334 // the lower dimension as array section, however, for case like 8335 // arr[0:2][2], Clang construct the inner dimension as an array section 8336 // but it actually is not in an array section form according to spec. 8337 if (!OASE->getColonLocFirst().isValid() && 8338 !OASE->getColonLocSecond().isValid()) { 8339 Count = llvm::ConstantInt::get(CGF.Int64Ty, 1); 8340 } else { 8341 // OpenMP 5.0, 2.1.5 Array Sections, Description. 8342 // When the length is absent it defaults to ⌈(size − 8343 // lower-bound)/stride⌉, where size is the size of the array 8344 // dimension. 8345 const Expr *StrideExpr = OASE->getStride(); 8346 llvm::Value *Stride = 8347 StrideExpr 8348 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8349 CGF.Int64Ty, /*isSigned=*/false) 8350 : nullptr; 8351 if (Stride) 8352 Count = CGF.Builder.CreateUDiv( 8353 CGF.Builder.CreateNUWSub(*DI, Offset), Stride); 8354 else 8355 Count = CGF.Builder.CreateNUWSub(*DI, Offset); 8356 } 8357 } else { 8358 Count = CGF.EmitScalarExpr(CountExpr); 8359 } 8360 Count = CGF.Builder.CreateIntCast(Count, CGF.Int64Ty, /*isSigned=*/false); 8361 CurCounts.push_back(Count); 8362 8363 // Stride_n' = Stride_n * (D_0 * D_1 ... * D_n-1) * Unit size 8364 // Take `int arr[5][5][5]` and `arr[0:2:2][1:2:1][0:2:2]` as an example: 8365 // Offset Count Stride 8366 // D0 0 1 4 (int) <- dummy dimension 8367 // D1 0 2 8 (2 * (1) * 4) 8368 // D2 1 2 20 (1 * (1 * 5) * 4) 8369 // D3 0 2 200 (2 * (1 * 5 * 4) * 4) 8370 const Expr *StrideExpr = OASE->getStride(); 8371 llvm::Value *Stride = 8372 StrideExpr 8373 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8374 CGF.Int64Ty, /*isSigned=*/false) 8375 : nullptr; 8376 DimProd = CGF.Builder.CreateNUWMul(DimProd, *(DI - 1)); 8377 if (Stride) 8378 CurStrides.push_back(CGF.Builder.CreateNUWMul(DimProd, Stride)); 8379 else 8380 CurStrides.push_back(DimProd); 8381 if (DI != DimSizes.end()) 8382 ++DI; 8383 } 8384 8385 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets); 8386 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts); 8387 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides); 8388 } 8389 8390 /// Return the adjusted map modifiers if the declaration a capture refers to 8391 /// appears in a first-private clause. This is expected to be used only with 8392 /// directives that start with 'target'. 8393 MappableExprsHandler::OpenMPOffloadMappingFlags 8394 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 8395 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 8396 8397 // A first private variable captured by reference will use only the 8398 // 'private ptr' and 'map to' flag. Return the right flags if the captured 8399 // declaration is known as first-private in this handler. 8400 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 8401 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 8402 return MappableExprsHandler::OMP_MAP_TO | 8403 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 8404 return MappableExprsHandler::OMP_MAP_PRIVATE | 8405 MappableExprsHandler::OMP_MAP_TO; 8406 } 8407 return MappableExprsHandler::OMP_MAP_TO | 8408 MappableExprsHandler::OMP_MAP_FROM; 8409 } 8410 8411 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 8412 // Rotate by getFlagMemberOffset() bits. 8413 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 8414 << getFlagMemberOffset()); 8415 } 8416 8417 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 8418 OpenMPOffloadMappingFlags MemberOfFlag) { 8419 // If the entry is PTR_AND_OBJ but has not been marked with the special 8420 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 8421 // marked as MEMBER_OF. 8422 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 8423 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 8424 return; 8425 8426 // Reset the placeholder value to prepare the flag for the assignment of the 8427 // proper MEMBER_OF value. 8428 Flags &= ~OMP_MAP_MEMBER_OF; 8429 Flags |= MemberOfFlag; 8430 } 8431 8432 void getPlainLayout(const CXXRecordDecl *RD, 8433 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 8434 bool AsBase) const { 8435 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 8436 8437 llvm::StructType *St = 8438 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 8439 8440 unsigned NumElements = St->getNumElements(); 8441 llvm::SmallVector< 8442 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 8443 RecordLayout(NumElements); 8444 8445 // Fill bases. 8446 for (const auto &I : RD->bases()) { 8447 if (I.isVirtual()) 8448 continue; 8449 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8450 // Ignore empty bases. 8451 if (Base->isEmpty() || CGF.getContext() 8452 .getASTRecordLayout(Base) 8453 .getNonVirtualSize() 8454 .isZero()) 8455 continue; 8456 8457 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 8458 RecordLayout[FieldIndex] = Base; 8459 } 8460 // Fill in virtual bases. 8461 for (const auto &I : RD->vbases()) { 8462 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8463 // Ignore empty bases. 8464 if (Base->isEmpty()) 8465 continue; 8466 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 8467 if (RecordLayout[FieldIndex]) 8468 continue; 8469 RecordLayout[FieldIndex] = Base; 8470 } 8471 // Fill in all the fields. 8472 assert(!RD->isUnion() && "Unexpected union."); 8473 for (const auto *Field : RD->fields()) { 8474 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 8475 // will fill in later.) 8476 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 8477 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 8478 RecordLayout[FieldIndex] = Field; 8479 } 8480 } 8481 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 8482 &Data : RecordLayout) { 8483 if (Data.isNull()) 8484 continue; 8485 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 8486 getPlainLayout(Base, Layout, /*AsBase=*/true); 8487 else 8488 Layout.push_back(Data.get<const FieldDecl *>()); 8489 } 8490 } 8491 8492 /// Generate all the base pointers, section pointers, sizes, map types, and 8493 /// mappers for the extracted mappable expressions (all included in \a 8494 /// CombinedInfo). Also, for each item that relates with a device pointer, a 8495 /// pair of the relevant declaration and index where it occurs is appended to 8496 /// the device pointers info array. 8497 void generateAllInfoForClauses( 8498 ArrayRef<const OMPClause *> Clauses, MapCombinedInfoTy &CombinedInfo, 8499 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 8500 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 8501 // We have to process the component lists that relate with the same 8502 // declaration in a single chunk so that we can generate the map flags 8503 // correctly. Therefore, we organize all lists in a map. 8504 enum MapKind { Present, Allocs, Other, Total }; 8505 llvm::MapVector<CanonicalDeclPtr<const Decl>, 8506 SmallVector<SmallVector<MapInfo, 8>, 4>> 8507 Info; 8508 8509 // Helper function to fill the information map for the different supported 8510 // clauses. 8511 auto &&InfoGen = 8512 [&Info, &SkipVarSet]( 8513 const ValueDecl *D, MapKind Kind, 8514 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8515 OpenMPMapClauseKind MapType, 8516 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8517 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 8518 bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper, 8519 const Expr *VarRef = nullptr, bool ForDeviceAddr = false) { 8520 if (SkipVarSet.contains(D)) 8521 return; 8522 auto It = Info.find(D); 8523 if (It == Info.end()) 8524 It = Info 8525 .insert(std::make_pair( 8526 D, SmallVector<SmallVector<MapInfo, 8>, 4>(Total))) 8527 .first; 8528 It->second[Kind].emplace_back( 8529 L, MapType, MapModifiers, MotionModifiers, ReturnDevicePointer, 8530 IsImplicit, Mapper, VarRef, ForDeviceAddr); 8531 }; 8532 8533 for (const auto *Cl : Clauses) { 8534 const auto *C = dyn_cast<OMPMapClause>(Cl); 8535 if (!C) 8536 continue; 8537 MapKind Kind = Other; 8538 if (!C->getMapTypeModifiers().empty() && 8539 llvm::any_of(C->getMapTypeModifiers(), [](OpenMPMapModifierKind K) { 8540 return K == OMPC_MAP_MODIFIER_present; 8541 })) 8542 Kind = Present; 8543 else if (C->getMapType() == OMPC_MAP_alloc) 8544 Kind = Allocs; 8545 const auto *EI = C->getVarRefs().begin(); 8546 for (const auto L : C->component_lists()) { 8547 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 8548 InfoGen(std::get<0>(L), Kind, std::get<1>(L), C->getMapType(), 8549 C->getMapTypeModifiers(), llvm::None, 8550 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L), 8551 E); 8552 ++EI; 8553 } 8554 } 8555 for (const auto *Cl : Clauses) { 8556 const auto *C = dyn_cast<OMPToClause>(Cl); 8557 if (!C) 8558 continue; 8559 MapKind Kind = Other; 8560 if (!C->getMotionModifiers().empty() && 8561 llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) { 8562 return K == OMPC_MOTION_MODIFIER_present; 8563 })) 8564 Kind = Present; 8565 const auto *EI = C->getVarRefs().begin(); 8566 for (const auto L : C->component_lists()) { 8567 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_to, llvm::None, 8568 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8569 C->isImplicit(), std::get<2>(L), *EI); 8570 ++EI; 8571 } 8572 } 8573 for (const auto *Cl : Clauses) { 8574 const auto *C = dyn_cast<OMPFromClause>(Cl); 8575 if (!C) 8576 continue; 8577 MapKind Kind = Other; 8578 if (!C->getMotionModifiers().empty() && 8579 llvm::any_of(C->getMotionModifiers(), [](OpenMPMotionModifierKind K) { 8580 return K == OMPC_MOTION_MODIFIER_present; 8581 })) 8582 Kind = Present; 8583 const auto *EI = C->getVarRefs().begin(); 8584 for (const auto L : C->component_lists()) { 8585 InfoGen(std::get<0>(L), Kind, std::get<1>(L), OMPC_MAP_from, llvm::None, 8586 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8587 C->isImplicit(), std::get<2>(L), *EI); 8588 ++EI; 8589 } 8590 } 8591 8592 // Look at the use_device_ptr clause information and mark the existing map 8593 // entries as such. If there is no map information for an entry in the 8594 // use_device_ptr list, we create one with map type 'alloc' and zero size 8595 // section. It is the user fault if that was not mapped before. If there is 8596 // no map information and the pointer is a struct member, then we defer the 8597 // emission of that entry until the whole struct has been processed. 8598 llvm::MapVector<CanonicalDeclPtr<const Decl>, 8599 SmallVector<DeferredDevicePtrEntryTy, 4>> 8600 DeferredInfo; 8601 MapCombinedInfoTy UseDevicePtrCombinedInfo; 8602 8603 for (const auto *Cl : Clauses) { 8604 const auto *C = dyn_cast<OMPUseDevicePtrClause>(Cl); 8605 if (!C) 8606 continue; 8607 for (const auto L : C->component_lists()) { 8608 OMPClauseMappableExprCommon::MappableExprComponentListRef Components = 8609 std::get<1>(L); 8610 assert(!Components.empty() && 8611 "Not expecting empty list of components!"); 8612 const ValueDecl *VD = Components.back().getAssociatedDeclaration(); 8613 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8614 const Expr *IE = Components.back().getAssociatedExpression(); 8615 // If the first component is a member expression, we have to look into 8616 // 'this', which maps to null in the map of map information. Otherwise 8617 // look directly for the information. 8618 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8619 8620 // We potentially have map information for this declaration already. 8621 // Look for the first set of components that refer to it. 8622 if (It != Info.end()) { 8623 bool Found = false; 8624 for (auto &Data : It->second) { 8625 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) { 8626 return MI.Components.back().getAssociatedDeclaration() == VD; 8627 }); 8628 // If we found a map entry, signal that the pointer has to be 8629 // returned and move on to the next declaration. Exclude cases where 8630 // the base pointer is mapped as array subscript, array section or 8631 // array shaping. The base address is passed as a pointer to base in 8632 // this case and cannot be used as a base for use_device_ptr list 8633 // item. 8634 if (CI != Data.end()) { 8635 auto PrevCI = std::next(CI->Components.rbegin()); 8636 const auto *VarD = dyn_cast<VarDecl>(VD); 8637 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8638 isa<MemberExpr>(IE) || 8639 !VD->getType().getNonReferenceType()->isPointerType() || 8640 PrevCI == CI->Components.rend() || 8641 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD || 8642 VarD->hasLocalStorage()) { 8643 CI->ReturnDevicePointer = true; 8644 Found = true; 8645 break; 8646 } 8647 } 8648 } 8649 if (Found) 8650 continue; 8651 } 8652 8653 // We didn't find any match in our map information - generate a zero 8654 // size array section - if the pointer is a struct member we defer this 8655 // action until the whole struct has been processed. 8656 if (isa<MemberExpr>(IE)) { 8657 // Insert the pointer into Info to be processed by 8658 // generateInfoForComponentList. Because it is a member pointer 8659 // without a pointee, no entry will be generated for it, therefore 8660 // we need to generate one after the whole struct has been processed. 8661 // Nonetheless, generateInfoForComponentList must be called to take 8662 // the pointer into account for the calculation of the range of the 8663 // partial struct. 8664 InfoGen(nullptr, Other, Components, OMPC_MAP_unknown, llvm::None, 8665 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8666 nullptr); 8667 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false); 8668 } else { 8669 llvm::Value *Ptr = 8670 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8671 UseDevicePtrCombinedInfo.Exprs.push_back(VD); 8672 UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD); 8673 UseDevicePtrCombinedInfo.Pointers.push_back(Ptr); 8674 UseDevicePtrCombinedInfo.Sizes.push_back( 8675 llvm::Constant::getNullValue(CGF.Int64Ty)); 8676 UseDevicePtrCombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM); 8677 UseDevicePtrCombinedInfo.Mappers.push_back(nullptr); 8678 } 8679 } 8680 } 8681 8682 // Look at the use_device_addr clause information and mark the existing map 8683 // entries as such. If there is no map information for an entry in the 8684 // use_device_addr list, we create one with map type 'alloc' and zero size 8685 // section. It is the user fault if that was not mapped before. If there is 8686 // no map information and the pointer is a struct member, then we defer the 8687 // emission of that entry until the whole struct has been processed. 8688 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed; 8689 for (const auto *Cl : Clauses) { 8690 const auto *C = dyn_cast<OMPUseDeviceAddrClause>(Cl); 8691 if (!C) 8692 continue; 8693 for (const auto L : C->component_lists()) { 8694 assert(!std::get<1>(L).empty() && 8695 "Not expecting empty list of components!"); 8696 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration(); 8697 if (!Processed.insert(VD).second) 8698 continue; 8699 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8700 const Expr *IE = std::get<1>(L).back().getAssociatedExpression(); 8701 // If the first component is a member expression, we have to look into 8702 // 'this', which maps to null in the map of map information. Otherwise 8703 // look directly for the information. 8704 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8705 8706 // We potentially have map information for this declaration already. 8707 // Look for the first set of components that refer to it. 8708 if (It != Info.end()) { 8709 bool Found = false; 8710 for (auto &Data : It->second) { 8711 auto *CI = llvm::find_if(Data, [VD](const MapInfo &MI) { 8712 return MI.Components.back().getAssociatedDeclaration() == VD; 8713 }); 8714 // If we found a map entry, signal that the pointer has to be 8715 // returned and move on to the next declaration. 8716 if (CI != Data.end()) { 8717 CI->ReturnDevicePointer = true; 8718 Found = true; 8719 break; 8720 } 8721 } 8722 if (Found) 8723 continue; 8724 } 8725 8726 // We didn't find any match in our map information - generate a zero 8727 // size array section - if the pointer is a struct member we defer this 8728 // action until the whole struct has been processed. 8729 if (isa<MemberExpr>(IE)) { 8730 // Insert the pointer into Info to be processed by 8731 // generateInfoForComponentList. Because it is a member pointer 8732 // without a pointee, no entry will be generated for it, therefore 8733 // we need to generate one after the whole struct has been processed. 8734 // Nonetheless, generateInfoForComponentList must be called to take 8735 // the pointer into account for the calculation of the range of the 8736 // partial struct. 8737 InfoGen(nullptr, Other, std::get<1>(L), OMPC_MAP_unknown, llvm::None, 8738 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8739 nullptr, nullptr, /*ForDeviceAddr=*/true); 8740 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true); 8741 } else { 8742 llvm::Value *Ptr; 8743 if (IE->isGLValue()) 8744 Ptr = CGF.EmitLValue(IE).getPointer(CGF); 8745 else 8746 Ptr = CGF.EmitScalarExpr(IE); 8747 CombinedInfo.Exprs.push_back(VD); 8748 CombinedInfo.BasePointers.emplace_back(Ptr, VD); 8749 CombinedInfo.Pointers.push_back(Ptr); 8750 CombinedInfo.Sizes.push_back( 8751 llvm::Constant::getNullValue(CGF.Int64Ty)); 8752 CombinedInfo.Types.push_back(OMP_MAP_RETURN_PARAM); 8753 CombinedInfo.Mappers.push_back(nullptr); 8754 } 8755 } 8756 } 8757 8758 for (const auto &Data : Info) { 8759 StructRangeInfoTy PartialStruct; 8760 // Temporary generated information. 8761 MapCombinedInfoTy CurInfo; 8762 const Decl *D = Data.first; 8763 const ValueDecl *VD = cast_or_null<ValueDecl>(D); 8764 for (const auto &M : Data.second) { 8765 for (const MapInfo &L : M) { 8766 assert(!L.Components.empty() && 8767 "Not expecting declaration with no component lists."); 8768 8769 // Remember the current base pointer index. 8770 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size(); 8771 CurInfo.NonContigInfo.IsNonContiguous = 8772 L.Components.back().isNonContiguous(); 8773 generateInfoForComponentList( 8774 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components, 8775 CurInfo, PartialStruct, /*IsFirstComponentList=*/false, 8776 L.IsImplicit, L.Mapper, L.ForDeviceAddr, VD, L.VarRef); 8777 8778 // If this entry relates with a device pointer, set the relevant 8779 // declaration and add the 'return pointer' flag. 8780 if (L.ReturnDevicePointer) { 8781 assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx && 8782 "Unexpected number of mapped base pointers."); 8783 8784 const ValueDecl *RelevantVD = 8785 L.Components.back().getAssociatedDeclaration(); 8786 assert(RelevantVD && 8787 "No relevant declaration related with device pointer??"); 8788 8789 CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl( 8790 RelevantVD); 8791 CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8792 } 8793 } 8794 } 8795 8796 // Append any pending zero-length pointers which are struct members and 8797 // used with use_device_ptr or use_device_addr. 8798 auto CI = DeferredInfo.find(Data.first); 8799 if (CI != DeferredInfo.end()) { 8800 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8801 llvm::Value *BasePtr; 8802 llvm::Value *Ptr; 8803 if (L.ForDeviceAddr) { 8804 if (L.IE->isGLValue()) 8805 Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8806 else 8807 Ptr = this->CGF.EmitScalarExpr(L.IE); 8808 BasePtr = Ptr; 8809 // Entry is RETURN_PARAM. Also, set the placeholder value 8810 // MEMBER_OF=FFFF so that the entry is later updated with the 8811 // correct value of MEMBER_OF. 8812 CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF); 8813 } else { 8814 BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8815 Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE), 8816 L.IE->getExprLoc()); 8817 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the 8818 // placeholder value MEMBER_OF=FFFF so that the entry is later 8819 // updated with the correct value of MEMBER_OF. 8820 CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8821 OMP_MAP_MEMBER_OF); 8822 } 8823 CurInfo.Exprs.push_back(L.VD); 8824 CurInfo.BasePointers.emplace_back(BasePtr, L.VD); 8825 CurInfo.Pointers.push_back(Ptr); 8826 CurInfo.Sizes.push_back( 8827 llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8828 CurInfo.Mappers.push_back(nullptr); 8829 } 8830 } 8831 // If there is an entry in PartialStruct it means we have a struct with 8832 // individual members mapped. Emit an extra combined entry. 8833 if (PartialStruct.Base.isValid()) { 8834 CurInfo.NonContigInfo.Dims.push_back(0); 8835 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD); 8836 } 8837 8838 // We need to append the results of this capture to what we already 8839 // have. 8840 CombinedInfo.append(CurInfo); 8841 } 8842 // Append data for use_device_ptr clauses. 8843 CombinedInfo.append(UseDevicePtrCombinedInfo); 8844 } 8845 8846 public: 8847 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 8848 : CurDir(&Dir), CGF(CGF) { 8849 // Extract firstprivate clause information. 8850 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 8851 for (const auto *D : C->varlists()) 8852 FirstPrivateDecls.try_emplace( 8853 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 8854 // Extract implicit firstprivates from uses_allocators clauses. 8855 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) { 8856 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 8857 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 8858 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits)) 8859 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()), 8860 /*Implicit=*/true); 8861 else if (const auto *VD = dyn_cast<VarDecl>( 8862 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts()) 8863 ->getDecl())) 8864 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true); 8865 } 8866 } 8867 // Extract device pointer clause information. 8868 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 8869 for (auto L : C->component_lists()) 8870 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L)); 8871 } 8872 8873 /// Constructor for the declare mapper directive. 8874 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 8875 : CurDir(&Dir), CGF(CGF) {} 8876 8877 /// Generate code for the combined entry if we have a partially mapped struct 8878 /// and take care of the mapping flags of the arguments corresponding to 8879 /// individual struct members. 8880 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo, 8881 MapFlagsArrayTy &CurTypes, 8882 const StructRangeInfoTy &PartialStruct, 8883 const ValueDecl *VD = nullptr, 8884 bool NotTargetParams = true) const { 8885 if (CurTypes.size() == 1 && 8886 ((CurTypes.back() & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF) && 8887 !PartialStruct.IsArraySection) 8888 return; 8889 Address LBAddr = PartialStruct.LowestElem.second; 8890 Address HBAddr = PartialStruct.HighestElem.second; 8891 if (PartialStruct.HasCompleteRecord) { 8892 LBAddr = PartialStruct.LB; 8893 HBAddr = PartialStruct.LB; 8894 } 8895 CombinedInfo.Exprs.push_back(VD); 8896 // Base is the base of the struct 8897 CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); 8898 // Pointer is the address of the lowest element 8899 llvm::Value *LB = LBAddr.getPointer(); 8900 CombinedInfo.Pointers.push_back(LB); 8901 // There should not be a mapper for a combined entry. 8902 CombinedInfo.Mappers.push_back(nullptr); 8903 // Size is (addr of {highest+1} element) - (addr of lowest element) 8904 llvm::Value *HB = HBAddr.getPointer(); 8905 llvm::Value *HAddr = 8906 CGF.Builder.CreateConstGEP1_32(HBAddr.getElementType(), HB, /*Idx0=*/1); 8907 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 8908 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 8909 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 8910 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 8911 /*isSigned=*/false); 8912 CombinedInfo.Sizes.push_back(Size); 8913 // Map type is always TARGET_PARAM, if generate info for captures. 8914 CombinedInfo.Types.push_back(NotTargetParams ? OMP_MAP_NONE 8915 : OMP_MAP_TARGET_PARAM); 8916 // If any element has the present modifier, then make sure the runtime 8917 // doesn't attempt to allocate the struct. 8918 if (CurTypes.end() != 8919 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) { 8920 return Type & OMP_MAP_PRESENT; 8921 })) 8922 CombinedInfo.Types.back() |= OMP_MAP_PRESENT; 8923 // Remove TARGET_PARAM flag from the first element 8924 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 8925 8926 // All other current entries will be MEMBER_OF the combined entry 8927 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8928 // 0xFFFF in the MEMBER_OF field). 8929 OpenMPOffloadMappingFlags MemberOfFlag = 8930 getMemberOfFlag(CombinedInfo.BasePointers.size() - 1); 8931 for (auto &M : CurTypes) 8932 setCorrectMemberOfFlag(M, MemberOfFlag); 8933 } 8934 8935 /// Generate all the base pointers, section pointers, sizes, map types, and 8936 /// mappers for the extracted mappable expressions (all included in \a 8937 /// CombinedInfo). Also, for each item that relates with a device pointer, a 8938 /// pair of the relevant declaration and index where it occurs is appended to 8939 /// the device pointers info array. 8940 void generateAllInfo( 8941 MapCombinedInfoTy &CombinedInfo, 8942 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 8943 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 8944 assert(CurDir.is<const OMPExecutableDirective *>() && 8945 "Expect a executable directive"); 8946 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8947 generateAllInfoForClauses(CurExecDir->clauses(), CombinedInfo, SkipVarSet); 8948 } 8949 8950 /// Generate all the base pointers, section pointers, sizes, map types, and 8951 /// mappers for the extracted map clauses of user-defined mapper (all included 8952 /// in \a CombinedInfo). 8953 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const { 8954 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8955 "Expect a declare mapper directive"); 8956 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8957 generateAllInfoForClauses(CurMapperDir->clauses(), CombinedInfo); 8958 } 8959 8960 /// Emit capture info for lambdas for variables captured by reference. 8961 void generateInfoForLambdaCaptures( 8962 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 8963 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8964 const auto *RD = VD->getType() 8965 .getCanonicalType() 8966 .getNonReferenceType() 8967 ->getAsCXXRecordDecl(); 8968 if (!RD || !RD->isLambda()) 8969 return; 8970 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8971 LValue VDLVal = CGF.MakeAddrLValue( 8972 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8973 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8974 FieldDecl *ThisCapture = nullptr; 8975 RD->getCaptureFields(Captures, ThisCapture); 8976 if (ThisCapture) { 8977 LValue ThisLVal = 8978 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8979 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8980 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8981 VDLVal.getPointer(CGF)); 8982 CombinedInfo.Exprs.push_back(VD); 8983 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF)); 8984 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF)); 8985 CombinedInfo.Sizes.push_back( 8986 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8987 CGF.Int64Ty, /*isSigned=*/true)); 8988 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8989 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8990 CombinedInfo.Mappers.push_back(nullptr); 8991 } 8992 for (const LambdaCapture &LC : RD->captures()) { 8993 if (!LC.capturesVariable()) 8994 continue; 8995 const VarDecl *VD = LC.getCapturedVar(); 8996 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8997 continue; 8998 auto It = Captures.find(VD); 8999 assert(It != Captures.end() && "Found lambda capture without field."); 9000 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 9001 if (LC.getCaptureKind() == LCK_ByRef) { 9002 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 9003 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 9004 VDLVal.getPointer(CGF)); 9005 CombinedInfo.Exprs.push_back(VD); 9006 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 9007 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF)); 9008 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9009 CGF.getTypeSize( 9010 VD->getType().getCanonicalType().getNonReferenceType()), 9011 CGF.Int64Ty, /*isSigned=*/true)); 9012 } else { 9013 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 9014 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 9015 VDLVal.getPointer(CGF)); 9016 CombinedInfo.Exprs.push_back(VD); 9017 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 9018 CombinedInfo.Pointers.push_back(VarRVal.getScalarVal()); 9019 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 9020 } 9021 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9022 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 9023 CombinedInfo.Mappers.push_back(nullptr); 9024 } 9025 } 9026 9027 /// Set correct indices for lambdas captures. 9028 void adjustMemberOfForLambdaCaptures( 9029 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 9030 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 9031 MapFlagsArrayTy &Types) const { 9032 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 9033 // Set correct member_of idx for all implicit lambda captures. 9034 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 9035 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 9036 continue; 9037 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 9038 assert(BasePtr && "Unable to find base lambda address."); 9039 int TgtIdx = -1; 9040 for (unsigned J = I; J > 0; --J) { 9041 unsigned Idx = J - 1; 9042 if (Pointers[Idx] != BasePtr) 9043 continue; 9044 TgtIdx = Idx; 9045 break; 9046 } 9047 assert(TgtIdx != -1 && "Unable to find parent lambda."); 9048 // All other current entries will be MEMBER_OF the combined entry 9049 // (except for PTR_AND_OBJ entries which do not have a placeholder value 9050 // 0xFFFF in the MEMBER_OF field). 9051 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 9052 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 9053 } 9054 } 9055 9056 /// Generate the base pointers, section pointers, sizes, map types, and 9057 /// mappers associated to a given capture (all included in \a CombinedInfo). 9058 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 9059 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 9060 StructRangeInfoTy &PartialStruct) const { 9061 assert(!Cap->capturesVariableArrayType() && 9062 "Not expecting to generate map info for a variable array type!"); 9063 9064 // We need to know when we generating information for the first component 9065 const ValueDecl *VD = Cap->capturesThis() 9066 ? nullptr 9067 : Cap->getCapturedVar()->getCanonicalDecl(); 9068 9069 // If this declaration appears in a is_device_ptr clause we just have to 9070 // pass the pointer by value. If it is a reference to a declaration, we just 9071 // pass its value. 9072 if (DevPointersMap.count(VD)) { 9073 CombinedInfo.Exprs.push_back(VD); 9074 CombinedInfo.BasePointers.emplace_back(Arg, VD); 9075 CombinedInfo.Pointers.push_back(Arg); 9076 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9077 CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty, 9078 /*isSigned=*/true)); 9079 CombinedInfo.Types.push_back( 9080 (Cap->capturesVariable() ? OMP_MAP_TO : OMP_MAP_LITERAL) | 9081 OMP_MAP_TARGET_PARAM); 9082 CombinedInfo.Mappers.push_back(nullptr); 9083 return; 9084 } 9085 9086 using MapData = 9087 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 9088 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool, 9089 const ValueDecl *, const Expr *>; 9090 SmallVector<MapData, 4> DeclComponentLists; 9091 assert(CurDir.is<const OMPExecutableDirective *>() && 9092 "Expect a executable directive"); 9093 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 9094 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 9095 const auto *EI = C->getVarRefs().begin(); 9096 for (const auto L : C->decl_component_lists(VD)) { 9097 const ValueDecl *VDecl, *Mapper; 9098 // The Expression is not correct if the mapping is implicit 9099 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 9100 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9101 std::tie(VDecl, Components, Mapper) = L; 9102 assert(VDecl == VD && "We got information for the wrong declaration??"); 9103 assert(!Components.empty() && 9104 "Not expecting declaration with no component lists."); 9105 DeclComponentLists.emplace_back(Components, C->getMapType(), 9106 C->getMapTypeModifiers(), 9107 C->isImplicit(), Mapper, E); 9108 ++EI; 9109 } 9110 } 9111 llvm::stable_sort(DeclComponentLists, [](const MapData &LHS, 9112 const MapData &RHS) { 9113 ArrayRef<OpenMPMapModifierKind> MapModifiers = std::get<2>(LHS); 9114 OpenMPMapClauseKind MapType = std::get<1>(RHS); 9115 bool HasPresent = !MapModifiers.empty() && 9116 llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) { 9117 return K == clang::OMPC_MAP_MODIFIER_present; 9118 }); 9119 bool HasAllocs = MapType == OMPC_MAP_alloc; 9120 MapModifiers = std::get<2>(RHS); 9121 MapType = std::get<1>(LHS); 9122 bool HasPresentR = 9123 !MapModifiers.empty() && 9124 llvm::any_of(MapModifiers, [](OpenMPMapModifierKind K) { 9125 return K == clang::OMPC_MAP_MODIFIER_present; 9126 }); 9127 bool HasAllocsR = MapType == OMPC_MAP_alloc; 9128 return (HasPresent && !HasPresentR) || (HasAllocs && !HasAllocsR); 9129 }); 9130 9131 // Find overlapping elements (including the offset from the base element). 9132 llvm::SmallDenseMap< 9133 const MapData *, 9134 llvm::SmallVector< 9135 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 9136 4> 9137 OverlappedData; 9138 size_t Count = 0; 9139 for (const MapData &L : DeclComponentLists) { 9140 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9141 OpenMPMapClauseKind MapType; 9142 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9143 bool IsImplicit; 9144 const ValueDecl *Mapper; 9145 const Expr *VarRef; 9146 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9147 L; 9148 ++Count; 9149 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 9150 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 9151 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper, 9152 VarRef) = L1; 9153 auto CI = Components.rbegin(); 9154 auto CE = Components.rend(); 9155 auto SI = Components1.rbegin(); 9156 auto SE = Components1.rend(); 9157 for (; CI != CE && SI != SE; ++CI, ++SI) { 9158 if (CI->getAssociatedExpression()->getStmtClass() != 9159 SI->getAssociatedExpression()->getStmtClass()) 9160 break; 9161 // Are we dealing with different variables/fields? 9162 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 9163 break; 9164 } 9165 // Found overlapping if, at least for one component, reached the head 9166 // of the components list. 9167 if (CI == CE || SI == SE) { 9168 // Ignore it if it is the same component. 9169 if (CI == CE && SI == SE) 9170 continue; 9171 const auto It = (SI == SE) ? CI : SI; 9172 // If one component is a pointer and another one is a kind of 9173 // dereference of this pointer (array subscript, section, dereference, 9174 // etc.), it is not an overlapping. 9175 // Same, if one component is a base and another component is a 9176 // dereferenced pointer memberexpr with the same base. 9177 if (!isa<MemberExpr>(It->getAssociatedExpression()) || 9178 (std::prev(It)->getAssociatedDeclaration() && 9179 std::prev(It) 9180 ->getAssociatedDeclaration() 9181 ->getType() 9182 ->isPointerType()) || 9183 (It->getAssociatedDeclaration() && 9184 It->getAssociatedDeclaration()->getType()->isPointerType() && 9185 std::next(It) != CE && std::next(It) != SE)) 9186 continue; 9187 const MapData &BaseData = CI == CE ? L : L1; 9188 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 9189 SI == SE ? Components : Components1; 9190 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 9191 OverlappedElements.getSecond().push_back(SubData); 9192 } 9193 } 9194 } 9195 // Sort the overlapped elements for each item. 9196 llvm::SmallVector<const FieldDecl *, 4> Layout; 9197 if (!OverlappedData.empty()) { 9198 const Type *BaseType = VD->getType().getCanonicalType().getTypePtr(); 9199 const Type *OrigType = BaseType->getPointeeOrArrayElementType(); 9200 while (BaseType != OrigType) { 9201 BaseType = OrigType->getCanonicalTypeInternal().getTypePtr(); 9202 OrigType = BaseType->getPointeeOrArrayElementType(); 9203 } 9204 9205 if (const auto *CRD = BaseType->getAsCXXRecordDecl()) 9206 getPlainLayout(CRD, Layout, /*AsBase=*/false); 9207 else { 9208 const auto *RD = BaseType->getAsRecordDecl(); 9209 Layout.append(RD->field_begin(), RD->field_end()); 9210 } 9211 } 9212 for (auto &Pair : OverlappedData) { 9213 llvm::stable_sort( 9214 Pair.getSecond(), 9215 [&Layout]( 9216 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 9217 OMPClauseMappableExprCommon::MappableExprComponentListRef 9218 Second) { 9219 auto CI = First.rbegin(); 9220 auto CE = First.rend(); 9221 auto SI = Second.rbegin(); 9222 auto SE = Second.rend(); 9223 for (; CI != CE && SI != SE; ++CI, ++SI) { 9224 if (CI->getAssociatedExpression()->getStmtClass() != 9225 SI->getAssociatedExpression()->getStmtClass()) 9226 break; 9227 // Are we dealing with different variables/fields? 9228 if (CI->getAssociatedDeclaration() != 9229 SI->getAssociatedDeclaration()) 9230 break; 9231 } 9232 9233 // Lists contain the same elements. 9234 if (CI == CE && SI == SE) 9235 return false; 9236 9237 // List with less elements is less than list with more elements. 9238 if (CI == CE || SI == SE) 9239 return CI == CE; 9240 9241 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 9242 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 9243 if (FD1->getParent() == FD2->getParent()) 9244 return FD1->getFieldIndex() < FD2->getFieldIndex(); 9245 const auto *It = 9246 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 9247 return FD == FD1 || FD == FD2; 9248 }); 9249 return *It == FD1; 9250 }); 9251 } 9252 9253 // Associated with a capture, because the mapping flags depend on it. 9254 // Go through all of the elements with the overlapped elements. 9255 bool IsFirstComponentList = true; 9256 for (const auto &Pair : OverlappedData) { 9257 const MapData &L = *Pair.getFirst(); 9258 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9259 OpenMPMapClauseKind MapType; 9260 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9261 bool IsImplicit; 9262 const ValueDecl *Mapper; 9263 const Expr *VarRef; 9264 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9265 L; 9266 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 9267 OverlappedComponents = Pair.getSecond(); 9268 generateInfoForComponentList( 9269 MapType, MapModifiers, llvm::None, Components, CombinedInfo, 9270 PartialStruct, IsFirstComponentList, IsImplicit, Mapper, 9271 /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents); 9272 IsFirstComponentList = false; 9273 } 9274 // Go through other elements without overlapped elements. 9275 for (const MapData &L : DeclComponentLists) { 9276 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 9277 OpenMPMapClauseKind MapType; 9278 ArrayRef<OpenMPMapModifierKind> MapModifiers; 9279 bool IsImplicit; 9280 const ValueDecl *Mapper; 9281 const Expr *VarRef; 9282 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 9283 L; 9284 auto It = OverlappedData.find(&L); 9285 if (It == OverlappedData.end()) 9286 generateInfoForComponentList(MapType, MapModifiers, llvm::None, 9287 Components, CombinedInfo, PartialStruct, 9288 IsFirstComponentList, IsImplicit, Mapper, 9289 /*ForDeviceAddr=*/false, VD, VarRef); 9290 IsFirstComponentList = false; 9291 } 9292 } 9293 9294 /// Generate the default map information for a given capture \a CI, 9295 /// record field declaration \a RI and captured value \a CV. 9296 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 9297 const FieldDecl &RI, llvm::Value *CV, 9298 MapCombinedInfoTy &CombinedInfo) const { 9299 bool IsImplicit = true; 9300 // Do the default mapping. 9301 if (CI.capturesThis()) { 9302 CombinedInfo.Exprs.push_back(nullptr); 9303 CombinedInfo.BasePointers.push_back(CV); 9304 CombinedInfo.Pointers.push_back(CV); 9305 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 9306 CombinedInfo.Sizes.push_back( 9307 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 9308 CGF.Int64Ty, /*isSigned=*/true)); 9309 // Default map type. 9310 CombinedInfo.Types.push_back(OMP_MAP_TO | OMP_MAP_FROM); 9311 } else if (CI.capturesVariableByCopy()) { 9312 const VarDecl *VD = CI.getCapturedVar(); 9313 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9314 CombinedInfo.BasePointers.push_back(CV); 9315 CombinedInfo.Pointers.push_back(CV); 9316 if (!RI.getType()->isAnyPointerType()) { 9317 // We have to signal to the runtime captures passed by value that are 9318 // not pointers. 9319 CombinedInfo.Types.push_back(OMP_MAP_LITERAL); 9320 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9321 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 9322 } else { 9323 // Pointers are implicitly mapped with a zero size and no flags 9324 // (other than first map that is added for all implicit maps). 9325 CombinedInfo.Types.push_back(OMP_MAP_NONE); 9326 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 9327 } 9328 auto I = FirstPrivateDecls.find(VD); 9329 if (I != FirstPrivateDecls.end()) 9330 IsImplicit = I->getSecond(); 9331 } else { 9332 assert(CI.capturesVariable() && "Expected captured reference."); 9333 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 9334 QualType ElementType = PtrTy->getPointeeType(); 9335 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9336 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 9337 // The default map type for a scalar/complex type is 'to' because by 9338 // default the value doesn't have to be retrieved. For an aggregate 9339 // type, the default is 'tofrom'. 9340 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI)); 9341 const VarDecl *VD = CI.getCapturedVar(); 9342 auto I = FirstPrivateDecls.find(VD); 9343 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9344 CombinedInfo.BasePointers.push_back(CV); 9345 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 9346 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 9347 CV, ElementType, CGF.getContext().getDeclAlign(VD), 9348 AlignmentSource::Decl)); 9349 CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); 9350 } else { 9351 CombinedInfo.Pointers.push_back(CV); 9352 } 9353 if (I != FirstPrivateDecls.end()) 9354 IsImplicit = I->getSecond(); 9355 } 9356 // Every default map produces a single argument which is a target parameter. 9357 CombinedInfo.Types.back() |= OMP_MAP_TARGET_PARAM; 9358 9359 // Add flag stating this is an implicit map. 9360 if (IsImplicit) 9361 CombinedInfo.Types.back() |= OMP_MAP_IMPLICIT; 9362 9363 // No user-defined mapper for default mapping. 9364 CombinedInfo.Mappers.push_back(nullptr); 9365 } 9366 }; 9367 } // anonymous namespace 9368 9369 static void emitNonContiguousDescriptor( 9370 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9371 CGOpenMPRuntime::TargetDataInfo &Info) { 9372 CodeGenModule &CGM = CGF.CGM; 9373 MappableExprsHandler::MapCombinedInfoTy::StructNonContiguousInfo 9374 &NonContigInfo = CombinedInfo.NonContigInfo; 9375 9376 // Build an array of struct descriptor_dim and then assign it to 9377 // offload_args. 9378 // 9379 // struct descriptor_dim { 9380 // uint64_t offset; 9381 // uint64_t count; 9382 // uint64_t stride 9383 // }; 9384 ASTContext &C = CGF.getContext(); 9385 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 9386 RecordDecl *RD; 9387 RD = C.buildImplicitRecord("descriptor_dim"); 9388 RD->startDefinition(); 9389 addFieldToRecordDecl(C, RD, Int64Ty); 9390 addFieldToRecordDecl(C, RD, Int64Ty); 9391 addFieldToRecordDecl(C, RD, Int64Ty); 9392 RD->completeDefinition(); 9393 QualType DimTy = C.getRecordType(RD); 9394 9395 enum { OffsetFD = 0, CountFD, StrideFD }; 9396 // We need two index variable here since the size of "Dims" is the same as the 9397 // size of Components, however, the size of offset, count, and stride is equal 9398 // to the size of base declaration that is non-contiguous. 9399 for (unsigned I = 0, L = 0, E = NonContigInfo.Dims.size(); I < E; ++I) { 9400 // Skip emitting ir if dimension size is 1 since it cannot be 9401 // non-contiguous. 9402 if (NonContigInfo.Dims[I] == 1) 9403 continue; 9404 llvm::APInt Size(/*numBits=*/32, NonContigInfo.Dims[I]); 9405 QualType ArrayTy = 9406 C.getConstantArrayType(DimTy, Size, nullptr, ArrayType::Normal, 0); 9407 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 9408 for (unsigned II = 0, EE = NonContigInfo.Dims[I]; II < EE; ++II) { 9409 unsigned RevIdx = EE - II - 1; 9410 LValue DimsLVal = CGF.MakeAddrLValue( 9411 CGF.Builder.CreateConstArrayGEP(DimsAddr, II), DimTy); 9412 // Offset 9413 LValue OffsetLVal = CGF.EmitLValueForField( 9414 DimsLVal, *std::next(RD->field_begin(), OffsetFD)); 9415 CGF.EmitStoreOfScalar(NonContigInfo.Offsets[L][RevIdx], OffsetLVal); 9416 // Count 9417 LValue CountLVal = CGF.EmitLValueForField( 9418 DimsLVal, *std::next(RD->field_begin(), CountFD)); 9419 CGF.EmitStoreOfScalar(NonContigInfo.Counts[L][RevIdx], CountLVal); 9420 // Stride 9421 LValue StrideLVal = CGF.EmitLValueForField( 9422 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 9423 CGF.EmitStoreOfScalar(NonContigInfo.Strides[L][RevIdx], StrideLVal); 9424 } 9425 // args[I] = &dims 9426 Address DAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9427 DimsAddr, CGM.Int8PtrTy); 9428 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9429 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9430 Info.PointersArray, 0, I); 9431 Address PAddr(P, CGF.getPointerAlign()); 9432 CGF.Builder.CreateStore(DAddr.getPointer(), PAddr); 9433 ++L; 9434 } 9435 } 9436 9437 /// Emit a string constant containing the names of the values mapped to the 9438 /// offloading runtime library. 9439 llvm::Constant * 9440 emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, 9441 MappableExprsHandler::MappingExprInfo &MapExprs) { 9442 llvm::Constant *SrcLocStr; 9443 if (!MapExprs.getMapDecl()) { 9444 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(); 9445 } else { 9446 std::string ExprName = ""; 9447 if (MapExprs.getMapExpr()) { 9448 PrintingPolicy P(CGF.getContext().getLangOpts()); 9449 llvm::raw_string_ostream OS(ExprName); 9450 MapExprs.getMapExpr()->printPretty(OS, nullptr, P); 9451 OS.flush(); 9452 } else { 9453 ExprName = MapExprs.getMapDecl()->getNameAsString(); 9454 } 9455 9456 SourceLocation Loc = MapExprs.getMapDecl()->getLocation(); 9457 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 9458 const char *FileName = PLoc.getFilename(); 9459 unsigned Line = PLoc.getLine(); 9460 unsigned Column = PLoc.getColumn(); 9461 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FileName, ExprName.c_str(), 9462 Line, Column); 9463 } 9464 return SrcLocStr; 9465 } 9466 9467 /// Emit the arrays used to pass the captures and map information to the 9468 /// offloading runtime library. If there is no map or capture information, 9469 /// return nullptr by reference. 9470 static void emitOffloadingArrays( 9471 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9472 CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, 9473 bool IsNonContiguous = false) { 9474 CodeGenModule &CGM = CGF.CGM; 9475 ASTContext &Ctx = CGF.getContext(); 9476 9477 // Reset the array information. 9478 Info.clearArrayInfo(); 9479 Info.NumberOfPtrs = CombinedInfo.BasePointers.size(); 9480 9481 if (Info.NumberOfPtrs) { 9482 // Detect if we have any capture size requiring runtime evaluation of the 9483 // size so that a constant array could be eventually used. 9484 bool hasRuntimeEvaluationCaptureSize = false; 9485 for (llvm::Value *S : CombinedInfo.Sizes) 9486 if (!isa<llvm::Constant>(S)) { 9487 hasRuntimeEvaluationCaptureSize = true; 9488 break; 9489 } 9490 9491 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 9492 QualType PointerArrayType = Ctx.getConstantArrayType( 9493 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 9494 /*IndexTypeQuals=*/0); 9495 9496 Info.BasePointersArray = 9497 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 9498 Info.PointersArray = 9499 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 9500 Address MappersArray = 9501 CGF.CreateMemTemp(PointerArrayType, ".offload_mappers"); 9502 Info.MappersArray = MappersArray.getPointer(); 9503 9504 // If we don't have any VLA types or other types that require runtime 9505 // evaluation, we can use a constant array for the map sizes, otherwise we 9506 // need to fill up the arrays as we do for the pointers. 9507 QualType Int64Ty = 9508 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 9509 if (hasRuntimeEvaluationCaptureSize) { 9510 QualType SizeArrayType = Ctx.getConstantArrayType( 9511 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 9512 /*IndexTypeQuals=*/0); 9513 Info.SizesArray = 9514 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 9515 } else { 9516 // We expect all the sizes to be constant, so we collect them to create 9517 // a constant array. 9518 SmallVector<llvm::Constant *, 16> ConstSizes; 9519 for (unsigned I = 0, E = CombinedInfo.Sizes.size(); I < E; ++I) { 9520 if (IsNonContiguous && 9521 (CombinedInfo.Types[I] & MappableExprsHandler::OMP_MAP_NON_CONTIG)) { 9522 ConstSizes.push_back(llvm::ConstantInt::get( 9523 CGF.Int64Ty, CombinedInfo.NonContigInfo.Dims[I])); 9524 } else { 9525 ConstSizes.push_back(cast<llvm::Constant>(CombinedInfo.Sizes[I])); 9526 } 9527 } 9528 9529 auto *SizesArrayInit = llvm::ConstantArray::get( 9530 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 9531 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 9532 auto *SizesArrayGbl = new llvm::GlobalVariable( 9533 CGM.getModule(), SizesArrayInit->getType(), 9534 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 9535 SizesArrayInit, Name); 9536 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 9537 Info.SizesArray = SizesArrayGbl; 9538 } 9539 9540 // The map types are always constant so we don't need to generate code to 9541 // fill arrays. Instead, we create an array constant. 9542 SmallVector<uint64_t, 4> Mapping(CombinedInfo.Types.size(), 0); 9543 llvm::copy(CombinedInfo.Types, Mapping.begin()); 9544 std::string MaptypesName = 9545 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 9546 auto *MapTypesArrayGbl = 9547 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName); 9548 Info.MapTypesArray = MapTypesArrayGbl; 9549 9550 // The information types are only built if there is debug information 9551 // requested. 9552 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) { 9553 Info.MapNamesArray = llvm::Constant::getNullValue( 9554 llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo()); 9555 } else { 9556 auto fillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) { 9557 return emitMappingInformation(CGF, OMPBuilder, MapExpr); 9558 }; 9559 SmallVector<llvm::Constant *, 4> InfoMap(CombinedInfo.Exprs.size()); 9560 llvm::transform(CombinedInfo.Exprs, InfoMap.begin(), fillInfoMap); 9561 std::string MapnamesName = 9562 CGM.getOpenMPRuntime().getName({"offload_mapnames"}); 9563 auto *MapNamesArrayGbl = 9564 OMPBuilder.createOffloadMapnames(InfoMap, MapnamesName); 9565 Info.MapNamesArray = MapNamesArrayGbl; 9566 } 9567 9568 // If there's a present map type modifier, it must not be applied to the end 9569 // of a region, so generate a separate map type array in that case. 9570 if (Info.separateBeginEndCalls()) { 9571 bool EndMapTypesDiffer = false; 9572 for (uint64_t &Type : Mapping) { 9573 if (Type & MappableExprsHandler::OMP_MAP_PRESENT) { 9574 Type &= ~MappableExprsHandler::OMP_MAP_PRESENT; 9575 EndMapTypesDiffer = true; 9576 } 9577 } 9578 if (EndMapTypesDiffer) { 9579 MapTypesArrayGbl = 9580 OMPBuilder.createOffloadMaptypes(Mapping, MaptypesName); 9581 Info.MapTypesArrayEnd = MapTypesArrayGbl; 9582 } 9583 } 9584 9585 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 9586 llvm::Value *BPVal = *CombinedInfo.BasePointers[I]; 9587 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 9588 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9589 Info.BasePointersArray, 0, I); 9590 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9591 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9592 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9593 CGF.Builder.CreateStore(BPVal, BPAddr); 9594 9595 if (Info.requiresDevicePointerInfo()) 9596 if (const ValueDecl *DevVD = 9597 CombinedInfo.BasePointers[I].getDevicePtrDecl()) 9598 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 9599 9600 llvm::Value *PVal = CombinedInfo.Pointers[I]; 9601 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9602 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9603 Info.PointersArray, 0, I); 9604 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9605 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9606 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9607 CGF.Builder.CreateStore(PVal, PAddr); 9608 9609 if (hasRuntimeEvaluationCaptureSize) { 9610 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 9611 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9612 Info.SizesArray, 9613 /*Idx0=*/0, 9614 /*Idx1=*/I); 9615 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 9616 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(CombinedInfo.Sizes[I], 9617 CGM.Int64Ty, 9618 /*isSigned=*/true), 9619 SAddr); 9620 } 9621 9622 // Fill up the mapper array. 9623 llvm::Value *MFunc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 9624 if (CombinedInfo.Mappers[I]) { 9625 MFunc = CGM.getOpenMPRuntime().getOrCreateUserDefinedMapperFunc( 9626 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I])); 9627 MFunc = CGF.Builder.CreatePointerCast(MFunc, CGM.VoidPtrTy); 9628 Info.HasMapper = true; 9629 } 9630 Address MAddr = CGF.Builder.CreateConstArrayGEP(MappersArray, I); 9631 CGF.Builder.CreateStore(MFunc, MAddr); 9632 } 9633 } 9634 9635 if (!IsNonContiguous || CombinedInfo.NonContigInfo.Offsets.empty() || 9636 Info.NumberOfPtrs == 0) 9637 return; 9638 9639 emitNonContiguousDescriptor(CGF, CombinedInfo, Info); 9640 } 9641 9642 namespace { 9643 /// Additional arguments for emitOffloadingArraysArgument function. 9644 struct ArgumentsOptions { 9645 bool ForEndCall = false; 9646 ArgumentsOptions() = default; 9647 ArgumentsOptions(bool ForEndCall) : ForEndCall(ForEndCall) {} 9648 }; 9649 } // namespace 9650 9651 /// Emit the arguments to be passed to the runtime library based on the 9652 /// arrays of base pointers, pointers, sizes, map types, and mappers. If 9653 /// ForEndCall, emit map types to be passed for the end of the region instead of 9654 /// the beginning. 9655 static void emitOffloadingArraysArgument( 9656 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 9657 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 9658 llvm::Value *&MapTypesArrayArg, llvm::Value *&MapNamesArrayArg, 9659 llvm::Value *&MappersArrayArg, CGOpenMPRuntime::TargetDataInfo &Info, 9660 const ArgumentsOptions &Options = ArgumentsOptions()) { 9661 assert((!Options.ForEndCall || Info.separateBeginEndCalls()) && 9662 "expected region end call to runtime only when end call is separate"); 9663 CodeGenModule &CGM = CGF.CGM; 9664 if (Info.NumberOfPtrs) { 9665 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9666 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9667 Info.BasePointersArray, 9668 /*Idx0=*/0, /*Idx1=*/0); 9669 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9670 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9671 Info.PointersArray, 9672 /*Idx0=*/0, 9673 /*Idx1=*/0); 9674 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9675 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 9676 /*Idx0=*/0, /*Idx1=*/0); 9677 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9678 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9679 Options.ForEndCall && Info.MapTypesArrayEnd ? Info.MapTypesArrayEnd 9680 : Info.MapTypesArray, 9681 /*Idx0=*/0, 9682 /*Idx1=*/0); 9683 9684 // Only emit the mapper information arrays if debug information is 9685 // requested. 9686 if (CGF.CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 9687 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9688 else 9689 MapNamesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9690 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9691 Info.MapNamesArray, 9692 /*Idx0=*/0, 9693 /*Idx1=*/0); 9694 // If there is no user-defined mapper, set the mapper array to nullptr to 9695 // avoid an unnecessary data privatization 9696 if (!Info.HasMapper) 9697 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9698 else 9699 MappersArrayArg = 9700 CGF.Builder.CreatePointerCast(Info.MappersArray, CGM.VoidPtrPtrTy); 9701 } else { 9702 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9703 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9704 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9705 MapTypesArrayArg = 9706 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9707 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9708 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9709 } 9710 } 9711 9712 /// Check for inner distribute directive. 9713 static const OMPExecutableDirective * 9714 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 9715 const auto *CS = D.getInnermostCapturedStmt(); 9716 const auto *Body = 9717 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 9718 const Stmt *ChildStmt = 9719 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9720 9721 if (const auto *NestedDir = 9722 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9723 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 9724 switch (D.getDirectiveKind()) { 9725 case OMPD_target: 9726 if (isOpenMPDistributeDirective(DKind)) 9727 return NestedDir; 9728 if (DKind == OMPD_teams) { 9729 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 9730 /*IgnoreCaptured=*/true); 9731 if (!Body) 9732 return nullptr; 9733 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9734 if (const auto *NND = 9735 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9736 DKind = NND->getDirectiveKind(); 9737 if (isOpenMPDistributeDirective(DKind)) 9738 return NND; 9739 } 9740 } 9741 return nullptr; 9742 case OMPD_target_teams: 9743 if (isOpenMPDistributeDirective(DKind)) 9744 return NestedDir; 9745 return nullptr; 9746 case OMPD_target_parallel: 9747 case OMPD_target_simd: 9748 case OMPD_target_parallel_for: 9749 case OMPD_target_parallel_for_simd: 9750 return nullptr; 9751 case OMPD_target_teams_distribute: 9752 case OMPD_target_teams_distribute_simd: 9753 case OMPD_target_teams_distribute_parallel_for: 9754 case OMPD_target_teams_distribute_parallel_for_simd: 9755 case OMPD_parallel: 9756 case OMPD_for: 9757 case OMPD_parallel_for: 9758 case OMPD_parallel_master: 9759 case OMPD_parallel_sections: 9760 case OMPD_for_simd: 9761 case OMPD_parallel_for_simd: 9762 case OMPD_cancel: 9763 case OMPD_cancellation_point: 9764 case OMPD_ordered: 9765 case OMPD_threadprivate: 9766 case OMPD_allocate: 9767 case OMPD_task: 9768 case OMPD_simd: 9769 case OMPD_tile: 9770 case OMPD_unroll: 9771 case OMPD_sections: 9772 case OMPD_section: 9773 case OMPD_single: 9774 case OMPD_master: 9775 case OMPD_critical: 9776 case OMPD_taskyield: 9777 case OMPD_barrier: 9778 case OMPD_taskwait: 9779 case OMPD_taskgroup: 9780 case OMPD_atomic: 9781 case OMPD_flush: 9782 case OMPD_depobj: 9783 case OMPD_scan: 9784 case OMPD_teams: 9785 case OMPD_target_data: 9786 case OMPD_target_exit_data: 9787 case OMPD_target_enter_data: 9788 case OMPD_distribute: 9789 case OMPD_distribute_simd: 9790 case OMPD_distribute_parallel_for: 9791 case OMPD_distribute_parallel_for_simd: 9792 case OMPD_teams_distribute: 9793 case OMPD_teams_distribute_simd: 9794 case OMPD_teams_distribute_parallel_for: 9795 case OMPD_teams_distribute_parallel_for_simd: 9796 case OMPD_target_update: 9797 case OMPD_declare_simd: 9798 case OMPD_declare_variant: 9799 case OMPD_begin_declare_variant: 9800 case OMPD_end_declare_variant: 9801 case OMPD_declare_target: 9802 case OMPD_end_declare_target: 9803 case OMPD_declare_reduction: 9804 case OMPD_declare_mapper: 9805 case OMPD_taskloop: 9806 case OMPD_taskloop_simd: 9807 case OMPD_master_taskloop: 9808 case OMPD_master_taskloop_simd: 9809 case OMPD_parallel_master_taskloop: 9810 case OMPD_parallel_master_taskloop_simd: 9811 case OMPD_requires: 9812 case OMPD_unknown: 9813 default: 9814 llvm_unreachable("Unexpected directive."); 9815 } 9816 } 9817 9818 return nullptr; 9819 } 9820 9821 /// Emit the user-defined mapper function. The code generation follows the 9822 /// pattern in the example below. 9823 /// \code 9824 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 9825 /// void *base, void *begin, 9826 /// int64_t size, int64_t type, 9827 /// void *name = nullptr) { 9828 /// // Allocate space for an array section first or add a base/begin for 9829 /// // pointer dereference. 9830 /// if ((size > 1 || (base != begin && maptype.IsPtrAndObj)) && 9831 /// !maptype.IsDelete) 9832 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9833 /// size*sizeof(Ty), clearToFromMember(type)); 9834 /// // Map members. 9835 /// for (unsigned i = 0; i < size; i++) { 9836 /// // For each component specified by this mapper: 9837 /// for (auto c : begin[i]->all_components) { 9838 /// if (c.hasMapper()) 9839 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 9840 /// c.arg_type, c.arg_name); 9841 /// else 9842 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 9843 /// c.arg_begin, c.arg_size, c.arg_type, 9844 /// c.arg_name); 9845 /// } 9846 /// } 9847 /// // Delete the array section. 9848 /// if (size > 1 && maptype.IsDelete) 9849 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9850 /// size*sizeof(Ty), clearToFromMember(type)); 9851 /// } 9852 /// \endcode 9853 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 9854 CodeGenFunction *CGF) { 9855 if (UDMMap.count(D) > 0) 9856 return; 9857 ASTContext &C = CGM.getContext(); 9858 QualType Ty = D->getType(); 9859 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 9860 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 9861 auto *MapperVarDecl = 9862 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 9863 SourceLocation Loc = D->getLocation(); 9864 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 9865 9866 // Prepare mapper function arguments and attributes. 9867 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9868 C.VoidPtrTy, ImplicitParamDecl::Other); 9869 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9870 ImplicitParamDecl::Other); 9871 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9872 C.VoidPtrTy, ImplicitParamDecl::Other); 9873 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9874 ImplicitParamDecl::Other); 9875 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9876 ImplicitParamDecl::Other); 9877 ImplicitParamDecl NameArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9878 ImplicitParamDecl::Other); 9879 FunctionArgList Args; 9880 Args.push_back(&HandleArg); 9881 Args.push_back(&BaseArg); 9882 Args.push_back(&BeginArg); 9883 Args.push_back(&SizeArg); 9884 Args.push_back(&TypeArg); 9885 Args.push_back(&NameArg); 9886 const CGFunctionInfo &FnInfo = 9887 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 9888 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 9889 SmallString<64> TyStr; 9890 llvm::raw_svector_ostream Out(TyStr); 9891 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 9892 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 9893 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 9894 Name, &CGM.getModule()); 9895 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 9896 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 9897 // Start the mapper function code generation. 9898 CodeGenFunction MapperCGF(CGM); 9899 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 9900 // Compute the starting and end addresses of array elements. 9901 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 9902 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 9903 C.getPointerType(Int64Ty), Loc); 9904 // Prepare common arguments for array initiation and deletion. 9905 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 9906 MapperCGF.GetAddrOfLocalVar(&HandleArg), 9907 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9908 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 9909 MapperCGF.GetAddrOfLocalVar(&BaseArg), 9910 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9911 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 9912 MapperCGF.GetAddrOfLocalVar(&BeginArg), 9913 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9914 // Convert the size in bytes into the number of array elements. 9915 Size = MapperCGF.Builder.CreateExactUDiv( 9916 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9917 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 9918 BeginIn, CGM.getTypes().ConvertTypeForMem(PtrTy)); 9919 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP( 9920 PtrBegin->getType()->getPointerElementType(), PtrBegin, Size); 9921 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 9922 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 9923 C.getPointerType(Int64Ty), Loc); 9924 llvm::Value *MapName = MapperCGF.EmitLoadOfScalar( 9925 MapperCGF.GetAddrOfLocalVar(&NameArg), 9926 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9927 9928 // Emit array initiation if this is an array section and \p MapType indicates 9929 // that memory allocation is required. 9930 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 9931 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9932 MapName, ElementSize, HeadBB, /*IsInit=*/true); 9933 9934 // Emit a for loop to iterate through SizeArg of elements and map all of them. 9935 9936 // Emit the loop header block. 9937 MapperCGF.EmitBlock(HeadBB); 9938 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 9939 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 9940 // Evaluate whether the initial condition is satisfied. 9941 llvm::Value *IsEmpty = 9942 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 9943 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 9944 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 9945 9946 // Emit the loop body block. 9947 MapperCGF.EmitBlock(BodyBB); 9948 llvm::BasicBlock *LastBB = BodyBB; 9949 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 9950 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 9951 PtrPHI->addIncoming(PtrBegin, EntryBB); 9952 Address PtrCurrent = 9953 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 9954 .getAlignment() 9955 .alignmentOfArrayElement(ElementSize)); 9956 // Privatize the declared variable of mapper to be the current array element. 9957 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 9958 Scope.addPrivate(MapperVarDecl, [PtrCurrent]() { return PtrCurrent; }); 9959 (void)Scope.Privatize(); 9960 9961 // Get map clause information. Fill up the arrays with all mapped variables. 9962 MappableExprsHandler::MapCombinedInfoTy Info; 9963 MappableExprsHandler MEHandler(*D, MapperCGF); 9964 MEHandler.generateAllInfoForMapper(Info); 9965 9966 // Call the runtime API __tgt_mapper_num_components to get the number of 9967 // pre-existing components. 9968 llvm::Value *OffloadingArgs[] = {Handle}; 9969 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 9970 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 9971 OMPRTL___tgt_mapper_num_components), 9972 OffloadingArgs); 9973 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 9974 PreviousSize, 9975 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 9976 9977 // Fill up the runtime mapper handle for all components. 9978 for (unsigned I = 0; I < Info.BasePointers.size(); ++I) { 9979 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 9980 *Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9981 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9982 Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9983 llvm::Value *CurSizeArg = Info.Sizes[I]; 9984 llvm::Value *CurNameArg = 9985 (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 9986 ? llvm::ConstantPointerNull::get(CGM.VoidPtrTy) 9987 : emitMappingInformation(MapperCGF, OMPBuilder, Info.Exprs[I]); 9988 9989 // Extract the MEMBER_OF field from the map type. 9990 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(Info.Types[I]); 9991 llvm::Value *MemberMapType = 9992 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9993 9994 // Combine the map type inherited from user-defined mapper with that 9995 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9996 // bits of the \a MapType, which is the input argument of the mapper 9997 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9998 // bits of MemberMapType. 9999 // [OpenMP 5.0], 1.2.6. map-type decay. 10000 // | alloc | to | from | tofrom | release | delete 10001 // ---------------------------------------------------------- 10002 // alloc | alloc | alloc | alloc | alloc | release | delete 10003 // to | alloc | to | alloc | to | release | delete 10004 // from | alloc | alloc | from | from | release | delete 10005 // tofrom | alloc | to | from | tofrom | release | delete 10006 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 10007 MapType, 10008 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 10009 MappableExprsHandler::OMP_MAP_FROM)); 10010 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 10011 llvm::BasicBlock *AllocElseBB = 10012 MapperCGF.createBasicBlock("omp.type.alloc.else"); 10013 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 10014 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 10015 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 10016 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 10017 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 10018 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 10019 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 10020 MapperCGF.EmitBlock(AllocBB); 10021 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 10022 MemberMapType, 10023 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 10024 MappableExprsHandler::OMP_MAP_FROM))); 10025 MapperCGF.Builder.CreateBr(EndBB); 10026 MapperCGF.EmitBlock(AllocElseBB); 10027 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 10028 LeftToFrom, 10029 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 10030 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 10031 // In case of to, clear OMP_MAP_FROM. 10032 MapperCGF.EmitBlock(ToBB); 10033 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 10034 MemberMapType, 10035 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 10036 MapperCGF.Builder.CreateBr(EndBB); 10037 MapperCGF.EmitBlock(ToElseBB); 10038 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 10039 LeftToFrom, 10040 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 10041 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 10042 // In case of from, clear OMP_MAP_TO. 10043 MapperCGF.EmitBlock(FromBB); 10044 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 10045 MemberMapType, 10046 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 10047 // In case of tofrom, do nothing. 10048 MapperCGF.EmitBlock(EndBB); 10049 LastBB = EndBB; 10050 llvm::PHINode *CurMapType = 10051 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 10052 CurMapType->addIncoming(AllocMapType, AllocBB); 10053 CurMapType->addIncoming(ToMapType, ToBB); 10054 CurMapType->addIncoming(FromMapType, FromBB); 10055 CurMapType->addIncoming(MemberMapType, ToElseBB); 10056 10057 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 10058 CurSizeArg, CurMapType, CurNameArg}; 10059 if (Info.Mappers[I]) { 10060 // Call the corresponding mapper function. 10061 llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc( 10062 cast<OMPDeclareMapperDecl>(Info.Mappers[I])); 10063 assert(MapperFunc && "Expect a valid mapper function is available."); 10064 MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs); 10065 } else { 10066 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 10067 // data structure. 10068 MapperCGF.EmitRuntimeCall( 10069 OMPBuilder.getOrCreateRuntimeFunction( 10070 CGM.getModule(), OMPRTL___tgt_push_mapper_component), 10071 OffloadingArgs); 10072 } 10073 } 10074 10075 // Update the pointer to point to the next element that needs to be mapped, 10076 // and check whether we have mapped all elements. 10077 llvm::Type *ElemTy = PtrPHI->getType()->getPointerElementType(); 10078 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 10079 ElemTy, PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 10080 PtrPHI->addIncoming(PtrNext, LastBB); 10081 llvm::Value *IsDone = 10082 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 10083 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 10084 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 10085 10086 MapperCGF.EmitBlock(ExitBB); 10087 // Emit array deletion if this is an array section and \p MapType indicates 10088 // that deletion is required. 10089 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 10090 MapName, ElementSize, DoneBB, /*IsInit=*/false); 10091 10092 // Emit the function exit block. 10093 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 10094 MapperCGF.FinishFunction(); 10095 UDMMap.try_emplace(D, Fn); 10096 if (CGF) { 10097 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 10098 Decls.second.push_back(D); 10099 } 10100 } 10101 10102 /// Emit the array initialization or deletion portion for user-defined mapper 10103 /// code generation. First, it evaluates whether an array section is mapped and 10104 /// whether the \a MapType instructs to delete this section. If \a IsInit is 10105 /// true, and \a MapType indicates to not delete this array, array 10106 /// initialization code is generated. If \a IsInit is false, and \a MapType 10107 /// indicates to not this array, array deletion code is generated. 10108 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 10109 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 10110 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 10111 llvm::Value *MapName, CharUnits ElementSize, llvm::BasicBlock *ExitBB, 10112 bool IsInit) { 10113 StringRef Prefix = IsInit ? ".init" : ".del"; 10114 10115 // Evaluate if this is an array section. 10116 llvm::BasicBlock *BodyBB = 10117 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 10118 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGT( 10119 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 10120 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 10121 MapType, 10122 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 10123 llvm::Value *DeleteCond; 10124 llvm::Value *Cond; 10125 if (IsInit) { 10126 // base != begin? 10127 llvm::Value *BaseIsBegin = MapperCGF.Builder.CreateIsNotNull( 10128 MapperCGF.Builder.CreatePtrDiff(Base, Begin)); 10129 // IsPtrAndObj? 10130 llvm::Value *PtrAndObjBit = MapperCGF.Builder.CreateAnd( 10131 MapType, 10132 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_PTR_AND_OBJ)); 10133 PtrAndObjBit = MapperCGF.Builder.CreateIsNotNull(PtrAndObjBit); 10134 BaseIsBegin = MapperCGF.Builder.CreateAnd(BaseIsBegin, PtrAndObjBit); 10135 Cond = MapperCGF.Builder.CreateOr(IsArray, BaseIsBegin); 10136 DeleteCond = MapperCGF.Builder.CreateIsNull( 10137 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 10138 } else { 10139 Cond = IsArray; 10140 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 10141 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 10142 } 10143 Cond = MapperCGF.Builder.CreateAnd(Cond, DeleteCond); 10144 MapperCGF.Builder.CreateCondBr(Cond, BodyBB, ExitBB); 10145 10146 MapperCGF.EmitBlock(BodyBB); 10147 // Get the array size by multiplying element size and element number (i.e., \p 10148 // Size). 10149 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 10150 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 10151 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 10152 // memory allocation/deletion purpose only. 10153 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 10154 MapType, 10155 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 10156 MappableExprsHandler::OMP_MAP_FROM))); 10157 MapTypeArg = MapperCGF.Builder.CreateOr( 10158 MapTypeArg, 10159 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_IMPLICIT)); 10160 10161 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 10162 // data structure. 10163 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, 10164 ArraySize, MapTypeArg, MapName}; 10165 MapperCGF.EmitRuntimeCall( 10166 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 10167 OMPRTL___tgt_push_mapper_component), 10168 OffloadingArgs); 10169 } 10170 10171 llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc( 10172 const OMPDeclareMapperDecl *D) { 10173 auto I = UDMMap.find(D); 10174 if (I != UDMMap.end()) 10175 return I->second; 10176 emitUserDefinedMapper(D); 10177 return UDMMap.lookup(D); 10178 } 10179 10180 void CGOpenMPRuntime::emitTargetNumIterationsCall( 10181 CodeGenFunction &CGF, const OMPExecutableDirective &D, 10182 llvm::Value *DeviceID, 10183 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 10184 const OMPLoopDirective &D)> 10185 SizeEmitter) { 10186 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 10187 const OMPExecutableDirective *TD = &D; 10188 // Get nested teams distribute kind directive, if any. 10189 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 10190 TD = getNestedDistributeDirective(CGM.getContext(), D); 10191 if (!TD) 10192 return; 10193 const auto *LD = cast<OMPLoopDirective>(TD); 10194 auto &&CodeGen = [LD, DeviceID, SizeEmitter, &D, this](CodeGenFunction &CGF, 10195 PrePostActionTy &) { 10196 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 10197 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10198 llvm::Value *Args[] = {RTLoc, DeviceID, NumIterations}; 10199 CGF.EmitRuntimeCall( 10200 OMPBuilder.getOrCreateRuntimeFunction( 10201 CGM.getModule(), OMPRTL___kmpc_push_target_tripcount_mapper), 10202 Args); 10203 } 10204 }; 10205 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 10206 } 10207 10208 void CGOpenMPRuntime::emitTargetCall( 10209 CodeGenFunction &CGF, const OMPExecutableDirective &D, 10210 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 10211 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 10212 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 10213 const OMPLoopDirective &D)> 10214 SizeEmitter) { 10215 if (!CGF.HaveInsertPoint()) 10216 return; 10217 10218 assert(OutlinedFn && "Invalid outlined function!"); 10219 10220 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 10221 D.hasClausesOfKind<OMPNowaitClause>(); 10222 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 10223 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 10224 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 10225 PrePostActionTy &) { 10226 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10227 }; 10228 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 10229 10230 CodeGenFunction::OMPTargetDataInfo InputInfo; 10231 llvm::Value *MapTypesArray = nullptr; 10232 llvm::Value *MapNamesArray = nullptr; 10233 // Fill up the pointer arrays and transfer execution to the device. 10234 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 10235 &MapTypesArray, &MapNamesArray, &CS, RequiresOuterTask, 10236 &CapturedVars, 10237 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 10238 if (Device.getInt() == OMPC_DEVICE_ancestor) { 10239 // Reverse offloading is not supported, so just execute on the host. 10240 if (RequiresOuterTask) { 10241 CapturedVars.clear(); 10242 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10243 } 10244 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10245 return; 10246 } 10247 10248 // On top of the arrays that were filled up, the target offloading call 10249 // takes as arguments the device id as well as the host pointer. The host 10250 // pointer is used by the runtime library to identify the current target 10251 // region, so it only has to be unique and not necessarily point to 10252 // anything. It could be the pointer to the outlined function that 10253 // implements the target region, but we aren't using that so that the 10254 // compiler doesn't need to keep that, and could therefore inline the host 10255 // function if proven worthwhile during optimization. 10256 10257 // From this point on, we need to have an ID of the target region defined. 10258 assert(OutlinedFnID && "Invalid outlined function ID!"); 10259 10260 // Emit device ID if any. 10261 llvm::Value *DeviceID; 10262 if (Device.getPointer()) { 10263 assert((Device.getInt() == OMPC_DEVICE_unknown || 10264 Device.getInt() == OMPC_DEVICE_device_num) && 10265 "Expected device_num modifier."); 10266 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer()); 10267 DeviceID = 10268 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true); 10269 } else { 10270 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10271 } 10272 10273 // Emit the number of elements in the offloading arrays. 10274 llvm::Value *PointerNum = 10275 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10276 10277 // Return value of the runtime offloading call. 10278 llvm::Value *Return; 10279 10280 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 10281 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 10282 10283 // Source location for the ident struct 10284 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10285 10286 // Emit tripcount for the target loop-based directive. 10287 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 10288 10289 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10290 // The target region is an outlined function launched by the runtime 10291 // via calls __tgt_target() or __tgt_target_teams(). 10292 // 10293 // __tgt_target() launches a target region with one team and one thread, 10294 // executing a serial region. This master thread may in turn launch 10295 // more threads within its team upon encountering a parallel region, 10296 // however, no additional teams can be launched on the device. 10297 // 10298 // __tgt_target_teams() launches a target region with one or more teams, 10299 // each with one or more threads. This call is required for target 10300 // constructs such as: 10301 // 'target teams' 10302 // 'target' / 'teams' 10303 // 'target teams distribute parallel for' 10304 // 'target parallel' 10305 // and so on. 10306 // 10307 // Note that on the host and CPU targets, the runtime implementation of 10308 // these calls simply call the outlined function without forking threads. 10309 // The outlined functions themselves have runtime calls to 10310 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 10311 // the compiler in emitTeamsCall() and emitParallelCall(). 10312 // 10313 // In contrast, on the NVPTX target, the implementation of 10314 // __tgt_target_teams() launches a GPU kernel with the requested number 10315 // of teams and threads so no additional calls to the runtime are required. 10316 if (NumTeams) { 10317 // If we have NumTeams defined this means that we have an enclosed teams 10318 // region. Therefore we also expect to have NumThreads defined. These two 10319 // values should be defined in the presence of a teams directive, 10320 // regardless of having any clauses associated. If the user is using teams 10321 // but no clauses, these two values will be the default that should be 10322 // passed to the runtime library - a 32-bit integer with the value zero. 10323 assert(NumThreads && "Thread limit expression should be available along " 10324 "with number of teams."); 10325 SmallVector<llvm::Value *> OffloadingArgs = { 10326 RTLoc, 10327 DeviceID, 10328 OutlinedFnID, 10329 PointerNum, 10330 InputInfo.BasePointersArray.getPointer(), 10331 InputInfo.PointersArray.getPointer(), 10332 InputInfo.SizesArray.getPointer(), 10333 MapTypesArray, 10334 MapNamesArray, 10335 InputInfo.MappersArray.getPointer(), 10336 NumTeams, 10337 NumThreads}; 10338 if (HasNowait) { 10339 // Add int32_t depNum = 0, void *depList = nullptr, int32_t 10340 // noAliasDepNum = 0, void *noAliasDepList = nullptr. 10341 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10342 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10343 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10344 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10345 } 10346 Return = CGF.EmitRuntimeCall( 10347 OMPBuilder.getOrCreateRuntimeFunction( 10348 CGM.getModule(), HasNowait 10349 ? OMPRTL___tgt_target_teams_nowait_mapper 10350 : OMPRTL___tgt_target_teams_mapper), 10351 OffloadingArgs); 10352 } else { 10353 SmallVector<llvm::Value *> OffloadingArgs = { 10354 RTLoc, 10355 DeviceID, 10356 OutlinedFnID, 10357 PointerNum, 10358 InputInfo.BasePointersArray.getPointer(), 10359 InputInfo.PointersArray.getPointer(), 10360 InputInfo.SizesArray.getPointer(), 10361 MapTypesArray, 10362 MapNamesArray, 10363 InputInfo.MappersArray.getPointer()}; 10364 if (HasNowait) { 10365 // Add int32_t depNum = 0, void *depList = nullptr, int32_t 10366 // noAliasDepNum = 0, void *noAliasDepList = nullptr. 10367 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10368 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10369 OffloadingArgs.push_back(CGF.Builder.getInt32(0)); 10370 OffloadingArgs.push_back(llvm::ConstantPointerNull::get(CGM.VoidPtrTy)); 10371 } 10372 Return = CGF.EmitRuntimeCall( 10373 OMPBuilder.getOrCreateRuntimeFunction( 10374 CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper 10375 : OMPRTL___tgt_target_mapper), 10376 OffloadingArgs); 10377 } 10378 10379 // Check the error code and execute the host version if required. 10380 llvm::BasicBlock *OffloadFailedBlock = 10381 CGF.createBasicBlock("omp_offload.failed"); 10382 llvm::BasicBlock *OffloadContBlock = 10383 CGF.createBasicBlock("omp_offload.cont"); 10384 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 10385 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 10386 10387 CGF.EmitBlock(OffloadFailedBlock); 10388 if (RequiresOuterTask) { 10389 CapturedVars.clear(); 10390 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10391 } 10392 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10393 CGF.EmitBranch(OffloadContBlock); 10394 10395 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 10396 }; 10397 10398 // Notify that the host version must be executed. 10399 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 10400 RequiresOuterTask](CodeGenFunction &CGF, 10401 PrePostActionTy &) { 10402 if (RequiresOuterTask) { 10403 CapturedVars.clear(); 10404 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10405 } 10406 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10407 }; 10408 10409 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 10410 &MapNamesArray, &CapturedVars, RequiresOuterTask, 10411 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 10412 // Fill up the arrays with all the captured variables. 10413 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 10414 10415 // Get mappable expression information. 10416 MappableExprsHandler MEHandler(D, CGF); 10417 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 10418 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet; 10419 10420 auto RI = CS.getCapturedRecordDecl()->field_begin(); 10421 auto *CV = CapturedVars.begin(); 10422 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 10423 CE = CS.capture_end(); 10424 CI != CE; ++CI, ++RI, ++CV) { 10425 MappableExprsHandler::MapCombinedInfoTy CurInfo; 10426 MappableExprsHandler::StructRangeInfoTy PartialStruct; 10427 10428 // VLA sizes are passed to the outlined region by copy and do not have map 10429 // information associated. 10430 if (CI->capturesVariableArrayType()) { 10431 CurInfo.Exprs.push_back(nullptr); 10432 CurInfo.BasePointers.push_back(*CV); 10433 CurInfo.Pointers.push_back(*CV); 10434 CurInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 10435 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 10436 // Copy to the device as an argument. No need to retrieve it. 10437 CurInfo.Types.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 10438 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 10439 MappableExprsHandler::OMP_MAP_IMPLICIT); 10440 CurInfo.Mappers.push_back(nullptr); 10441 } else { 10442 // If we have any information in the map clause, we use it, otherwise we 10443 // just do a default mapping. 10444 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct); 10445 if (!CI->capturesThis()) 10446 MappedVarSet.insert(CI->getCapturedVar()); 10447 else 10448 MappedVarSet.insert(nullptr); 10449 if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid()) 10450 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo); 10451 // Generate correct mapping for variables captured by reference in 10452 // lambdas. 10453 if (CI->capturesVariable()) 10454 MEHandler.generateInfoForLambdaCaptures(CI->getCapturedVar(), *CV, 10455 CurInfo, LambdaPointers); 10456 } 10457 // We expect to have at least an element of information for this capture. 10458 assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) && 10459 "Non-existing map pointer for capture!"); 10460 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() && 10461 CurInfo.BasePointers.size() == CurInfo.Sizes.size() && 10462 CurInfo.BasePointers.size() == CurInfo.Types.size() && 10463 CurInfo.BasePointers.size() == CurInfo.Mappers.size() && 10464 "Inconsistent map information sizes!"); 10465 10466 // If there is an entry in PartialStruct it means we have a struct with 10467 // individual members mapped. Emit an extra combined entry. 10468 if (PartialStruct.Base.isValid()) { 10469 CombinedInfo.append(PartialStruct.PreliminaryMapData); 10470 MEHandler.emitCombinedEntry( 10471 CombinedInfo, CurInfo.Types, PartialStruct, nullptr, 10472 !PartialStruct.PreliminaryMapData.BasePointers.empty()); 10473 } 10474 10475 // We need to append the results of this capture to what we already have. 10476 CombinedInfo.append(CurInfo); 10477 } 10478 // Adjust MEMBER_OF flags for the lambdas captures. 10479 MEHandler.adjustMemberOfForLambdaCaptures( 10480 LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers, 10481 CombinedInfo.Types); 10482 // Map any list items in a map clause that were not captures because they 10483 // weren't referenced within the construct. 10484 MEHandler.generateAllInfo(CombinedInfo, MappedVarSet); 10485 10486 TargetDataInfo Info; 10487 // Fill up the arrays and create the arguments. 10488 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder); 10489 emitOffloadingArraysArgument( 10490 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 10491 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 10492 {/*ForEndTask=*/false}); 10493 10494 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10495 InputInfo.BasePointersArray = 10496 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10497 InputInfo.PointersArray = 10498 Address(Info.PointersArray, CGM.getPointerAlign()); 10499 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 10500 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 10501 MapTypesArray = Info.MapTypesArray; 10502 MapNamesArray = Info.MapNamesArray; 10503 if (RequiresOuterTask) 10504 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10505 else 10506 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10507 }; 10508 10509 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 10510 CodeGenFunction &CGF, PrePostActionTy &) { 10511 if (RequiresOuterTask) { 10512 CodeGenFunction::OMPTargetDataInfo InputInfo; 10513 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 10514 } else { 10515 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 10516 } 10517 }; 10518 10519 // If we have a target function ID it means that we need to support 10520 // offloading, otherwise, just execute on the host. We need to execute on host 10521 // regardless of the conditional in the if clause if, e.g., the user do not 10522 // specify target triples. 10523 if (OutlinedFnID) { 10524 if (IfCond) { 10525 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 10526 } else { 10527 RegionCodeGenTy ThenRCG(TargetThenGen); 10528 ThenRCG(CGF); 10529 } 10530 } else { 10531 RegionCodeGenTy ElseRCG(TargetElseGen); 10532 ElseRCG(CGF); 10533 } 10534 } 10535 10536 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 10537 StringRef ParentName) { 10538 if (!S) 10539 return; 10540 10541 // Codegen OMP target directives that offload compute to the device. 10542 bool RequiresDeviceCodegen = 10543 isa<OMPExecutableDirective>(S) && 10544 isOpenMPTargetExecutionDirective( 10545 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 10546 10547 if (RequiresDeviceCodegen) { 10548 const auto &E = *cast<OMPExecutableDirective>(S); 10549 unsigned DeviceID; 10550 unsigned FileID; 10551 unsigned Line; 10552 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 10553 FileID, Line); 10554 10555 // Is this a target region that should not be emitted as an entry point? If 10556 // so just signal we are done with this target region. 10557 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 10558 ParentName, Line)) 10559 return; 10560 10561 switch (E.getDirectiveKind()) { 10562 case OMPD_target: 10563 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 10564 cast<OMPTargetDirective>(E)); 10565 break; 10566 case OMPD_target_parallel: 10567 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 10568 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 10569 break; 10570 case OMPD_target_teams: 10571 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 10572 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 10573 break; 10574 case OMPD_target_teams_distribute: 10575 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 10576 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 10577 break; 10578 case OMPD_target_teams_distribute_simd: 10579 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 10580 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 10581 break; 10582 case OMPD_target_parallel_for: 10583 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 10584 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 10585 break; 10586 case OMPD_target_parallel_for_simd: 10587 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 10588 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 10589 break; 10590 case OMPD_target_simd: 10591 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 10592 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 10593 break; 10594 case OMPD_target_teams_distribute_parallel_for: 10595 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 10596 CGM, ParentName, 10597 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 10598 break; 10599 case OMPD_target_teams_distribute_parallel_for_simd: 10600 CodeGenFunction:: 10601 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 10602 CGM, ParentName, 10603 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 10604 break; 10605 case OMPD_parallel: 10606 case OMPD_for: 10607 case OMPD_parallel_for: 10608 case OMPD_parallel_master: 10609 case OMPD_parallel_sections: 10610 case OMPD_for_simd: 10611 case OMPD_parallel_for_simd: 10612 case OMPD_cancel: 10613 case OMPD_cancellation_point: 10614 case OMPD_ordered: 10615 case OMPD_threadprivate: 10616 case OMPD_allocate: 10617 case OMPD_task: 10618 case OMPD_simd: 10619 case OMPD_tile: 10620 case OMPD_unroll: 10621 case OMPD_sections: 10622 case OMPD_section: 10623 case OMPD_single: 10624 case OMPD_master: 10625 case OMPD_critical: 10626 case OMPD_taskyield: 10627 case OMPD_barrier: 10628 case OMPD_taskwait: 10629 case OMPD_taskgroup: 10630 case OMPD_atomic: 10631 case OMPD_flush: 10632 case OMPD_depobj: 10633 case OMPD_scan: 10634 case OMPD_teams: 10635 case OMPD_target_data: 10636 case OMPD_target_exit_data: 10637 case OMPD_target_enter_data: 10638 case OMPD_distribute: 10639 case OMPD_distribute_simd: 10640 case OMPD_distribute_parallel_for: 10641 case OMPD_distribute_parallel_for_simd: 10642 case OMPD_teams_distribute: 10643 case OMPD_teams_distribute_simd: 10644 case OMPD_teams_distribute_parallel_for: 10645 case OMPD_teams_distribute_parallel_for_simd: 10646 case OMPD_target_update: 10647 case OMPD_declare_simd: 10648 case OMPD_declare_variant: 10649 case OMPD_begin_declare_variant: 10650 case OMPD_end_declare_variant: 10651 case OMPD_declare_target: 10652 case OMPD_end_declare_target: 10653 case OMPD_declare_reduction: 10654 case OMPD_declare_mapper: 10655 case OMPD_taskloop: 10656 case OMPD_taskloop_simd: 10657 case OMPD_master_taskloop: 10658 case OMPD_master_taskloop_simd: 10659 case OMPD_parallel_master_taskloop: 10660 case OMPD_parallel_master_taskloop_simd: 10661 case OMPD_requires: 10662 case OMPD_unknown: 10663 default: 10664 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 10665 } 10666 return; 10667 } 10668 10669 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 10670 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 10671 return; 10672 10673 scanForTargetRegionsFunctions(E->getRawStmt(), ParentName); 10674 return; 10675 } 10676 10677 // If this is a lambda function, look into its body. 10678 if (const auto *L = dyn_cast<LambdaExpr>(S)) 10679 S = L->getBody(); 10680 10681 // Keep looking for target regions recursively. 10682 for (const Stmt *II : S->children()) 10683 scanForTargetRegionsFunctions(II, ParentName); 10684 } 10685 10686 static bool isAssumedToBeNotEmitted(const ValueDecl *VD, bool IsDevice) { 10687 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10688 OMPDeclareTargetDeclAttr::getDeviceType(VD); 10689 if (!DevTy) 10690 return false; 10691 // Do not emit device_type(nohost) functions for the host. 10692 if (!IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 10693 return true; 10694 // Do not emit device_type(host) functions for the device. 10695 if (IsDevice && DevTy == OMPDeclareTargetDeclAttr::DT_Host) 10696 return true; 10697 return false; 10698 } 10699 10700 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 10701 // If emitting code for the host, we do not process FD here. Instead we do 10702 // the normal code generation. 10703 if (!CGM.getLangOpts().OpenMPIsDevice) { 10704 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) 10705 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD), 10706 CGM.getLangOpts().OpenMPIsDevice)) 10707 return true; 10708 return false; 10709 } 10710 10711 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 10712 // Try to detect target regions in the function. 10713 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 10714 StringRef Name = CGM.getMangledName(GD); 10715 scanForTargetRegionsFunctions(FD->getBody(), Name); 10716 if (isAssumedToBeNotEmitted(cast<ValueDecl>(FD), 10717 CGM.getLangOpts().OpenMPIsDevice)) 10718 return true; 10719 } 10720 10721 // Do not to emit function if it is not marked as declare target. 10722 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 10723 AlreadyEmittedTargetDecls.count(VD) == 0; 10724 } 10725 10726 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 10727 if (isAssumedToBeNotEmitted(cast<ValueDecl>(GD.getDecl()), 10728 CGM.getLangOpts().OpenMPIsDevice)) 10729 return true; 10730 10731 if (!CGM.getLangOpts().OpenMPIsDevice) 10732 return false; 10733 10734 // Check if there are Ctors/Dtors in this declaration and look for target 10735 // regions in it. We use the complete variant to produce the kernel name 10736 // mangling. 10737 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 10738 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 10739 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 10740 StringRef ParentName = 10741 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 10742 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 10743 } 10744 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 10745 StringRef ParentName = 10746 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 10747 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 10748 } 10749 } 10750 10751 // Do not to emit variable if it is not marked as declare target. 10752 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10753 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 10754 cast<VarDecl>(GD.getDecl())); 10755 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 10756 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10757 HasRequiresUnifiedSharedMemory)) { 10758 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 10759 return true; 10760 } 10761 return false; 10762 } 10763 10764 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 10765 llvm::Constant *Addr) { 10766 if (CGM.getLangOpts().OMPTargetTriples.empty() && 10767 !CGM.getLangOpts().OpenMPIsDevice) 10768 return; 10769 10770 // If we have host/nohost variables, they do not need to be registered. 10771 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10772 OMPDeclareTargetDeclAttr::getDeviceType(VD); 10773 if (DevTy && DevTy.getValue() != OMPDeclareTargetDeclAttr::DT_Any) 10774 return; 10775 10776 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10777 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10778 if (!Res) { 10779 if (CGM.getLangOpts().OpenMPIsDevice) { 10780 // Register non-target variables being emitted in device code (debug info 10781 // may cause this). 10782 StringRef VarName = CGM.getMangledName(VD); 10783 EmittedNonTargetVariables.try_emplace(VarName, Addr); 10784 } 10785 return; 10786 } 10787 // Register declare target variables. 10788 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 10789 StringRef VarName; 10790 CharUnits VarSize; 10791 llvm::GlobalValue::LinkageTypes Linkage; 10792 10793 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10794 !HasRequiresUnifiedSharedMemory) { 10795 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10796 VarName = CGM.getMangledName(VD); 10797 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 10798 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 10799 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 10800 } else { 10801 VarSize = CharUnits::Zero(); 10802 } 10803 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 10804 // Temp solution to prevent optimizations of the internal variables. 10805 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 10806 // Do not create a "ref-variable" if the original is not also available 10807 // on the host. 10808 if (!OffloadEntriesInfoManager.hasDeviceGlobalVarEntryInfo(VarName)) 10809 return; 10810 std::string RefName = getName({VarName, "ref"}); 10811 if (!CGM.GetGlobalValue(RefName)) { 10812 llvm::Constant *AddrRef = 10813 getOrCreateInternalVariable(Addr->getType(), RefName); 10814 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 10815 GVAddrRef->setConstant(/*Val=*/true); 10816 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 10817 GVAddrRef->setInitializer(Addr); 10818 CGM.addCompilerUsedGlobal(GVAddrRef); 10819 } 10820 } 10821 } else { 10822 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 10823 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10824 HasRequiresUnifiedSharedMemory)) && 10825 "Declare target attribute must link or to with unified memory."); 10826 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 10827 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 10828 else 10829 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10830 10831 if (CGM.getLangOpts().OpenMPIsDevice) { 10832 VarName = Addr->getName(); 10833 Addr = nullptr; 10834 } else { 10835 VarName = getAddrOfDeclareTargetVar(VD).getName(); 10836 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 10837 } 10838 VarSize = CGM.getPointerSize(); 10839 Linkage = llvm::GlobalValue::WeakAnyLinkage; 10840 } 10841 10842 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10843 VarName, Addr, VarSize, Flags, Linkage); 10844 } 10845 10846 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 10847 if (isa<FunctionDecl>(GD.getDecl()) || 10848 isa<OMPDeclareReductionDecl>(GD.getDecl())) 10849 return emitTargetFunctions(GD); 10850 10851 return emitTargetGlobalVariable(GD); 10852 } 10853 10854 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 10855 for (const VarDecl *VD : DeferredGlobalVariables) { 10856 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10857 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10858 if (!Res) 10859 continue; 10860 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10861 !HasRequiresUnifiedSharedMemory) { 10862 CGM.EmitGlobal(VD); 10863 } else { 10864 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 10865 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10866 HasRequiresUnifiedSharedMemory)) && 10867 "Expected link clause or to clause with unified memory."); 10868 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 10869 } 10870 } 10871 } 10872 10873 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 10874 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 10875 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 10876 " Expected target-based directive."); 10877 } 10878 10879 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 10880 for (const OMPClause *Clause : D->clauselists()) { 10881 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 10882 HasRequiresUnifiedSharedMemory = true; 10883 } else if (const auto *AC = 10884 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 10885 switch (AC->getAtomicDefaultMemOrderKind()) { 10886 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 10887 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 10888 break; 10889 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 10890 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 10891 break; 10892 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 10893 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 10894 break; 10895 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 10896 break; 10897 } 10898 } 10899 } 10900 } 10901 10902 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 10903 return RequiresAtomicOrdering; 10904 } 10905 10906 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 10907 LangAS &AS) { 10908 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 10909 return false; 10910 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 10911 switch(A->getAllocatorType()) { 10912 case OMPAllocateDeclAttr::OMPNullMemAlloc: 10913 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 10914 // Not supported, fallback to the default mem space. 10915 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 10916 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 10917 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 10918 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 10919 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 10920 case OMPAllocateDeclAttr::OMPConstMemAlloc: 10921 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 10922 AS = LangAS::Default; 10923 return true; 10924 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 10925 llvm_unreachable("Expected predefined allocator for the variables with the " 10926 "static storage."); 10927 } 10928 return false; 10929 } 10930 10931 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 10932 return HasRequiresUnifiedSharedMemory; 10933 } 10934 10935 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 10936 CodeGenModule &CGM) 10937 : CGM(CGM) { 10938 if (CGM.getLangOpts().OpenMPIsDevice) { 10939 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 10940 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 10941 } 10942 } 10943 10944 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 10945 if (CGM.getLangOpts().OpenMPIsDevice) 10946 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 10947 } 10948 10949 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 10950 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 10951 return true; 10952 10953 const auto *D = cast<FunctionDecl>(GD.getDecl()); 10954 // Do not to emit function if it is marked as declare target as it was already 10955 // emitted. 10956 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 10957 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 10958 if (auto *F = dyn_cast_or_null<llvm::Function>( 10959 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 10960 return !F->isDeclaration(); 10961 return false; 10962 } 10963 return true; 10964 } 10965 10966 return !AlreadyEmittedTargetDecls.insert(D).second; 10967 } 10968 10969 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 10970 // If we don't have entries or if we are emitting code for the device, we 10971 // don't need to do anything. 10972 if (CGM.getLangOpts().OMPTargetTriples.empty() || 10973 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 10974 (OffloadEntriesInfoManager.empty() && 10975 !HasEmittedDeclareTargetRegion && 10976 !HasEmittedTargetRegion)) 10977 return nullptr; 10978 10979 // Create and register the function that handles the requires directives. 10980 ASTContext &C = CGM.getContext(); 10981 10982 llvm::Function *RequiresRegFn; 10983 { 10984 CodeGenFunction CGF(CGM); 10985 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 10986 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 10987 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 10988 RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI); 10989 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 10990 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 10991 // TODO: check for other requires clauses. 10992 // The requires directive takes effect only when a target region is 10993 // present in the compilation unit. Otherwise it is ignored and not 10994 // passed to the runtime. This avoids the runtime from throwing an error 10995 // for mismatching requires clauses across compilation units that don't 10996 // contain at least 1 target region. 10997 assert((HasEmittedTargetRegion || 10998 HasEmittedDeclareTargetRegion || 10999 !OffloadEntriesInfoManager.empty()) && 11000 "Target or declare target region expected."); 11001 if (HasRequiresUnifiedSharedMemory) 11002 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 11003 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 11004 CGM.getModule(), OMPRTL___tgt_register_requires), 11005 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 11006 CGF.FinishFunction(); 11007 } 11008 return RequiresRegFn; 11009 } 11010 11011 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 11012 const OMPExecutableDirective &D, 11013 SourceLocation Loc, 11014 llvm::Function *OutlinedFn, 11015 ArrayRef<llvm::Value *> CapturedVars) { 11016 if (!CGF.HaveInsertPoint()) 11017 return; 11018 11019 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 11020 CodeGenFunction::RunCleanupsScope Scope(CGF); 11021 11022 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 11023 llvm::Value *Args[] = { 11024 RTLoc, 11025 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 11026 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 11027 llvm::SmallVector<llvm::Value *, 16> RealArgs; 11028 RealArgs.append(std::begin(Args), std::end(Args)); 11029 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 11030 11031 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11032 CGM.getModule(), OMPRTL___kmpc_fork_teams); 11033 CGF.EmitRuntimeCall(RTLFn, RealArgs); 11034 } 11035 11036 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11037 const Expr *NumTeams, 11038 const Expr *ThreadLimit, 11039 SourceLocation Loc) { 11040 if (!CGF.HaveInsertPoint()) 11041 return; 11042 11043 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 11044 11045 llvm::Value *NumTeamsVal = 11046 NumTeams 11047 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 11048 CGF.CGM.Int32Ty, /* isSigned = */ true) 11049 : CGF.Builder.getInt32(0); 11050 11051 llvm::Value *ThreadLimitVal = 11052 ThreadLimit 11053 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 11054 CGF.CGM.Int32Ty, /* isSigned = */ true) 11055 : CGF.Builder.getInt32(0); 11056 11057 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 11058 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 11059 ThreadLimitVal}; 11060 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 11061 CGM.getModule(), OMPRTL___kmpc_push_num_teams), 11062 PushNumTeamsArgs); 11063 } 11064 11065 void CGOpenMPRuntime::emitTargetDataCalls( 11066 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11067 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11068 if (!CGF.HaveInsertPoint()) 11069 return; 11070 11071 // Action used to replace the default codegen action and turn privatization 11072 // off. 11073 PrePostActionTy NoPrivAction; 11074 11075 // Generate the code for the opening of the data environment. Capture all the 11076 // arguments of the runtime call by reference because they are used in the 11077 // closing of the region. 11078 auto &&BeginThenGen = [this, &D, Device, &Info, 11079 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 11080 // Fill up the arrays with all the mapped variables. 11081 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 11082 11083 // Get map clause information. 11084 MappableExprsHandler MEHandler(D, CGF); 11085 MEHandler.generateAllInfo(CombinedInfo); 11086 11087 // Fill up the arrays and create the arguments. 11088 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 11089 /*IsNonContiguous=*/true); 11090 11091 llvm::Value *BasePointersArrayArg = nullptr; 11092 llvm::Value *PointersArrayArg = nullptr; 11093 llvm::Value *SizesArrayArg = nullptr; 11094 llvm::Value *MapTypesArrayArg = nullptr; 11095 llvm::Value *MapNamesArrayArg = nullptr; 11096 llvm::Value *MappersArrayArg = nullptr; 11097 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 11098 SizesArrayArg, MapTypesArrayArg, 11099 MapNamesArrayArg, MappersArrayArg, Info); 11100 11101 // Emit device ID if any. 11102 llvm::Value *DeviceID = nullptr; 11103 if (Device) { 11104 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11105 CGF.Int64Ty, /*isSigned=*/true); 11106 } else { 11107 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11108 } 11109 11110 // Emit the number of elements in the offloading arrays. 11111 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 11112 // 11113 // Source location for the ident struct 11114 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11115 11116 llvm::Value *OffloadingArgs[] = {RTLoc, 11117 DeviceID, 11118 PointerNum, 11119 BasePointersArrayArg, 11120 PointersArrayArg, 11121 SizesArrayArg, 11122 MapTypesArrayArg, 11123 MapNamesArrayArg, 11124 MappersArrayArg}; 11125 CGF.EmitRuntimeCall( 11126 OMPBuilder.getOrCreateRuntimeFunction( 11127 CGM.getModule(), OMPRTL___tgt_target_data_begin_mapper), 11128 OffloadingArgs); 11129 11130 // If device pointer privatization is required, emit the body of the region 11131 // here. It will have to be duplicated: with and without privatization. 11132 if (!Info.CaptureDeviceAddrMap.empty()) 11133 CodeGen(CGF); 11134 }; 11135 11136 // Generate code for the closing of the data region. 11137 auto &&EndThenGen = [this, Device, &Info, &D](CodeGenFunction &CGF, 11138 PrePostActionTy &) { 11139 assert(Info.isValid() && "Invalid data environment closing arguments."); 11140 11141 llvm::Value *BasePointersArrayArg = nullptr; 11142 llvm::Value *PointersArrayArg = nullptr; 11143 llvm::Value *SizesArrayArg = nullptr; 11144 llvm::Value *MapTypesArrayArg = nullptr; 11145 llvm::Value *MapNamesArrayArg = nullptr; 11146 llvm::Value *MappersArrayArg = nullptr; 11147 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 11148 SizesArrayArg, MapTypesArrayArg, 11149 MapNamesArrayArg, MappersArrayArg, Info, 11150 {/*ForEndCall=*/true}); 11151 11152 // Emit device ID if any. 11153 llvm::Value *DeviceID = nullptr; 11154 if (Device) { 11155 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11156 CGF.Int64Ty, /*isSigned=*/true); 11157 } else { 11158 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11159 } 11160 11161 // Emit the number of elements in the offloading arrays. 11162 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 11163 11164 // Source location for the ident struct 11165 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11166 11167 llvm::Value *OffloadingArgs[] = {RTLoc, 11168 DeviceID, 11169 PointerNum, 11170 BasePointersArrayArg, 11171 PointersArrayArg, 11172 SizesArrayArg, 11173 MapTypesArrayArg, 11174 MapNamesArrayArg, 11175 MappersArrayArg}; 11176 CGF.EmitRuntimeCall( 11177 OMPBuilder.getOrCreateRuntimeFunction( 11178 CGM.getModule(), OMPRTL___tgt_target_data_end_mapper), 11179 OffloadingArgs); 11180 }; 11181 11182 // If we need device pointer privatization, we need to emit the body of the 11183 // region with no privatization in the 'else' branch of the conditional. 11184 // Otherwise, we don't have to do anything. 11185 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 11186 PrePostActionTy &) { 11187 if (!Info.CaptureDeviceAddrMap.empty()) { 11188 CodeGen.setAction(NoPrivAction); 11189 CodeGen(CGF); 11190 } 11191 }; 11192 11193 // We don't have to do anything to close the region if the if clause evaluates 11194 // to false. 11195 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 11196 11197 if (IfCond) { 11198 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 11199 } else { 11200 RegionCodeGenTy RCG(BeginThenGen); 11201 RCG(CGF); 11202 } 11203 11204 // If we don't require privatization of device pointers, we emit the body in 11205 // between the runtime calls. This avoids duplicating the body code. 11206 if (Info.CaptureDeviceAddrMap.empty()) { 11207 CodeGen.setAction(NoPrivAction); 11208 CodeGen(CGF); 11209 } 11210 11211 if (IfCond) { 11212 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 11213 } else { 11214 RegionCodeGenTy RCG(EndThenGen); 11215 RCG(CGF); 11216 } 11217 } 11218 11219 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 11220 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11221 const Expr *Device) { 11222 if (!CGF.HaveInsertPoint()) 11223 return; 11224 11225 assert((isa<OMPTargetEnterDataDirective>(D) || 11226 isa<OMPTargetExitDataDirective>(D) || 11227 isa<OMPTargetUpdateDirective>(D)) && 11228 "Expecting either target enter, exit data, or update directives."); 11229 11230 CodeGenFunction::OMPTargetDataInfo InputInfo; 11231 llvm::Value *MapTypesArray = nullptr; 11232 llvm::Value *MapNamesArray = nullptr; 11233 // Generate the code for the opening of the data environment. 11234 auto &&ThenGen = [this, &D, Device, &InputInfo, &MapTypesArray, 11235 &MapNamesArray](CodeGenFunction &CGF, PrePostActionTy &) { 11236 // Emit device ID if any. 11237 llvm::Value *DeviceID = nullptr; 11238 if (Device) { 11239 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 11240 CGF.Int64Ty, /*isSigned=*/true); 11241 } else { 11242 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 11243 } 11244 11245 // Emit the number of elements in the offloading arrays. 11246 llvm::Constant *PointerNum = 11247 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 11248 11249 // Source location for the ident struct 11250 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 11251 11252 llvm::Value *OffloadingArgs[] = {RTLoc, 11253 DeviceID, 11254 PointerNum, 11255 InputInfo.BasePointersArray.getPointer(), 11256 InputInfo.PointersArray.getPointer(), 11257 InputInfo.SizesArray.getPointer(), 11258 MapTypesArray, 11259 MapNamesArray, 11260 InputInfo.MappersArray.getPointer()}; 11261 11262 // Select the right runtime function call for each standalone 11263 // directive. 11264 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 11265 RuntimeFunction RTLFn; 11266 switch (D.getDirectiveKind()) { 11267 case OMPD_target_enter_data: 11268 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper 11269 : OMPRTL___tgt_target_data_begin_mapper; 11270 break; 11271 case OMPD_target_exit_data: 11272 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper 11273 : OMPRTL___tgt_target_data_end_mapper; 11274 break; 11275 case OMPD_target_update: 11276 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper 11277 : OMPRTL___tgt_target_data_update_mapper; 11278 break; 11279 case OMPD_parallel: 11280 case OMPD_for: 11281 case OMPD_parallel_for: 11282 case OMPD_parallel_master: 11283 case OMPD_parallel_sections: 11284 case OMPD_for_simd: 11285 case OMPD_parallel_for_simd: 11286 case OMPD_cancel: 11287 case OMPD_cancellation_point: 11288 case OMPD_ordered: 11289 case OMPD_threadprivate: 11290 case OMPD_allocate: 11291 case OMPD_task: 11292 case OMPD_simd: 11293 case OMPD_tile: 11294 case OMPD_unroll: 11295 case OMPD_sections: 11296 case OMPD_section: 11297 case OMPD_single: 11298 case OMPD_master: 11299 case OMPD_critical: 11300 case OMPD_taskyield: 11301 case OMPD_barrier: 11302 case OMPD_taskwait: 11303 case OMPD_taskgroup: 11304 case OMPD_atomic: 11305 case OMPD_flush: 11306 case OMPD_depobj: 11307 case OMPD_scan: 11308 case OMPD_teams: 11309 case OMPD_target_data: 11310 case OMPD_distribute: 11311 case OMPD_distribute_simd: 11312 case OMPD_distribute_parallel_for: 11313 case OMPD_distribute_parallel_for_simd: 11314 case OMPD_teams_distribute: 11315 case OMPD_teams_distribute_simd: 11316 case OMPD_teams_distribute_parallel_for: 11317 case OMPD_teams_distribute_parallel_for_simd: 11318 case OMPD_declare_simd: 11319 case OMPD_declare_variant: 11320 case OMPD_begin_declare_variant: 11321 case OMPD_end_declare_variant: 11322 case OMPD_declare_target: 11323 case OMPD_end_declare_target: 11324 case OMPD_declare_reduction: 11325 case OMPD_declare_mapper: 11326 case OMPD_taskloop: 11327 case OMPD_taskloop_simd: 11328 case OMPD_master_taskloop: 11329 case OMPD_master_taskloop_simd: 11330 case OMPD_parallel_master_taskloop: 11331 case OMPD_parallel_master_taskloop_simd: 11332 case OMPD_target: 11333 case OMPD_target_simd: 11334 case OMPD_target_teams_distribute: 11335 case OMPD_target_teams_distribute_simd: 11336 case OMPD_target_teams_distribute_parallel_for: 11337 case OMPD_target_teams_distribute_parallel_for_simd: 11338 case OMPD_target_teams: 11339 case OMPD_target_parallel: 11340 case OMPD_target_parallel_for: 11341 case OMPD_target_parallel_for_simd: 11342 case OMPD_requires: 11343 case OMPD_unknown: 11344 default: 11345 llvm_unreachable("Unexpected standalone target data directive."); 11346 break; 11347 } 11348 CGF.EmitRuntimeCall( 11349 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), RTLFn), 11350 OffloadingArgs); 11351 }; 11352 11353 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 11354 &MapNamesArray](CodeGenFunction &CGF, 11355 PrePostActionTy &) { 11356 // Fill up the arrays with all the mapped variables. 11357 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 11358 11359 // Get map clause information. 11360 MappableExprsHandler MEHandler(D, CGF); 11361 MEHandler.generateAllInfo(CombinedInfo); 11362 11363 TargetDataInfo Info; 11364 // Fill up the arrays and create the arguments. 11365 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 11366 /*IsNonContiguous=*/true); 11367 bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 11368 D.hasClausesOfKind<OMPNowaitClause>(); 11369 emitOffloadingArraysArgument( 11370 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 11371 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 11372 {/*ForEndTask=*/false}); 11373 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 11374 InputInfo.BasePointersArray = 11375 Address(Info.BasePointersArray, CGM.getPointerAlign()); 11376 InputInfo.PointersArray = 11377 Address(Info.PointersArray, CGM.getPointerAlign()); 11378 InputInfo.SizesArray = 11379 Address(Info.SizesArray, CGM.getPointerAlign()); 11380 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 11381 MapTypesArray = Info.MapTypesArray; 11382 MapNamesArray = Info.MapNamesArray; 11383 if (RequiresOuterTask) 11384 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 11385 else 11386 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 11387 }; 11388 11389 if (IfCond) { 11390 emitIfClause(CGF, IfCond, TargetThenGen, 11391 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 11392 } else { 11393 RegionCodeGenTy ThenRCG(TargetThenGen); 11394 ThenRCG(CGF); 11395 } 11396 } 11397 11398 namespace { 11399 /// Kind of parameter in a function with 'declare simd' directive. 11400 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 11401 /// Attribute set of the parameter. 11402 struct ParamAttrTy { 11403 ParamKindTy Kind = Vector; 11404 llvm::APSInt StrideOrArg; 11405 llvm::APSInt Alignment; 11406 }; 11407 } // namespace 11408 11409 static unsigned evaluateCDTSize(const FunctionDecl *FD, 11410 ArrayRef<ParamAttrTy> ParamAttrs) { 11411 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 11412 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 11413 // of that clause. The VLEN value must be power of 2. 11414 // In other case the notion of the function`s "characteristic data type" (CDT) 11415 // is used to compute the vector length. 11416 // CDT is defined in the following order: 11417 // a) For non-void function, the CDT is the return type. 11418 // b) If the function has any non-uniform, non-linear parameters, then the 11419 // CDT is the type of the first such parameter. 11420 // c) If the CDT determined by a) or b) above is struct, union, or class 11421 // type which is pass-by-value (except for the type that maps to the 11422 // built-in complex data type), the characteristic data type is int. 11423 // d) If none of the above three cases is applicable, the CDT is int. 11424 // The VLEN is then determined based on the CDT and the size of vector 11425 // register of that ISA for which current vector version is generated. The 11426 // VLEN is computed using the formula below: 11427 // VLEN = sizeof(vector_register) / sizeof(CDT), 11428 // where vector register size specified in section 3.2.1 Registers and the 11429 // Stack Frame of original AMD64 ABI document. 11430 QualType RetType = FD->getReturnType(); 11431 if (RetType.isNull()) 11432 return 0; 11433 ASTContext &C = FD->getASTContext(); 11434 QualType CDT; 11435 if (!RetType.isNull() && !RetType->isVoidType()) { 11436 CDT = RetType; 11437 } else { 11438 unsigned Offset = 0; 11439 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 11440 if (ParamAttrs[Offset].Kind == Vector) 11441 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 11442 ++Offset; 11443 } 11444 if (CDT.isNull()) { 11445 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11446 if (ParamAttrs[I + Offset].Kind == Vector) { 11447 CDT = FD->getParamDecl(I)->getType(); 11448 break; 11449 } 11450 } 11451 } 11452 } 11453 if (CDT.isNull()) 11454 CDT = C.IntTy; 11455 CDT = CDT->getCanonicalTypeUnqualified(); 11456 if (CDT->isRecordType() || CDT->isUnionType()) 11457 CDT = C.IntTy; 11458 return C.getTypeSize(CDT); 11459 } 11460 11461 static void 11462 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 11463 const llvm::APSInt &VLENVal, 11464 ArrayRef<ParamAttrTy> ParamAttrs, 11465 OMPDeclareSimdDeclAttr::BranchStateTy State) { 11466 struct ISADataTy { 11467 char ISA; 11468 unsigned VecRegSize; 11469 }; 11470 ISADataTy ISAData[] = { 11471 { 11472 'b', 128 11473 }, // SSE 11474 { 11475 'c', 256 11476 }, // AVX 11477 { 11478 'd', 256 11479 }, // AVX2 11480 { 11481 'e', 512 11482 }, // AVX512 11483 }; 11484 llvm::SmallVector<char, 2> Masked; 11485 switch (State) { 11486 case OMPDeclareSimdDeclAttr::BS_Undefined: 11487 Masked.push_back('N'); 11488 Masked.push_back('M'); 11489 break; 11490 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11491 Masked.push_back('N'); 11492 break; 11493 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11494 Masked.push_back('M'); 11495 break; 11496 } 11497 for (char Mask : Masked) { 11498 for (const ISADataTy &Data : ISAData) { 11499 SmallString<256> Buffer; 11500 llvm::raw_svector_ostream Out(Buffer); 11501 Out << "_ZGV" << Data.ISA << Mask; 11502 if (!VLENVal) { 11503 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 11504 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 11505 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 11506 } else { 11507 Out << VLENVal; 11508 } 11509 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 11510 switch (ParamAttr.Kind){ 11511 case LinearWithVarStride: 11512 Out << 's' << ParamAttr.StrideOrArg; 11513 break; 11514 case Linear: 11515 Out << 'l'; 11516 if (ParamAttr.StrideOrArg != 1) 11517 Out << ParamAttr.StrideOrArg; 11518 break; 11519 case Uniform: 11520 Out << 'u'; 11521 break; 11522 case Vector: 11523 Out << 'v'; 11524 break; 11525 } 11526 if (!!ParamAttr.Alignment) 11527 Out << 'a' << ParamAttr.Alignment; 11528 } 11529 Out << '_' << Fn->getName(); 11530 Fn->addFnAttr(Out.str()); 11531 } 11532 } 11533 } 11534 11535 // This are the Functions that are needed to mangle the name of the 11536 // vector functions generated by the compiler, according to the rules 11537 // defined in the "Vector Function ABI specifications for AArch64", 11538 // available at 11539 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 11540 11541 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 11542 /// 11543 /// TODO: Need to implement the behavior for reference marked with a 11544 /// var or no linear modifiers (1.b in the section). For this, we 11545 /// need to extend ParamKindTy to support the linear modifiers. 11546 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 11547 QT = QT.getCanonicalType(); 11548 11549 if (QT->isVoidType()) 11550 return false; 11551 11552 if (Kind == ParamKindTy::Uniform) 11553 return false; 11554 11555 if (Kind == ParamKindTy::Linear) 11556 return false; 11557 11558 // TODO: Handle linear references with modifiers 11559 11560 if (Kind == ParamKindTy::LinearWithVarStride) 11561 return false; 11562 11563 return true; 11564 } 11565 11566 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 11567 static bool getAArch64PBV(QualType QT, ASTContext &C) { 11568 QT = QT.getCanonicalType(); 11569 unsigned Size = C.getTypeSize(QT); 11570 11571 // Only scalars and complex within 16 bytes wide set PVB to true. 11572 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 11573 return false; 11574 11575 if (QT->isFloatingType()) 11576 return true; 11577 11578 if (QT->isIntegerType()) 11579 return true; 11580 11581 if (QT->isPointerType()) 11582 return true; 11583 11584 // TODO: Add support for complex types (section 3.1.2, item 2). 11585 11586 return false; 11587 } 11588 11589 /// Computes the lane size (LS) of a return type or of an input parameter, 11590 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 11591 /// TODO: Add support for references, section 3.2.1, item 1. 11592 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 11593 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 11594 QualType PTy = QT.getCanonicalType()->getPointeeType(); 11595 if (getAArch64PBV(PTy, C)) 11596 return C.getTypeSize(PTy); 11597 } 11598 if (getAArch64PBV(QT, C)) 11599 return C.getTypeSize(QT); 11600 11601 return C.getTypeSize(C.getUIntPtrType()); 11602 } 11603 11604 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 11605 // signature of the scalar function, as defined in 3.2.2 of the 11606 // AAVFABI. 11607 static std::tuple<unsigned, unsigned, bool> 11608 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 11609 QualType RetType = FD->getReturnType().getCanonicalType(); 11610 11611 ASTContext &C = FD->getASTContext(); 11612 11613 bool OutputBecomesInput = false; 11614 11615 llvm::SmallVector<unsigned, 8> Sizes; 11616 if (!RetType->isVoidType()) { 11617 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 11618 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 11619 OutputBecomesInput = true; 11620 } 11621 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11622 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 11623 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 11624 } 11625 11626 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 11627 // The LS of a function parameter / return value can only be a power 11628 // of 2, starting from 8 bits, up to 128. 11629 assert(std::all_of(Sizes.begin(), Sizes.end(), 11630 [](unsigned Size) { 11631 return Size == 8 || Size == 16 || Size == 32 || 11632 Size == 64 || Size == 128; 11633 }) && 11634 "Invalid size"); 11635 11636 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 11637 *std::max_element(std::begin(Sizes), std::end(Sizes)), 11638 OutputBecomesInput); 11639 } 11640 11641 /// Mangle the parameter part of the vector function name according to 11642 /// their OpenMP classification. The mangling function is defined in 11643 /// section 3.5 of the AAVFABI. 11644 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 11645 SmallString<256> Buffer; 11646 llvm::raw_svector_ostream Out(Buffer); 11647 for (const auto &ParamAttr : ParamAttrs) { 11648 switch (ParamAttr.Kind) { 11649 case LinearWithVarStride: 11650 Out << "ls" << ParamAttr.StrideOrArg; 11651 break; 11652 case Linear: 11653 Out << 'l'; 11654 // Don't print the step value if it is not present or if it is 11655 // equal to 1. 11656 if (ParamAttr.StrideOrArg != 1) 11657 Out << ParamAttr.StrideOrArg; 11658 break; 11659 case Uniform: 11660 Out << 'u'; 11661 break; 11662 case Vector: 11663 Out << 'v'; 11664 break; 11665 } 11666 11667 if (!!ParamAttr.Alignment) 11668 Out << 'a' << ParamAttr.Alignment; 11669 } 11670 11671 return std::string(Out.str()); 11672 } 11673 11674 // Function used to add the attribute. The parameter `VLEN` is 11675 // templated to allow the use of "x" when targeting scalable functions 11676 // for SVE. 11677 template <typename T> 11678 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 11679 char ISA, StringRef ParSeq, 11680 StringRef MangledName, bool OutputBecomesInput, 11681 llvm::Function *Fn) { 11682 SmallString<256> Buffer; 11683 llvm::raw_svector_ostream Out(Buffer); 11684 Out << Prefix << ISA << LMask << VLEN; 11685 if (OutputBecomesInput) 11686 Out << "v"; 11687 Out << ParSeq << "_" << MangledName; 11688 Fn->addFnAttr(Out.str()); 11689 } 11690 11691 // Helper function to generate the Advanced SIMD names depending on 11692 // the value of the NDS when simdlen is not present. 11693 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 11694 StringRef Prefix, char ISA, 11695 StringRef ParSeq, StringRef MangledName, 11696 bool OutputBecomesInput, 11697 llvm::Function *Fn) { 11698 switch (NDS) { 11699 case 8: 11700 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11701 OutputBecomesInput, Fn); 11702 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 11703 OutputBecomesInput, Fn); 11704 break; 11705 case 16: 11706 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11707 OutputBecomesInput, Fn); 11708 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11709 OutputBecomesInput, Fn); 11710 break; 11711 case 32: 11712 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11713 OutputBecomesInput, Fn); 11714 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11715 OutputBecomesInput, Fn); 11716 break; 11717 case 64: 11718 case 128: 11719 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11720 OutputBecomesInput, Fn); 11721 break; 11722 default: 11723 llvm_unreachable("Scalar type is too wide."); 11724 } 11725 } 11726 11727 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 11728 static void emitAArch64DeclareSimdFunction( 11729 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 11730 ArrayRef<ParamAttrTy> ParamAttrs, 11731 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 11732 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 11733 11734 // Get basic data for building the vector signature. 11735 const auto Data = getNDSWDS(FD, ParamAttrs); 11736 const unsigned NDS = std::get<0>(Data); 11737 const unsigned WDS = std::get<1>(Data); 11738 const bool OutputBecomesInput = std::get<2>(Data); 11739 11740 // Check the values provided via `simdlen` by the user. 11741 // 1. A `simdlen(1)` doesn't produce vector signatures, 11742 if (UserVLEN == 1) { 11743 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11744 DiagnosticsEngine::Warning, 11745 "The clause simdlen(1) has no effect when targeting aarch64."); 11746 CGM.getDiags().Report(SLoc, DiagID); 11747 return; 11748 } 11749 11750 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 11751 // Advanced SIMD output. 11752 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 11753 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11754 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 11755 "power of 2 when targeting Advanced SIMD."); 11756 CGM.getDiags().Report(SLoc, DiagID); 11757 return; 11758 } 11759 11760 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 11761 // limits. 11762 if (ISA == 's' && UserVLEN != 0) { 11763 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 11764 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11765 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 11766 "lanes in the architectural constraints " 11767 "for SVE (min is 128-bit, max is " 11768 "2048-bit, by steps of 128-bit)"); 11769 CGM.getDiags().Report(SLoc, DiagID) << WDS; 11770 return; 11771 } 11772 } 11773 11774 // Sort out parameter sequence. 11775 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 11776 StringRef Prefix = "_ZGV"; 11777 // Generate simdlen from user input (if any). 11778 if (UserVLEN) { 11779 if (ISA == 's') { 11780 // SVE generates only a masked function. 11781 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11782 OutputBecomesInput, Fn); 11783 } else { 11784 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11785 // Advanced SIMD generates one or two functions, depending on 11786 // the `[not]inbranch` clause. 11787 switch (State) { 11788 case OMPDeclareSimdDeclAttr::BS_Undefined: 11789 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11790 OutputBecomesInput, Fn); 11791 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11792 OutputBecomesInput, Fn); 11793 break; 11794 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11795 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11796 OutputBecomesInput, Fn); 11797 break; 11798 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11799 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11800 OutputBecomesInput, Fn); 11801 break; 11802 } 11803 } 11804 } else { 11805 // If no user simdlen is provided, follow the AAVFABI rules for 11806 // generating the vector length. 11807 if (ISA == 's') { 11808 // SVE, section 3.4.1, item 1. 11809 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 11810 OutputBecomesInput, Fn); 11811 } else { 11812 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11813 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 11814 // two vector names depending on the use of the clause 11815 // `[not]inbranch`. 11816 switch (State) { 11817 case OMPDeclareSimdDeclAttr::BS_Undefined: 11818 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11819 OutputBecomesInput, Fn); 11820 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11821 OutputBecomesInput, Fn); 11822 break; 11823 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11824 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11825 OutputBecomesInput, Fn); 11826 break; 11827 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11828 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11829 OutputBecomesInput, Fn); 11830 break; 11831 } 11832 } 11833 } 11834 } 11835 11836 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 11837 llvm::Function *Fn) { 11838 ASTContext &C = CGM.getContext(); 11839 FD = FD->getMostRecentDecl(); 11840 // Map params to their positions in function decl. 11841 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 11842 if (isa<CXXMethodDecl>(FD)) 11843 ParamPositions.try_emplace(FD, 0); 11844 unsigned ParamPos = ParamPositions.size(); 11845 for (const ParmVarDecl *P : FD->parameters()) { 11846 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 11847 ++ParamPos; 11848 } 11849 while (FD) { 11850 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 11851 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 11852 // Mark uniform parameters. 11853 for (const Expr *E : Attr->uniforms()) { 11854 E = E->IgnoreParenImpCasts(); 11855 unsigned Pos; 11856 if (isa<CXXThisExpr>(E)) { 11857 Pos = ParamPositions[FD]; 11858 } else { 11859 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11860 ->getCanonicalDecl(); 11861 Pos = ParamPositions[PVD]; 11862 } 11863 ParamAttrs[Pos].Kind = Uniform; 11864 } 11865 // Get alignment info. 11866 auto NI = Attr->alignments_begin(); 11867 for (const Expr *E : Attr->aligneds()) { 11868 E = E->IgnoreParenImpCasts(); 11869 unsigned Pos; 11870 QualType ParmTy; 11871 if (isa<CXXThisExpr>(E)) { 11872 Pos = ParamPositions[FD]; 11873 ParmTy = E->getType(); 11874 } else { 11875 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11876 ->getCanonicalDecl(); 11877 Pos = ParamPositions[PVD]; 11878 ParmTy = PVD->getType(); 11879 } 11880 ParamAttrs[Pos].Alignment = 11881 (*NI) 11882 ? (*NI)->EvaluateKnownConstInt(C) 11883 : llvm::APSInt::getUnsigned( 11884 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 11885 .getQuantity()); 11886 ++NI; 11887 } 11888 // Mark linear parameters. 11889 auto SI = Attr->steps_begin(); 11890 auto MI = Attr->modifiers_begin(); 11891 for (const Expr *E : Attr->linears()) { 11892 E = E->IgnoreParenImpCasts(); 11893 unsigned Pos; 11894 // Rescaling factor needed to compute the linear parameter 11895 // value in the mangled name. 11896 unsigned PtrRescalingFactor = 1; 11897 if (isa<CXXThisExpr>(E)) { 11898 Pos = ParamPositions[FD]; 11899 } else { 11900 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11901 ->getCanonicalDecl(); 11902 Pos = ParamPositions[PVD]; 11903 if (auto *P = dyn_cast<PointerType>(PVD->getType())) 11904 PtrRescalingFactor = CGM.getContext() 11905 .getTypeSizeInChars(P->getPointeeType()) 11906 .getQuantity(); 11907 } 11908 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 11909 ParamAttr.Kind = Linear; 11910 // Assuming a stride of 1, for `linear` without modifiers. 11911 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1); 11912 if (*SI) { 11913 Expr::EvalResult Result; 11914 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 11915 if (const auto *DRE = 11916 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 11917 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 11918 ParamAttr.Kind = LinearWithVarStride; 11919 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 11920 ParamPositions[StridePVD->getCanonicalDecl()]); 11921 } 11922 } 11923 } else { 11924 ParamAttr.StrideOrArg = Result.Val.getInt(); 11925 } 11926 } 11927 // If we are using a linear clause on a pointer, we need to 11928 // rescale the value of linear_step with the byte size of the 11929 // pointee type. 11930 if (Linear == ParamAttr.Kind) 11931 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor; 11932 ++SI; 11933 ++MI; 11934 } 11935 llvm::APSInt VLENVal; 11936 SourceLocation ExprLoc; 11937 const Expr *VLENExpr = Attr->getSimdlen(); 11938 if (VLENExpr) { 11939 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 11940 ExprLoc = VLENExpr->getExprLoc(); 11941 } 11942 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 11943 if (CGM.getTriple().isX86()) { 11944 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 11945 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 11946 unsigned VLEN = VLENVal.getExtValue(); 11947 StringRef MangledName = Fn->getName(); 11948 if (CGM.getTarget().hasFeature("sve")) 11949 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11950 MangledName, 's', 128, Fn, ExprLoc); 11951 if (CGM.getTarget().hasFeature("neon")) 11952 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11953 MangledName, 'n', 128, Fn, ExprLoc); 11954 } 11955 } 11956 FD = FD->getPreviousDecl(); 11957 } 11958 } 11959 11960 namespace { 11961 /// Cleanup action for doacross support. 11962 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 11963 public: 11964 static const int DoacrossFinArgs = 2; 11965 11966 private: 11967 llvm::FunctionCallee RTLFn; 11968 llvm::Value *Args[DoacrossFinArgs]; 11969 11970 public: 11971 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 11972 ArrayRef<llvm::Value *> CallArgs) 11973 : RTLFn(RTLFn) { 11974 assert(CallArgs.size() == DoacrossFinArgs); 11975 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11976 } 11977 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11978 if (!CGF.HaveInsertPoint()) 11979 return; 11980 CGF.EmitRuntimeCall(RTLFn, Args); 11981 } 11982 }; 11983 } // namespace 11984 11985 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11986 const OMPLoopDirective &D, 11987 ArrayRef<Expr *> NumIterations) { 11988 if (!CGF.HaveInsertPoint()) 11989 return; 11990 11991 ASTContext &C = CGM.getContext(); 11992 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 11993 RecordDecl *RD; 11994 if (KmpDimTy.isNull()) { 11995 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 11996 // kmp_int64 lo; // lower 11997 // kmp_int64 up; // upper 11998 // kmp_int64 st; // stride 11999 // }; 12000 RD = C.buildImplicitRecord("kmp_dim"); 12001 RD->startDefinition(); 12002 addFieldToRecordDecl(C, RD, Int64Ty); 12003 addFieldToRecordDecl(C, RD, Int64Ty); 12004 addFieldToRecordDecl(C, RD, Int64Ty); 12005 RD->completeDefinition(); 12006 KmpDimTy = C.getRecordType(RD); 12007 } else { 12008 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 12009 } 12010 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 12011 QualType ArrayTy = 12012 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 12013 12014 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 12015 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 12016 enum { LowerFD = 0, UpperFD, StrideFD }; 12017 // Fill dims with data. 12018 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 12019 LValue DimsLVal = CGF.MakeAddrLValue( 12020 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 12021 // dims.upper = num_iterations; 12022 LValue UpperLVal = CGF.EmitLValueForField( 12023 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 12024 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 12025 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(), 12026 Int64Ty, NumIterations[I]->getExprLoc()); 12027 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 12028 // dims.stride = 1; 12029 LValue StrideLVal = CGF.EmitLValueForField( 12030 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 12031 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 12032 StrideLVal); 12033 } 12034 12035 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 12036 // kmp_int32 num_dims, struct kmp_dim * dims); 12037 llvm::Value *Args[] = { 12038 emitUpdateLocation(CGF, D.getBeginLoc()), 12039 getThreadID(CGF, D.getBeginLoc()), 12040 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 12041 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12042 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 12043 CGM.VoidPtrTy)}; 12044 12045 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12046 CGM.getModule(), OMPRTL___kmpc_doacross_init); 12047 CGF.EmitRuntimeCall(RTLFn, Args); 12048 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 12049 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 12050 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12051 CGM.getModule(), OMPRTL___kmpc_doacross_fini); 12052 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 12053 llvm::makeArrayRef(FiniArgs)); 12054 } 12055 12056 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12057 const OMPDependClause *C) { 12058 QualType Int64Ty = 12059 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 12060 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 12061 QualType ArrayTy = CGM.getContext().getConstantArrayType( 12062 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 12063 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 12064 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 12065 const Expr *CounterVal = C->getLoopData(I); 12066 assert(CounterVal); 12067 llvm::Value *CntVal = CGF.EmitScalarConversion( 12068 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 12069 CounterVal->getExprLoc()); 12070 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 12071 /*Volatile=*/false, Int64Ty); 12072 } 12073 llvm::Value *Args[] = { 12074 emitUpdateLocation(CGF, C->getBeginLoc()), 12075 getThreadID(CGF, C->getBeginLoc()), 12076 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 12077 llvm::FunctionCallee RTLFn; 12078 if (C->getDependencyKind() == OMPC_DEPEND_source) { 12079 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 12080 OMPRTL___kmpc_doacross_post); 12081 } else { 12082 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 12083 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 12084 OMPRTL___kmpc_doacross_wait); 12085 } 12086 CGF.EmitRuntimeCall(RTLFn, Args); 12087 } 12088 12089 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 12090 llvm::FunctionCallee Callee, 12091 ArrayRef<llvm::Value *> Args) const { 12092 assert(Loc.isValid() && "Outlined function call location must be valid."); 12093 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 12094 12095 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 12096 if (Fn->doesNotThrow()) { 12097 CGF.EmitNounwindRuntimeCall(Fn, Args); 12098 return; 12099 } 12100 } 12101 CGF.EmitRuntimeCall(Callee, Args); 12102 } 12103 12104 void CGOpenMPRuntime::emitOutlinedFunctionCall( 12105 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 12106 ArrayRef<llvm::Value *> Args) const { 12107 emitCall(CGF, Loc, OutlinedFn, Args); 12108 } 12109 12110 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 12111 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 12112 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 12113 HasEmittedDeclareTargetRegion = true; 12114 } 12115 12116 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 12117 const VarDecl *NativeParam, 12118 const VarDecl *TargetParam) const { 12119 return CGF.GetAddrOfLocalVar(NativeParam); 12120 } 12121 12122 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 12123 const VarDecl *VD) { 12124 if (!VD) 12125 return Address::invalid(); 12126 Address UntiedAddr = Address::invalid(); 12127 Address UntiedRealAddr = Address::invalid(); 12128 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 12129 if (It != FunctionToUntiedTaskStackMap.end()) { 12130 const UntiedLocalVarsAddressesMap &UntiedData = 12131 UntiedLocalVarsStack[It->second]; 12132 auto I = UntiedData.find(VD); 12133 if (I != UntiedData.end()) { 12134 UntiedAddr = I->second.first; 12135 UntiedRealAddr = I->second.second; 12136 } 12137 } 12138 const VarDecl *CVD = VD->getCanonicalDecl(); 12139 if (CVD->hasAttr<OMPAllocateDeclAttr>()) { 12140 // Use the default allocation. 12141 if (!isAllocatableDecl(VD)) 12142 return UntiedAddr; 12143 llvm::Value *Size; 12144 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 12145 if (CVD->getType()->isVariablyModifiedType()) { 12146 Size = CGF.getTypeSize(CVD->getType()); 12147 // Align the size: ((size + align - 1) / align) * align 12148 Size = CGF.Builder.CreateNUWAdd( 12149 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 12150 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 12151 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 12152 } else { 12153 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 12154 Size = CGM.getSize(Sz.alignTo(Align)); 12155 } 12156 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 12157 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 12158 assert(AA->getAllocator() && 12159 "Expected allocator expression for non-default allocator."); 12160 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 12161 // According to the standard, the original allocator type is a enum 12162 // (integer). Convert to pointer type, if required. 12163 Allocator = CGF.EmitScalarConversion( 12164 Allocator, AA->getAllocator()->getType(), CGF.getContext().VoidPtrTy, 12165 AA->getAllocator()->getExprLoc()); 12166 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 12167 12168 llvm::Value *Addr = 12169 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 12170 CGM.getModule(), OMPRTL___kmpc_alloc), 12171 Args, getName({CVD->getName(), ".void.addr"})); 12172 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 12173 CGM.getModule(), OMPRTL___kmpc_free); 12174 QualType Ty = CGM.getContext().getPointerType(CVD->getType()); 12175 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12176 Addr, CGF.ConvertTypeForMem(Ty), getName({CVD->getName(), ".addr"})); 12177 if (UntiedAddr.isValid()) 12178 CGF.EmitStoreOfScalar(Addr, UntiedAddr, /*Volatile=*/false, Ty); 12179 12180 // Cleanup action for allocate support. 12181 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 12182 llvm::FunctionCallee RTLFn; 12183 SourceLocation::UIntTy LocEncoding; 12184 Address Addr; 12185 const Expr *Allocator; 12186 12187 public: 12188 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 12189 SourceLocation::UIntTy LocEncoding, Address Addr, 12190 const Expr *Allocator) 12191 : RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr), 12192 Allocator(Allocator) {} 12193 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 12194 if (!CGF.HaveInsertPoint()) 12195 return; 12196 llvm::Value *Args[3]; 12197 Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( 12198 CGF, SourceLocation::getFromRawEncoding(LocEncoding)); 12199 Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12200 Addr.getPointer(), CGF.VoidPtrTy); 12201 llvm::Value *AllocVal = CGF.EmitScalarExpr(Allocator); 12202 // According to the standard, the original allocator type is a enum 12203 // (integer). Convert to pointer type, if required. 12204 AllocVal = CGF.EmitScalarConversion(AllocVal, Allocator->getType(), 12205 CGF.getContext().VoidPtrTy, 12206 Allocator->getExprLoc()); 12207 Args[2] = AllocVal; 12208 12209 CGF.EmitRuntimeCall(RTLFn, Args); 12210 } 12211 }; 12212 Address VDAddr = 12213 UntiedRealAddr.isValid() ? UntiedRealAddr : Address(Addr, Align); 12214 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>( 12215 NormalAndEHCleanup, FiniRTLFn, CVD->getLocation().getRawEncoding(), 12216 VDAddr, AA->getAllocator()); 12217 if (UntiedRealAddr.isValid()) 12218 if (auto *Region = 12219 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 12220 Region->emitUntiedSwitch(CGF); 12221 return VDAddr; 12222 } 12223 return UntiedAddr; 12224 } 12225 12226 bool CGOpenMPRuntime::isLocalVarInUntiedTask(CodeGenFunction &CGF, 12227 const VarDecl *VD) const { 12228 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 12229 if (It == FunctionToUntiedTaskStackMap.end()) 12230 return false; 12231 return UntiedLocalVarsStack[It->second].count(VD) > 0; 12232 } 12233 12234 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 12235 CodeGenModule &CGM, const OMPLoopDirective &S) 12236 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 12237 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12238 if (!NeedToPush) 12239 return; 12240 NontemporalDeclsSet &DS = 12241 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 12242 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 12243 for (const Stmt *Ref : C->private_refs()) { 12244 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 12245 const ValueDecl *VD; 12246 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 12247 VD = DRE->getDecl(); 12248 } else { 12249 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 12250 assert((ME->isImplicitCXXThis() || 12251 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 12252 "Expected member of current class."); 12253 VD = ME->getMemberDecl(); 12254 } 12255 DS.insert(VD); 12256 } 12257 } 12258 } 12259 12260 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 12261 if (!NeedToPush) 12262 return; 12263 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 12264 } 12265 12266 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII( 12267 CodeGenFunction &CGF, 12268 const llvm::MapVector<CanonicalDeclPtr<const VarDecl>, 12269 std::pair<Address, Address>> &LocalVars) 12270 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) { 12271 if (!NeedToPush) 12272 return; 12273 CGM.getOpenMPRuntime().FunctionToUntiedTaskStackMap.try_emplace( 12274 CGF.CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size()); 12275 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars); 12276 } 12277 12278 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::~UntiedTaskLocalDeclsRAII() { 12279 if (!NeedToPush) 12280 return; 12281 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back(); 12282 } 12283 12284 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 12285 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12286 12287 return llvm::any_of( 12288 CGM.getOpenMPRuntime().NontemporalDeclsStack, 12289 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 12290 } 12291 12292 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 12293 const OMPExecutableDirective &S, 12294 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 12295 const { 12296 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 12297 // Vars in target/task regions must be excluded completely. 12298 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 12299 isOpenMPTaskingDirective(S.getDirectiveKind())) { 12300 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12301 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 12302 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 12303 for (const CapturedStmt::Capture &Cap : CS->captures()) { 12304 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 12305 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 12306 } 12307 } 12308 // Exclude vars in private clauses. 12309 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 12310 for (const Expr *Ref : C->varlists()) { 12311 if (!Ref->getType()->isScalarType()) 12312 continue; 12313 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12314 if (!DRE) 12315 continue; 12316 NeedToCheckForLPCs.insert(DRE->getDecl()); 12317 } 12318 } 12319 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 12320 for (const Expr *Ref : C->varlists()) { 12321 if (!Ref->getType()->isScalarType()) 12322 continue; 12323 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12324 if (!DRE) 12325 continue; 12326 NeedToCheckForLPCs.insert(DRE->getDecl()); 12327 } 12328 } 12329 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12330 for (const Expr *Ref : C->varlists()) { 12331 if (!Ref->getType()->isScalarType()) 12332 continue; 12333 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12334 if (!DRE) 12335 continue; 12336 NeedToCheckForLPCs.insert(DRE->getDecl()); 12337 } 12338 } 12339 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 12340 for (const Expr *Ref : C->varlists()) { 12341 if (!Ref->getType()->isScalarType()) 12342 continue; 12343 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12344 if (!DRE) 12345 continue; 12346 NeedToCheckForLPCs.insert(DRE->getDecl()); 12347 } 12348 } 12349 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 12350 for (const Expr *Ref : C->varlists()) { 12351 if (!Ref->getType()->isScalarType()) 12352 continue; 12353 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12354 if (!DRE) 12355 continue; 12356 NeedToCheckForLPCs.insert(DRE->getDecl()); 12357 } 12358 } 12359 for (const Decl *VD : NeedToCheckForLPCs) { 12360 for (const LastprivateConditionalData &Data : 12361 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 12362 if (Data.DeclToUniqueName.count(VD) > 0) { 12363 if (!Data.Disabled) 12364 NeedToAddForLPCsAsDisabled.insert(VD); 12365 break; 12366 } 12367 } 12368 } 12369 } 12370 12371 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12372 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 12373 : CGM(CGF.CGM), 12374 Action((CGM.getLangOpts().OpenMP >= 50 && 12375 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 12376 [](const OMPLastprivateClause *C) { 12377 return C->getKind() == 12378 OMPC_LASTPRIVATE_conditional; 12379 })) 12380 ? ActionToDo::PushAsLastprivateConditional 12381 : ActionToDo::DoNotPush) { 12382 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12383 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 12384 return; 12385 assert(Action == ActionToDo::PushAsLastprivateConditional && 12386 "Expected a push action."); 12387 LastprivateConditionalData &Data = 12388 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12389 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12390 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 12391 continue; 12392 12393 for (const Expr *Ref : C->varlists()) { 12394 Data.DeclToUniqueName.insert(std::make_pair( 12395 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 12396 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 12397 } 12398 } 12399 Data.IVLVal = IVLVal; 12400 Data.Fn = CGF.CurFn; 12401 } 12402 12403 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12404 CodeGenFunction &CGF, const OMPExecutableDirective &S) 12405 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 12406 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12407 if (CGM.getLangOpts().OpenMP < 50) 12408 return; 12409 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 12410 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 12411 if (!NeedToAddForLPCsAsDisabled.empty()) { 12412 Action = ActionToDo::DisableLastprivateConditional; 12413 LastprivateConditionalData &Data = 12414 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12415 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 12416 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 12417 Data.Fn = CGF.CurFn; 12418 Data.Disabled = true; 12419 } 12420 } 12421 12422 CGOpenMPRuntime::LastprivateConditionalRAII 12423 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 12424 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 12425 return LastprivateConditionalRAII(CGF, S); 12426 } 12427 12428 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 12429 if (CGM.getLangOpts().OpenMP < 50) 12430 return; 12431 if (Action == ActionToDo::DisableLastprivateConditional) { 12432 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12433 "Expected list of disabled private vars."); 12434 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12435 } 12436 if (Action == ActionToDo::PushAsLastprivateConditional) { 12437 assert( 12438 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12439 "Expected list of lastprivate conditional vars."); 12440 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12441 } 12442 } 12443 12444 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 12445 const VarDecl *VD) { 12446 ASTContext &C = CGM.getContext(); 12447 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 12448 if (I == LastprivateConditionalToTypes.end()) 12449 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 12450 QualType NewType; 12451 const FieldDecl *VDField; 12452 const FieldDecl *FiredField; 12453 LValue BaseLVal; 12454 auto VI = I->getSecond().find(VD); 12455 if (VI == I->getSecond().end()) { 12456 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 12457 RD->startDefinition(); 12458 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 12459 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 12460 RD->completeDefinition(); 12461 NewType = C.getRecordType(RD); 12462 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 12463 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 12464 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 12465 } else { 12466 NewType = std::get<0>(VI->getSecond()); 12467 VDField = std::get<1>(VI->getSecond()); 12468 FiredField = std::get<2>(VI->getSecond()); 12469 BaseLVal = std::get<3>(VI->getSecond()); 12470 } 12471 LValue FiredLVal = 12472 CGF.EmitLValueForField(BaseLVal, FiredField); 12473 CGF.EmitStoreOfScalar( 12474 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 12475 FiredLVal); 12476 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 12477 } 12478 12479 namespace { 12480 /// Checks if the lastprivate conditional variable is referenced in LHS. 12481 class LastprivateConditionalRefChecker final 12482 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 12483 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 12484 const Expr *FoundE = nullptr; 12485 const Decl *FoundD = nullptr; 12486 StringRef UniqueDeclName; 12487 LValue IVLVal; 12488 llvm::Function *FoundFn = nullptr; 12489 SourceLocation Loc; 12490 12491 public: 12492 bool VisitDeclRefExpr(const DeclRefExpr *E) { 12493 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12494 llvm::reverse(LPM)) { 12495 auto It = D.DeclToUniqueName.find(E->getDecl()); 12496 if (It == D.DeclToUniqueName.end()) 12497 continue; 12498 if (D.Disabled) 12499 return false; 12500 FoundE = E; 12501 FoundD = E->getDecl()->getCanonicalDecl(); 12502 UniqueDeclName = It->second; 12503 IVLVal = D.IVLVal; 12504 FoundFn = D.Fn; 12505 break; 12506 } 12507 return FoundE == E; 12508 } 12509 bool VisitMemberExpr(const MemberExpr *E) { 12510 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 12511 return false; 12512 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12513 llvm::reverse(LPM)) { 12514 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 12515 if (It == D.DeclToUniqueName.end()) 12516 continue; 12517 if (D.Disabled) 12518 return false; 12519 FoundE = E; 12520 FoundD = E->getMemberDecl()->getCanonicalDecl(); 12521 UniqueDeclName = It->second; 12522 IVLVal = D.IVLVal; 12523 FoundFn = D.Fn; 12524 break; 12525 } 12526 return FoundE == E; 12527 } 12528 bool VisitStmt(const Stmt *S) { 12529 for (const Stmt *Child : S->children()) { 12530 if (!Child) 12531 continue; 12532 if (const auto *E = dyn_cast<Expr>(Child)) 12533 if (!E->isGLValue()) 12534 continue; 12535 if (Visit(Child)) 12536 return true; 12537 } 12538 return false; 12539 } 12540 explicit LastprivateConditionalRefChecker( 12541 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 12542 : LPM(LPM) {} 12543 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 12544 getFoundData() const { 12545 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 12546 } 12547 }; 12548 } // namespace 12549 12550 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 12551 LValue IVLVal, 12552 StringRef UniqueDeclName, 12553 LValue LVal, 12554 SourceLocation Loc) { 12555 // Last updated loop counter for the lastprivate conditional var. 12556 // int<xx> last_iv = 0; 12557 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 12558 llvm::Constant *LastIV = 12559 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 12560 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 12561 IVLVal.getAlignment().getAsAlign()); 12562 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 12563 12564 // Last value of the lastprivate conditional. 12565 // decltype(priv_a) last_a; 12566 llvm::Constant *Last = getOrCreateInternalVariable( 12567 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 12568 cast<llvm::GlobalVariable>(Last)->setAlignment( 12569 LVal.getAlignment().getAsAlign()); 12570 LValue LastLVal = 12571 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 12572 12573 // Global loop counter. Required to handle inner parallel-for regions. 12574 // iv 12575 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 12576 12577 // #pragma omp critical(a) 12578 // if (last_iv <= iv) { 12579 // last_iv = iv; 12580 // last_a = priv_a; 12581 // } 12582 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 12583 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 12584 Action.Enter(CGF); 12585 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 12586 // (last_iv <= iv) ? Check if the variable is updated and store new 12587 // value in global var. 12588 llvm::Value *CmpRes; 12589 if (IVLVal.getType()->isSignedIntegerType()) { 12590 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 12591 } else { 12592 assert(IVLVal.getType()->isUnsignedIntegerType() && 12593 "Loop iteration variable must be integer."); 12594 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 12595 } 12596 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 12597 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 12598 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 12599 // { 12600 CGF.EmitBlock(ThenBB); 12601 12602 // last_iv = iv; 12603 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 12604 12605 // last_a = priv_a; 12606 switch (CGF.getEvaluationKind(LVal.getType())) { 12607 case TEK_Scalar: { 12608 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 12609 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 12610 break; 12611 } 12612 case TEK_Complex: { 12613 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 12614 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 12615 break; 12616 } 12617 case TEK_Aggregate: 12618 llvm_unreachable( 12619 "Aggregates are not supported in lastprivate conditional."); 12620 } 12621 // } 12622 CGF.EmitBranch(ExitBB); 12623 // There is no need to emit line number for unconditional branch. 12624 (void)ApplyDebugLocation::CreateEmpty(CGF); 12625 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 12626 }; 12627 12628 if (CGM.getLangOpts().OpenMPSimd) { 12629 // Do not emit as a critical region as no parallel region could be emitted. 12630 RegionCodeGenTy ThenRCG(CodeGen); 12631 ThenRCG(CGF); 12632 } else { 12633 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 12634 } 12635 } 12636 12637 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 12638 const Expr *LHS) { 12639 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12640 return; 12641 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 12642 if (!Checker.Visit(LHS)) 12643 return; 12644 const Expr *FoundE; 12645 const Decl *FoundD; 12646 StringRef UniqueDeclName; 12647 LValue IVLVal; 12648 llvm::Function *FoundFn; 12649 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 12650 Checker.getFoundData(); 12651 if (FoundFn != CGF.CurFn) { 12652 // Special codegen for inner parallel regions. 12653 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 12654 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 12655 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 12656 "Lastprivate conditional is not found in outer region."); 12657 QualType StructTy = std::get<0>(It->getSecond()); 12658 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 12659 LValue PrivLVal = CGF.EmitLValue(FoundE); 12660 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12661 PrivLVal.getAddress(CGF), 12662 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 12663 LValue BaseLVal = 12664 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 12665 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 12666 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 12667 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 12668 FiredLVal, llvm::AtomicOrdering::Unordered, 12669 /*IsVolatile=*/true, /*isInit=*/false); 12670 return; 12671 } 12672 12673 // Private address of the lastprivate conditional in the current context. 12674 // priv_a 12675 LValue LVal = CGF.EmitLValue(FoundE); 12676 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 12677 FoundE->getExprLoc()); 12678 } 12679 12680 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 12681 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12682 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 12683 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12684 return; 12685 auto Range = llvm::reverse(LastprivateConditionalStack); 12686 auto It = llvm::find_if( 12687 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 12688 if (It == Range.end() || It->Fn != CGF.CurFn) 12689 return; 12690 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 12691 assert(LPCI != LastprivateConditionalToTypes.end() && 12692 "Lastprivates must be registered already."); 12693 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12694 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 12695 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 12696 for (const auto &Pair : It->DeclToUniqueName) { 12697 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 12698 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 12699 continue; 12700 auto I = LPCI->getSecond().find(Pair.first); 12701 assert(I != LPCI->getSecond().end() && 12702 "Lastprivate must be rehistered already."); 12703 // bool Cmp = priv_a.Fired != 0; 12704 LValue BaseLVal = std::get<3>(I->getSecond()); 12705 LValue FiredLVal = 12706 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 12707 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 12708 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 12709 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 12710 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 12711 // if (Cmp) { 12712 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 12713 CGF.EmitBlock(ThenBB); 12714 Address Addr = CGF.GetAddrOfLocalVar(VD); 12715 LValue LVal; 12716 if (VD->getType()->isReferenceType()) 12717 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 12718 AlignmentSource::Decl); 12719 else 12720 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 12721 AlignmentSource::Decl); 12722 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 12723 D.getBeginLoc()); 12724 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 12725 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 12726 // } 12727 } 12728 } 12729 12730 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 12731 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 12732 SourceLocation Loc) { 12733 if (CGF.getLangOpts().OpenMP < 50) 12734 return; 12735 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 12736 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 12737 "Unknown lastprivate conditional variable."); 12738 StringRef UniqueName = It->second; 12739 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 12740 // The variable was not updated in the region - exit. 12741 if (!GV) 12742 return; 12743 LValue LPLVal = CGF.MakeAddrLValue( 12744 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 12745 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 12746 CGF.EmitStoreOfScalar(Res, PrivLVal); 12747 } 12748 12749 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 12750 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12751 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12752 llvm_unreachable("Not supported in SIMD-only mode"); 12753 } 12754 12755 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 12756 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12757 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12758 llvm_unreachable("Not supported in SIMD-only mode"); 12759 } 12760 12761 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 12762 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12763 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 12764 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 12765 bool Tied, unsigned &NumberOfParts) { 12766 llvm_unreachable("Not supported in SIMD-only mode"); 12767 } 12768 12769 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 12770 SourceLocation Loc, 12771 llvm::Function *OutlinedFn, 12772 ArrayRef<llvm::Value *> CapturedVars, 12773 const Expr *IfCond) { 12774 llvm_unreachable("Not supported in SIMD-only mode"); 12775 } 12776 12777 void CGOpenMPSIMDRuntime::emitCriticalRegion( 12778 CodeGenFunction &CGF, StringRef CriticalName, 12779 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 12780 const Expr *Hint) { 12781 llvm_unreachable("Not supported in SIMD-only mode"); 12782 } 12783 12784 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 12785 const RegionCodeGenTy &MasterOpGen, 12786 SourceLocation Loc) { 12787 llvm_unreachable("Not supported in SIMD-only mode"); 12788 } 12789 12790 void CGOpenMPSIMDRuntime::emitMaskedRegion(CodeGenFunction &CGF, 12791 const RegionCodeGenTy &MasterOpGen, 12792 SourceLocation Loc, 12793 const Expr *Filter) { 12794 llvm_unreachable("Not supported in SIMD-only mode"); 12795 } 12796 12797 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 12798 SourceLocation Loc) { 12799 llvm_unreachable("Not supported in SIMD-only mode"); 12800 } 12801 12802 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 12803 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 12804 SourceLocation Loc) { 12805 llvm_unreachable("Not supported in SIMD-only mode"); 12806 } 12807 12808 void CGOpenMPSIMDRuntime::emitSingleRegion( 12809 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 12810 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 12811 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 12812 ArrayRef<const Expr *> AssignmentOps) { 12813 llvm_unreachable("Not supported in SIMD-only mode"); 12814 } 12815 12816 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 12817 const RegionCodeGenTy &OrderedOpGen, 12818 SourceLocation Loc, 12819 bool IsThreads) { 12820 llvm_unreachable("Not supported in SIMD-only mode"); 12821 } 12822 12823 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 12824 SourceLocation Loc, 12825 OpenMPDirectiveKind Kind, 12826 bool EmitChecks, 12827 bool ForceSimpleCall) { 12828 llvm_unreachable("Not supported in SIMD-only mode"); 12829 } 12830 12831 void CGOpenMPSIMDRuntime::emitForDispatchInit( 12832 CodeGenFunction &CGF, SourceLocation Loc, 12833 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 12834 bool Ordered, const DispatchRTInput &DispatchValues) { 12835 llvm_unreachable("Not supported in SIMD-only mode"); 12836 } 12837 12838 void CGOpenMPSIMDRuntime::emitForStaticInit( 12839 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 12840 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 12841 llvm_unreachable("Not supported in SIMD-only mode"); 12842 } 12843 12844 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 12845 CodeGenFunction &CGF, SourceLocation Loc, 12846 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 12847 llvm_unreachable("Not supported in SIMD-only mode"); 12848 } 12849 12850 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 12851 SourceLocation Loc, 12852 unsigned IVSize, 12853 bool IVSigned) { 12854 llvm_unreachable("Not supported in SIMD-only mode"); 12855 } 12856 12857 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 12858 SourceLocation Loc, 12859 OpenMPDirectiveKind DKind) { 12860 llvm_unreachable("Not supported in SIMD-only mode"); 12861 } 12862 12863 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 12864 SourceLocation Loc, 12865 unsigned IVSize, bool IVSigned, 12866 Address IL, Address LB, 12867 Address UB, Address ST) { 12868 llvm_unreachable("Not supported in SIMD-only mode"); 12869 } 12870 12871 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 12872 llvm::Value *NumThreads, 12873 SourceLocation Loc) { 12874 llvm_unreachable("Not supported in SIMD-only mode"); 12875 } 12876 12877 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 12878 ProcBindKind ProcBind, 12879 SourceLocation Loc) { 12880 llvm_unreachable("Not supported in SIMD-only mode"); 12881 } 12882 12883 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 12884 const VarDecl *VD, 12885 Address VDAddr, 12886 SourceLocation Loc) { 12887 llvm_unreachable("Not supported in SIMD-only mode"); 12888 } 12889 12890 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 12891 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 12892 CodeGenFunction *CGF) { 12893 llvm_unreachable("Not supported in SIMD-only mode"); 12894 } 12895 12896 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 12897 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 12898 llvm_unreachable("Not supported in SIMD-only mode"); 12899 } 12900 12901 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 12902 ArrayRef<const Expr *> Vars, 12903 SourceLocation Loc, 12904 llvm::AtomicOrdering AO) { 12905 llvm_unreachable("Not supported in SIMD-only mode"); 12906 } 12907 12908 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 12909 const OMPExecutableDirective &D, 12910 llvm::Function *TaskFunction, 12911 QualType SharedsTy, Address Shareds, 12912 const Expr *IfCond, 12913 const OMPTaskDataTy &Data) { 12914 llvm_unreachable("Not supported in SIMD-only mode"); 12915 } 12916 12917 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 12918 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 12919 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 12920 const Expr *IfCond, const OMPTaskDataTy &Data) { 12921 llvm_unreachable("Not supported in SIMD-only mode"); 12922 } 12923 12924 void CGOpenMPSIMDRuntime::emitReduction( 12925 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 12926 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 12927 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 12928 assert(Options.SimpleReduction && "Only simple reduction is expected."); 12929 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 12930 ReductionOps, Options); 12931 } 12932 12933 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 12934 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 12935 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 12936 llvm_unreachable("Not supported in SIMD-only mode"); 12937 } 12938 12939 void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 12940 SourceLocation Loc, 12941 bool IsWorksharingReduction) { 12942 llvm_unreachable("Not supported in SIMD-only mode"); 12943 } 12944 12945 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 12946 SourceLocation Loc, 12947 ReductionCodeGen &RCG, 12948 unsigned N) { 12949 llvm_unreachable("Not supported in SIMD-only mode"); 12950 } 12951 12952 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 12953 SourceLocation Loc, 12954 llvm::Value *ReductionsPtr, 12955 LValue SharedLVal) { 12956 llvm_unreachable("Not supported in SIMD-only mode"); 12957 } 12958 12959 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 12960 SourceLocation Loc) { 12961 llvm_unreachable("Not supported in SIMD-only mode"); 12962 } 12963 12964 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 12965 CodeGenFunction &CGF, SourceLocation Loc, 12966 OpenMPDirectiveKind CancelRegion) { 12967 llvm_unreachable("Not supported in SIMD-only mode"); 12968 } 12969 12970 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 12971 SourceLocation Loc, const Expr *IfCond, 12972 OpenMPDirectiveKind CancelRegion) { 12973 llvm_unreachable("Not supported in SIMD-only mode"); 12974 } 12975 12976 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 12977 const OMPExecutableDirective &D, StringRef ParentName, 12978 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 12979 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 12980 llvm_unreachable("Not supported in SIMD-only mode"); 12981 } 12982 12983 void CGOpenMPSIMDRuntime::emitTargetCall( 12984 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12985 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 12986 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 12987 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 12988 const OMPLoopDirective &D)> 12989 SizeEmitter) { 12990 llvm_unreachable("Not supported in SIMD-only mode"); 12991 } 12992 12993 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 12994 llvm_unreachable("Not supported in SIMD-only mode"); 12995 } 12996 12997 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 12998 llvm_unreachable("Not supported in SIMD-only mode"); 12999 } 13000 13001 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 13002 return false; 13003 } 13004 13005 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 13006 const OMPExecutableDirective &D, 13007 SourceLocation Loc, 13008 llvm::Function *OutlinedFn, 13009 ArrayRef<llvm::Value *> CapturedVars) { 13010 llvm_unreachable("Not supported in SIMD-only mode"); 13011 } 13012 13013 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 13014 const Expr *NumTeams, 13015 const Expr *ThreadLimit, 13016 SourceLocation Loc) { 13017 llvm_unreachable("Not supported in SIMD-only mode"); 13018 } 13019 13020 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 13021 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 13022 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 13023 llvm_unreachable("Not supported in SIMD-only mode"); 13024 } 13025 13026 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 13027 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 13028 const Expr *Device) { 13029 llvm_unreachable("Not supported in SIMD-only mode"); 13030 } 13031 13032 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 13033 const OMPLoopDirective &D, 13034 ArrayRef<Expr *> NumIterations) { 13035 llvm_unreachable("Not supported in SIMD-only mode"); 13036 } 13037 13038 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 13039 const OMPDependClause *C) { 13040 llvm_unreachable("Not supported in SIMD-only mode"); 13041 } 13042 13043 const VarDecl * 13044 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 13045 const VarDecl *NativeParam) const { 13046 llvm_unreachable("Not supported in SIMD-only mode"); 13047 } 13048 13049 Address 13050 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 13051 const VarDecl *NativeParam, 13052 const VarDecl *TargetParam) const { 13053 llvm_unreachable("Not supported in SIMD-only mode"); 13054 } 13055