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/Attr.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/OpenMPClause.h" 21 #include "clang/AST/StmtOpenMP.h" 22 #include "clang/AST/StmtVisitor.h" 23 #include "clang/Basic/BitmaskEnum.h" 24 #include "clang/Basic/FileManager.h" 25 #include "clang/Basic/OpenMPKinds.h" 26 #include "clang/Basic/SourceManager.h" 27 #include "clang/CodeGen/ConstantInitBuilder.h" 28 #include "llvm/ADT/ArrayRef.h" 29 #include "llvm/ADT/SetOperations.h" 30 #include "llvm/ADT/StringExtras.h" 31 #include "llvm/Bitcode/BitcodeReader.h" 32 #include "llvm/IR/Constants.h" 33 #include "llvm/IR/DerivedTypes.h" 34 #include "llvm/IR/GlobalValue.h" 35 #include "llvm/IR/Value.h" 36 #include "llvm/Support/AtomicOrdering.h" 37 #include "llvm/Support/Format.h" 38 #include "llvm/Support/raw_ostream.h" 39 #include <cassert> 40 #include <numeric> 41 42 using namespace clang; 43 using namespace CodeGen; 44 using namespace llvm::omp; 45 46 namespace { 47 /// Base class for handling code generation inside OpenMP regions. 48 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 49 public: 50 /// Kinds of OpenMP regions used in codegen. 51 enum CGOpenMPRegionKind { 52 /// Region with outlined function for standalone 'parallel' 53 /// directive. 54 ParallelOutlinedRegion, 55 /// Region with outlined function for standalone 'task' directive. 56 TaskOutlinedRegion, 57 /// Region for constructs that do not require function outlining, 58 /// like 'for', 'sections', 'atomic' etc. directives. 59 InlinedRegion, 60 /// Region with outlined function for standalone 'target' directive. 61 TargetRegion, 62 }; 63 64 CGOpenMPRegionInfo(const CapturedStmt &CS, 65 const CGOpenMPRegionKind RegionKind, 66 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 67 bool HasCancel) 68 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 69 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 70 71 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 72 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 73 bool HasCancel) 74 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 75 Kind(Kind), HasCancel(HasCancel) {} 76 77 /// Get a variable or parameter for storing global thread id 78 /// inside OpenMP construct. 79 virtual const VarDecl *getThreadIDVariable() const = 0; 80 81 /// Emit the captured statement body. 82 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 83 84 /// Get an LValue for the current ThreadID variable. 85 /// \return LValue for thread id variable. This LValue always has type int32*. 86 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 87 88 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 89 90 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 91 92 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 93 94 bool hasCancel() const { return HasCancel; } 95 96 static bool classof(const CGCapturedStmtInfo *Info) { 97 return Info->getKind() == CR_OpenMP; 98 } 99 100 ~CGOpenMPRegionInfo() override = default; 101 102 protected: 103 CGOpenMPRegionKind RegionKind; 104 RegionCodeGenTy CodeGen; 105 OpenMPDirectiveKind Kind; 106 bool HasCancel; 107 }; 108 109 /// API for captured statement code generation in OpenMP constructs. 110 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 111 public: 112 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 113 const RegionCodeGenTy &CodeGen, 114 OpenMPDirectiveKind Kind, bool HasCancel, 115 StringRef HelperName) 116 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 117 HasCancel), 118 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 119 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 120 } 121 122 /// Get a variable or parameter for storing global thread id 123 /// inside OpenMP construct. 124 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 125 126 /// Get the name of the capture helper. 127 StringRef getHelperName() const override { return HelperName; } 128 129 static bool classof(const CGCapturedStmtInfo *Info) { 130 return CGOpenMPRegionInfo::classof(Info) && 131 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 132 ParallelOutlinedRegion; 133 } 134 135 private: 136 /// A variable or parameter storing global thread id for OpenMP 137 /// constructs. 138 const VarDecl *ThreadIDVar; 139 StringRef HelperName; 140 }; 141 142 /// API for captured statement code generation in OpenMP constructs. 143 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 144 public: 145 class UntiedTaskActionTy final : public PrePostActionTy { 146 bool Untied; 147 const VarDecl *PartIDVar; 148 const RegionCodeGenTy UntiedCodeGen; 149 llvm::SwitchInst *UntiedSwitch = nullptr; 150 151 public: 152 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 153 const RegionCodeGenTy &UntiedCodeGen) 154 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 155 void Enter(CodeGenFunction &CGF) override { 156 if (Untied) { 157 // Emit task switching point. 158 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 159 CGF.GetAddrOfLocalVar(PartIDVar), 160 PartIDVar->getType()->castAs<PointerType>()); 161 llvm::Value *Res = 162 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 163 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 164 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 165 CGF.EmitBlock(DoneBB); 166 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 167 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 168 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 169 CGF.Builder.GetInsertBlock()); 170 emitUntiedSwitch(CGF); 171 } 172 } 173 void emitUntiedSwitch(CodeGenFunction &CGF) const { 174 if (Untied) { 175 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 176 CGF.GetAddrOfLocalVar(PartIDVar), 177 PartIDVar->getType()->castAs<PointerType>()); 178 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 179 PartIdLVal); 180 UntiedCodeGen(CGF); 181 CodeGenFunction::JumpDest CurPoint = 182 CGF.getJumpDestInCurrentScope(".untied.next."); 183 CGF.EmitBranch(CGF.ReturnBlock.getBlock()); 184 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 185 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 186 CGF.Builder.GetInsertBlock()); 187 CGF.EmitBranchThroughCleanup(CurPoint); 188 CGF.EmitBlock(CurPoint.getBlock()); 189 } 190 } 191 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 192 }; 193 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 194 const VarDecl *ThreadIDVar, 195 const RegionCodeGenTy &CodeGen, 196 OpenMPDirectiveKind Kind, bool HasCancel, 197 const UntiedTaskActionTy &Action) 198 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 199 ThreadIDVar(ThreadIDVar), Action(Action) { 200 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 201 } 202 203 /// Get a variable or parameter for storing global thread id 204 /// inside OpenMP construct. 205 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 206 207 /// Get an LValue for the current ThreadID variable. 208 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 209 210 /// Get the name of the capture helper. 211 StringRef getHelperName() const override { return ".omp_outlined."; } 212 213 void emitUntiedSwitch(CodeGenFunction &CGF) override { 214 Action.emitUntiedSwitch(CGF); 215 } 216 217 static bool classof(const CGCapturedStmtInfo *Info) { 218 return CGOpenMPRegionInfo::classof(Info) && 219 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 220 TaskOutlinedRegion; 221 } 222 223 private: 224 /// A variable or parameter storing global thread id for OpenMP 225 /// constructs. 226 const VarDecl *ThreadIDVar; 227 /// Action for emitting code for untied tasks. 228 const UntiedTaskActionTy &Action; 229 }; 230 231 /// API for inlined captured statement code generation in OpenMP 232 /// constructs. 233 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 234 public: 235 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 236 const RegionCodeGenTy &CodeGen, 237 OpenMPDirectiveKind Kind, bool HasCancel) 238 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 239 OldCSI(OldCSI), 240 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 241 242 // Retrieve the value of the context parameter. 243 llvm::Value *getContextValue() const override { 244 if (OuterRegionInfo) 245 return OuterRegionInfo->getContextValue(); 246 llvm_unreachable("No context value for inlined OpenMP region"); 247 } 248 249 void setContextValue(llvm::Value *V) override { 250 if (OuterRegionInfo) { 251 OuterRegionInfo->setContextValue(V); 252 return; 253 } 254 llvm_unreachable("No context value for inlined OpenMP region"); 255 } 256 257 /// Lookup the captured field decl for a variable. 258 const FieldDecl *lookup(const VarDecl *VD) const override { 259 if (OuterRegionInfo) 260 return OuterRegionInfo->lookup(VD); 261 // If there is no outer outlined region,no need to lookup in a list of 262 // captured variables, we can use the original one. 263 return nullptr; 264 } 265 266 FieldDecl *getThisFieldDecl() const override { 267 if (OuterRegionInfo) 268 return OuterRegionInfo->getThisFieldDecl(); 269 return nullptr; 270 } 271 272 /// Get a variable or parameter for storing global thread id 273 /// inside OpenMP construct. 274 const VarDecl *getThreadIDVariable() const override { 275 if (OuterRegionInfo) 276 return OuterRegionInfo->getThreadIDVariable(); 277 return nullptr; 278 } 279 280 /// Get an LValue for the current ThreadID variable. 281 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 282 if (OuterRegionInfo) 283 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 284 llvm_unreachable("No LValue for inlined OpenMP construct"); 285 } 286 287 /// Get the name of the capture helper. 288 StringRef getHelperName() const override { 289 if (auto *OuterRegionInfo = getOldCSI()) 290 return OuterRegionInfo->getHelperName(); 291 llvm_unreachable("No helper name for inlined OpenMP construct"); 292 } 293 294 void emitUntiedSwitch(CodeGenFunction &CGF) override { 295 if (OuterRegionInfo) 296 OuterRegionInfo->emitUntiedSwitch(CGF); 297 } 298 299 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 300 301 static bool classof(const CGCapturedStmtInfo *Info) { 302 return CGOpenMPRegionInfo::classof(Info) && 303 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 304 } 305 306 ~CGOpenMPInlinedRegionInfo() override = default; 307 308 private: 309 /// CodeGen info about outer OpenMP region. 310 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 311 CGOpenMPRegionInfo *OuterRegionInfo; 312 }; 313 314 /// API for captured statement code generation in OpenMP target 315 /// constructs. For this captures, implicit parameters are used instead of the 316 /// captured fields. The name of the target region has to be unique in a given 317 /// application so it is provided by the client, because only the client has 318 /// the information to generate that. 319 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 320 public: 321 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 322 const RegionCodeGenTy &CodeGen, StringRef HelperName) 323 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 324 /*HasCancel=*/false), 325 HelperName(HelperName) {} 326 327 /// This is unused for target regions because each starts executing 328 /// with a single thread. 329 const VarDecl *getThreadIDVariable() const override { return nullptr; } 330 331 /// Get the name of the capture helper. 332 StringRef getHelperName() const override { return HelperName; } 333 334 static bool classof(const CGCapturedStmtInfo *Info) { 335 return CGOpenMPRegionInfo::classof(Info) && 336 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 337 } 338 339 private: 340 StringRef HelperName; 341 }; 342 343 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 344 llvm_unreachable("No codegen for expressions"); 345 } 346 /// API for generation of expressions captured in a innermost OpenMP 347 /// region. 348 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 349 public: 350 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 351 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 352 OMPD_unknown, 353 /*HasCancel=*/false), 354 PrivScope(CGF) { 355 // Make sure the globals captured in the provided statement are local by 356 // using the privatization logic. We assume the same variable is not 357 // captured more than once. 358 for (const auto &C : CS.captures()) { 359 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 360 continue; 361 362 const VarDecl *VD = C.getCapturedVar(); 363 if (VD->isLocalVarDeclOrParm()) 364 continue; 365 366 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 367 /*RefersToEnclosingVariableOrCapture=*/false, 368 VD->getType().getNonReferenceType(), VK_LValue, 369 C.getLocation()); 370 PrivScope.addPrivate( 371 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 372 } 373 (void)PrivScope.Privatize(); 374 } 375 376 /// Lookup the captured field decl for a variable. 377 const FieldDecl *lookup(const VarDecl *VD) const override { 378 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 379 return FD; 380 return nullptr; 381 } 382 383 /// Emit the captured statement body. 384 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 385 llvm_unreachable("No body for expressions"); 386 } 387 388 /// Get a variable or parameter for storing global thread id 389 /// inside OpenMP construct. 390 const VarDecl *getThreadIDVariable() const override { 391 llvm_unreachable("No thread id for expressions"); 392 } 393 394 /// Get the name of the capture helper. 395 StringRef getHelperName() const override { 396 llvm_unreachable("No helper name for expressions"); 397 } 398 399 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 400 401 private: 402 /// Private scope to capture global variables. 403 CodeGenFunction::OMPPrivateScope PrivScope; 404 }; 405 406 /// RAII for emitting code of OpenMP constructs. 407 class InlinedOpenMPRegionRAII { 408 CodeGenFunction &CGF; 409 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 410 FieldDecl *LambdaThisCaptureField = nullptr; 411 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 412 413 public: 414 /// Constructs region for combined constructs. 415 /// \param CodeGen Code generation sequence for combined directives. Includes 416 /// a list of functions used for code generation of implicitly inlined 417 /// regions. 418 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 419 OpenMPDirectiveKind Kind, bool HasCancel) 420 : CGF(CGF) { 421 // Start emission for the construct. 422 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 423 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 424 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 425 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 426 CGF.LambdaThisCaptureField = nullptr; 427 BlockInfo = CGF.BlockInfo; 428 CGF.BlockInfo = nullptr; 429 } 430 431 ~InlinedOpenMPRegionRAII() { 432 // Restore original CapturedStmtInfo only if we're done with code emission. 433 auto *OldCSI = 434 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 435 delete CGF.CapturedStmtInfo; 436 CGF.CapturedStmtInfo = OldCSI; 437 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 438 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 439 CGF.BlockInfo = BlockInfo; 440 } 441 }; 442 443 /// Values for bit flags used in the ident_t to describe the fields. 444 /// All enumeric elements are named and described in accordance with the code 445 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 446 enum OpenMPLocationFlags : unsigned { 447 /// Use trampoline for internal microtask. 448 OMP_IDENT_IMD = 0x01, 449 /// Use c-style ident structure. 450 OMP_IDENT_KMPC = 0x02, 451 /// Atomic reduction option for kmpc_reduce. 452 OMP_ATOMIC_REDUCE = 0x10, 453 /// Explicit 'barrier' directive. 454 OMP_IDENT_BARRIER_EXPL = 0x20, 455 /// Implicit barrier in code. 456 OMP_IDENT_BARRIER_IMPL = 0x40, 457 /// Implicit barrier in 'for' directive. 458 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 459 /// Implicit barrier in 'sections' directive. 460 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 461 /// Implicit barrier in 'single' directive. 462 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 463 /// Call of __kmp_for_static_init for static loop. 464 OMP_IDENT_WORK_LOOP = 0x200, 465 /// Call of __kmp_for_static_init for sections. 466 OMP_IDENT_WORK_SECTIONS = 0x400, 467 /// Call of __kmp_for_static_init for distribute. 468 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 469 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 470 }; 471 472 namespace { 473 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 474 /// Values for bit flags for marking which requires clauses have been used. 475 enum OpenMPOffloadingRequiresDirFlags : int64_t { 476 /// flag undefined. 477 OMP_REQ_UNDEFINED = 0x000, 478 /// no requires clause present. 479 OMP_REQ_NONE = 0x001, 480 /// reverse_offload clause. 481 OMP_REQ_REVERSE_OFFLOAD = 0x002, 482 /// unified_address clause. 483 OMP_REQ_UNIFIED_ADDRESS = 0x004, 484 /// unified_shared_memory clause. 485 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 486 /// dynamic_allocators clause. 487 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 488 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 489 }; 490 491 enum OpenMPOffloadingReservedDeviceIDs { 492 /// Device ID if the device was not defined, runtime should get it 493 /// from environment variables in the spec. 494 OMP_DEVICEID_UNDEF = -1, 495 }; 496 } // anonymous namespace 497 498 /// Describes ident structure that describes a source location. 499 /// All descriptions are taken from 500 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 501 /// Original structure: 502 /// typedef struct ident { 503 /// kmp_int32 reserved_1; /**< might be used in Fortran; 504 /// see above */ 505 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 506 /// KMP_IDENT_KMPC identifies this union 507 /// member */ 508 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 509 /// see above */ 510 ///#if USE_ITT_BUILD 511 /// /* but currently used for storing 512 /// region-specific ITT */ 513 /// /* contextual information. */ 514 ///#endif /* USE_ITT_BUILD */ 515 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 516 /// C++ */ 517 /// char const *psource; /**< String describing the source location. 518 /// The string is composed of semi-colon separated 519 // fields which describe the source file, 520 /// the function and a pair of line numbers that 521 /// delimit the construct. 522 /// */ 523 /// } ident_t; 524 enum IdentFieldIndex { 525 /// might be used in Fortran 526 IdentField_Reserved_1, 527 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 528 IdentField_Flags, 529 /// Not really used in Fortran any more 530 IdentField_Reserved_2, 531 /// Source[4] in Fortran, do not use for C++ 532 IdentField_Reserved_3, 533 /// String describing the source location. The string is composed of 534 /// semi-colon separated fields which describe the source file, the function 535 /// and a pair of line numbers that delimit the construct. 536 IdentField_PSource 537 }; 538 539 /// Schedule types for 'omp for' loops (these enumerators are taken from 540 /// the enum sched_type in kmp.h). 541 enum OpenMPSchedType { 542 /// Lower bound for default (unordered) versions. 543 OMP_sch_lower = 32, 544 OMP_sch_static_chunked = 33, 545 OMP_sch_static = 34, 546 OMP_sch_dynamic_chunked = 35, 547 OMP_sch_guided_chunked = 36, 548 OMP_sch_runtime = 37, 549 OMP_sch_auto = 38, 550 /// static with chunk adjustment (e.g., simd) 551 OMP_sch_static_balanced_chunked = 45, 552 /// Lower bound for 'ordered' versions. 553 OMP_ord_lower = 64, 554 OMP_ord_static_chunked = 65, 555 OMP_ord_static = 66, 556 OMP_ord_dynamic_chunked = 67, 557 OMP_ord_guided_chunked = 68, 558 OMP_ord_runtime = 69, 559 OMP_ord_auto = 70, 560 OMP_sch_default = OMP_sch_static, 561 /// dist_schedule types 562 OMP_dist_sch_static_chunked = 91, 563 OMP_dist_sch_static = 92, 564 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 565 /// Set if the monotonic schedule modifier was present. 566 OMP_sch_modifier_monotonic = (1 << 29), 567 /// Set if the nonmonotonic schedule modifier was present. 568 OMP_sch_modifier_nonmonotonic = (1 << 30), 569 }; 570 571 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 572 /// region. 573 class CleanupTy final : public EHScopeStack::Cleanup { 574 PrePostActionTy *Action; 575 576 public: 577 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 578 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 579 if (!CGF.HaveInsertPoint()) 580 return; 581 Action->Exit(CGF); 582 } 583 }; 584 585 } // anonymous namespace 586 587 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 588 CodeGenFunction::RunCleanupsScope Scope(CGF); 589 if (PrePostAction) { 590 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 591 Callback(CodeGen, CGF, *PrePostAction); 592 } else { 593 PrePostActionTy Action; 594 Callback(CodeGen, CGF, Action); 595 } 596 } 597 598 /// Check if the combiner is a call to UDR combiner and if it is so return the 599 /// UDR decl used for reduction. 600 static const OMPDeclareReductionDecl * 601 getReductionInit(const Expr *ReductionOp) { 602 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 603 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 604 if (const auto *DRE = 605 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 606 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 607 return DRD; 608 return nullptr; 609 } 610 611 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 612 const OMPDeclareReductionDecl *DRD, 613 const Expr *InitOp, 614 Address Private, Address Original, 615 QualType Ty) { 616 if (DRD->getInitializer()) { 617 std::pair<llvm::Function *, llvm::Function *> Reduction = 618 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 619 const auto *CE = cast<CallExpr>(InitOp); 620 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 621 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 622 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 623 const auto *LHSDRE = 624 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 625 const auto *RHSDRE = 626 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 627 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 628 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 629 [=]() { return Private; }); 630 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 631 [=]() { return Original; }); 632 (void)PrivateScope.Privatize(); 633 RValue Func = RValue::get(Reduction.second); 634 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 635 CGF.EmitIgnoredExpr(InitOp); 636 } else { 637 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 638 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 639 auto *GV = new llvm::GlobalVariable( 640 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 641 llvm::GlobalValue::PrivateLinkage, Init, Name); 642 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 643 RValue InitRVal; 644 switch (CGF.getEvaluationKind(Ty)) { 645 case TEK_Scalar: 646 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 647 break; 648 case TEK_Complex: 649 InitRVal = 650 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 651 break; 652 case TEK_Aggregate: 653 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 654 break; 655 } 656 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 657 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 658 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 659 /*IsInitializer=*/false); 660 } 661 } 662 663 /// Emit initialization of arrays of complex types. 664 /// \param DestAddr Address of the array. 665 /// \param Type Type of array. 666 /// \param Init Initial expression of array. 667 /// \param SrcAddr Address of the original array. 668 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 669 QualType Type, bool EmitDeclareReductionInit, 670 const Expr *Init, 671 const OMPDeclareReductionDecl *DRD, 672 Address SrcAddr = Address::invalid()) { 673 // Perform element-by-element initialization. 674 QualType ElementTy; 675 676 // Drill down to the base element type on both arrays. 677 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 678 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 679 DestAddr = 680 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 681 if (DRD) 682 SrcAddr = 683 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 684 685 llvm::Value *SrcBegin = nullptr; 686 if (DRD) 687 SrcBegin = SrcAddr.getPointer(); 688 llvm::Value *DestBegin = DestAddr.getPointer(); 689 // Cast from pointer to array type to pointer to single element. 690 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 691 // The basic structure here is a while-do loop. 692 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 693 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 694 llvm::Value *IsEmpty = 695 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 696 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 697 698 // Enter the loop body, making that address the current address. 699 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 700 CGF.EmitBlock(BodyBB); 701 702 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 703 704 llvm::PHINode *SrcElementPHI = nullptr; 705 Address SrcElementCurrent = Address::invalid(); 706 if (DRD) { 707 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 708 "omp.arraycpy.srcElementPast"); 709 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 710 SrcElementCurrent = 711 Address(SrcElementPHI, 712 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 713 } 714 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 715 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 716 DestElementPHI->addIncoming(DestBegin, EntryBB); 717 Address DestElementCurrent = 718 Address(DestElementPHI, 719 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 720 721 // Emit copy. 722 { 723 CodeGenFunction::RunCleanupsScope InitScope(CGF); 724 if (EmitDeclareReductionInit) { 725 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 726 SrcElementCurrent, ElementTy); 727 } else 728 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 729 /*IsInitializer=*/false); 730 } 731 732 if (DRD) { 733 // Shift the address forward by one element. 734 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 735 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 736 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 737 } 738 739 // Shift the address forward by one element. 740 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 741 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 742 // Check whether we've reached the end. 743 llvm::Value *Done = 744 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 745 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 746 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 747 748 // Done. 749 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 750 } 751 752 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 753 return CGF.EmitOMPSharedLValue(E); 754 } 755 756 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 757 const Expr *E) { 758 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 759 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 760 return LValue(); 761 } 762 763 void ReductionCodeGen::emitAggregateInitialization( 764 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 765 const OMPDeclareReductionDecl *DRD) { 766 // Emit VarDecl with copy init for arrays. 767 // Get the address of the original variable captured in current 768 // captured region. 769 const auto *PrivateVD = 770 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 771 bool EmitDeclareReductionInit = 772 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 773 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 774 EmitDeclareReductionInit, 775 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 776 : PrivateVD->getInit(), 777 DRD, SharedLVal.getAddress(CGF)); 778 } 779 780 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 781 ArrayRef<const Expr *> Origs, 782 ArrayRef<const Expr *> Privates, 783 ArrayRef<const Expr *> ReductionOps) { 784 ClausesData.reserve(Shareds.size()); 785 SharedAddresses.reserve(Shareds.size()); 786 Sizes.reserve(Shareds.size()); 787 BaseDecls.reserve(Shareds.size()); 788 const auto *IOrig = Origs.begin(); 789 const auto *IPriv = Privates.begin(); 790 const auto *IRed = ReductionOps.begin(); 791 for (const Expr *Ref : Shareds) { 792 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed); 793 std::advance(IOrig, 1); 794 std::advance(IPriv, 1); 795 std::advance(IRed, 1); 796 } 797 } 798 799 void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) { 800 assert(SharedAddresses.size() == N && OrigAddresses.size() == N && 801 "Number of generated lvalues must be exactly N."); 802 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared); 803 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared); 804 SharedAddresses.emplace_back(First, Second); 805 if (ClausesData[N].Shared == ClausesData[N].Ref) { 806 OrigAddresses.emplace_back(First, Second); 807 } else { 808 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 809 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 810 OrigAddresses.emplace_back(First, Second); 811 } 812 } 813 814 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 815 const auto *PrivateVD = 816 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 817 QualType PrivateType = PrivateVD->getType(); 818 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 819 if (!PrivateType->isVariablyModifiedType()) { 820 Sizes.emplace_back( 821 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()), 822 nullptr); 823 return; 824 } 825 llvm::Value *Size; 826 llvm::Value *SizeInChars; 827 auto *ElemType = 828 cast<llvm::PointerType>(OrigAddresses[N].first.getPointer(CGF)->getType()) 829 ->getElementType(); 830 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 831 if (AsArraySection) { 832 Size = CGF.Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF), 833 OrigAddresses[N].first.getPointer(CGF)); 834 Size = CGF.Builder.CreateNUWAdd( 835 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 836 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 837 } else { 838 SizeInChars = 839 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()); 840 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 841 } 842 Sizes.emplace_back(SizeInChars, Size); 843 CodeGenFunction::OpaqueValueMapping OpaqueMap( 844 CGF, 845 cast<OpaqueValueExpr>( 846 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 847 RValue::get(Size)); 848 CGF.EmitVariablyModifiedType(PrivateType); 849 } 850 851 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 852 llvm::Value *Size) { 853 const auto *PrivateVD = 854 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 855 QualType PrivateType = PrivateVD->getType(); 856 if (!PrivateType->isVariablyModifiedType()) { 857 assert(!Size && !Sizes[N].second && 858 "Size should be nullptr for non-variably modified reduction " 859 "items."); 860 return; 861 } 862 CodeGenFunction::OpaqueValueMapping OpaqueMap( 863 CGF, 864 cast<OpaqueValueExpr>( 865 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 866 RValue::get(Size)); 867 CGF.EmitVariablyModifiedType(PrivateType); 868 } 869 870 void ReductionCodeGen::emitInitialization( 871 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 872 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 873 assert(SharedAddresses.size() > N && "No variable was generated"); 874 const auto *PrivateVD = 875 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 876 const OMPDeclareReductionDecl *DRD = 877 getReductionInit(ClausesData[N].ReductionOp); 878 QualType PrivateType = PrivateVD->getType(); 879 PrivateAddr = CGF.Builder.CreateElementBitCast( 880 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 881 QualType SharedType = SharedAddresses[N].first.getType(); 882 SharedLVal = CGF.MakeAddrLValue( 883 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 884 CGF.ConvertTypeForMem(SharedType)), 885 SharedType, SharedAddresses[N].first.getBaseInfo(), 886 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 887 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 888 if (DRD && DRD->getInitializer()) 889 (void)DefaultInit(CGF); 890 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 891 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 892 (void)DefaultInit(CGF); 893 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 894 PrivateAddr, SharedLVal.getAddress(CGF), 895 SharedLVal.getType()); 896 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 897 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 898 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 899 PrivateVD->getType().getQualifiers(), 900 /*IsInitializer=*/false); 901 } 902 } 903 904 bool ReductionCodeGen::needCleanups(unsigned N) { 905 const auto *PrivateVD = 906 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 907 QualType PrivateType = PrivateVD->getType(); 908 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 909 return DTorKind != QualType::DK_none; 910 } 911 912 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 913 Address PrivateAddr) { 914 const auto *PrivateVD = 915 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 916 QualType PrivateType = PrivateVD->getType(); 917 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 918 if (needCleanups(N)) { 919 PrivateAddr = CGF.Builder.CreateElementBitCast( 920 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 921 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 922 } 923 } 924 925 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 926 LValue BaseLV) { 927 BaseTy = BaseTy.getNonReferenceType(); 928 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 929 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 930 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 931 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 932 } else { 933 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 934 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 935 } 936 BaseTy = BaseTy->getPointeeType(); 937 } 938 return CGF.MakeAddrLValue( 939 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 940 CGF.ConvertTypeForMem(ElTy)), 941 BaseLV.getType(), BaseLV.getBaseInfo(), 942 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 943 } 944 945 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 946 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 947 llvm::Value *Addr) { 948 Address Tmp = Address::invalid(); 949 Address TopTmp = Address::invalid(); 950 Address MostTopTmp = Address::invalid(); 951 BaseTy = BaseTy.getNonReferenceType(); 952 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 953 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 954 Tmp = CGF.CreateMemTemp(BaseTy); 955 if (TopTmp.isValid()) 956 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 957 else 958 MostTopTmp = Tmp; 959 TopTmp = Tmp; 960 BaseTy = BaseTy->getPointeeType(); 961 } 962 llvm::Type *Ty = BaseLVType; 963 if (Tmp.isValid()) 964 Ty = Tmp.getElementType(); 965 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 966 if (Tmp.isValid()) { 967 CGF.Builder.CreateStore(Addr, Tmp); 968 return MostTopTmp; 969 } 970 return Address(Addr, BaseLVAlignment); 971 } 972 973 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 974 const VarDecl *OrigVD = nullptr; 975 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 976 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 977 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 978 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 979 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 980 Base = TempASE->getBase()->IgnoreParenImpCasts(); 981 DE = cast<DeclRefExpr>(Base); 982 OrigVD = cast<VarDecl>(DE->getDecl()); 983 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 984 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 985 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 986 Base = TempASE->getBase()->IgnoreParenImpCasts(); 987 DE = cast<DeclRefExpr>(Base); 988 OrigVD = cast<VarDecl>(DE->getDecl()); 989 } 990 return OrigVD; 991 } 992 993 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 994 Address PrivateAddr) { 995 const DeclRefExpr *DE; 996 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 997 BaseDecls.emplace_back(OrigVD); 998 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 999 LValue BaseLValue = 1000 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1001 OriginalBaseLValue); 1002 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1003 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1004 llvm::Value *PrivatePointer = 1005 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1006 PrivateAddr.getPointer(), 1007 SharedAddresses[N].first.getAddress(CGF).getType()); 1008 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1009 return castToBase(CGF, OrigVD->getType(), 1010 SharedAddresses[N].first.getType(), 1011 OriginalBaseLValue.getAddress(CGF).getType(), 1012 OriginalBaseLValue.getAlignment(), Ptr); 1013 } 1014 BaseDecls.emplace_back( 1015 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1016 return PrivateAddr; 1017 } 1018 1019 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1020 const OMPDeclareReductionDecl *DRD = 1021 getReductionInit(ClausesData[N].ReductionOp); 1022 return DRD && DRD->getInitializer(); 1023 } 1024 1025 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1026 return CGF.EmitLoadOfPointerLValue( 1027 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1028 getThreadIDVariable()->getType()->castAs<PointerType>()); 1029 } 1030 1031 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1032 if (!CGF.HaveInsertPoint()) 1033 return; 1034 // 1.2.2 OpenMP Language Terminology 1035 // Structured block - An executable statement with a single entry at the 1036 // top and a single exit at the bottom. 1037 // The point of exit cannot be a branch out of the structured block. 1038 // longjmp() and throw() must not violate the entry/exit criteria. 1039 CGF.EHStack.pushTerminate(); 1040 CodeGen(CGF); 1041 CGF.EHStack.popTerminate(); 1042 } 1043 1044 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1045 CodeGenFunction &CGF) { 1046 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1047 getThreadIDVariable()->getType(), 1048 AlignmentSource::Decl); 1049 } 1050 1051 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1052 QualType FieldTy) { 1053 auto *Field = FieldDecl::Create( 1054 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1055 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1056 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1057 Field->setAccess(AS_public); 1058 DC->addDecl(Field); 1059 return Field; 1060 } 1061 1062 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1063 StringRef Separator) 1064 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1065 OMPBuilder(CGM.getModule()), OffloadEntriesInfoManager(CGM) { 1066 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1067 1068 // Initialize Types used in OpenMPIRBuilder from OMPKinds.def 1069 OMPBuilder.initialize(); 1070 loadOffloadInfoMetadata(); 1071 } 1072 1073 void CGOpenMPRuntime::clear() { 1074 InternalVars.clear(); 1075 // Clean non-target variable declarations possibly used only in debug info. 1076 for (const auto &Data : EmittedNonTargetVariables) { 1077 if (!Data.getValue().pointsToAliveValue()) 1078 continue; 1079 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1080 if (!GV) 1081 continue; 1082 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1083 continue; 1084 GV->eraseFromParent(); 1085 } 1086 } 1087 1088 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1089 SmallString<128> Buffer; 1090 llvm::raw_svector_ostream OS(Buffer); 1091 StringRef Sep = FirstSeparator; 1092 for (StringRef Part : Parts) { 1093 OS << Sep << Part; 1094 Sep = Separator; 1095 } 1096 return std::string(OS.str()); 1097 } 1098 1099 static llvm::Function * 1100 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1101 const Expr *CombinerInitializer, const VarDecl *In, 1102 const VarDecl *Out, bool IsCombiner) { 1103 // void .omp_combiner.(Ty *in, Ty *out); 1104 ASTContext &C = CGM.getContext(); 1105 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1106 FunctionArgList Args; 1107 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1108 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1109 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1110 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1111 Args.push_back(&OmpOutParm); 1112 Args.push_back(&OmpInParm); 1113 const CGFunctionInfo &FnInfo = 1114 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1115 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1116 std::string Name = CGM.getOpenMPRuntime().getName( 1117 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1118 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1119 Name, &CGM.getModule()); 1120 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1121 if (CGM.getLangOpts().Optimize) { 1122 Fn->removeFnAttr(llvm::Attribute::NoInline); 1123 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1124 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1125 } 1126 CodeGenFunction CGF(CGM); 1127 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1128 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1129 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1130 Out->getLocation()); 1131 CodeGenFunction::OMPPrivateScope Scope(CGF); 1132 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1133 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1134 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1135 .getAddress(CGF); 1136 }); 1137 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1138 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1139 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1140 .getAddress(CGF); 1141 }); 1142 (void)Scope.Privatize(); 1143 if (!IsCombiner && Out->hasInit() && 1144 !CGF.isTrivialInitializer(Out->getInit())) { 1145 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1146 Out->getType().getQualifiers(), 1147 /*IsInitializer=*/true); 1148 } 1149 if (CombinerInitializer) 1150 CGF.EmitIgnoredExpr(CombinerInitializer); 1151 Scope.ForceCleanup(); 1152 CGF.FinishFunction(); 1153 return Fn; 1154 } 1155 1156 void CGOpenMPRuntime::emitUserDefinedReduction( 1157 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1158 if (UDRMap.count(D) > 0) 1159 return; 1160 llvm::Function *Combiner = emitCombinerOrInitializer( 1161 CGM, D->getType(), D->getCombiner(), 1162 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1163 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1164 /*IsCombiner=*/true); 1165 llvm::Function *Initializer = nullptr; 1166 if (const Expr *Init = D->getInitializer()) { 1167 Initializer = emitCombinerOrInitializer( 1168 CGM, D->getType(), 1169 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1170 : nullptr, 1171 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1172 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1173 /*IsCombiner=*/false); 1174 } 1175 UDRMap.try_emplace(D, Combiner, Initializer); 1176 if (CGF) { 1177 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1178 Decls.second.push_back(D); 1179 } 1180 } 1181 1182 std::pair<llvm::Function *, llvm::Function *> 1183 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1184 auto I = UDRMap.find(D); 1185 if (I != UDRMap.end()) 1186 return I->second; 1187 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1188 return UDRMap.lookup(D); 1189 } 1190 1191 namespace { 1192 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1193 // Builder if one is present. 1194 struct PushAndPopStackRAII { 1195 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1196 bool HasCancel) 1197 : OMPBuilder(OMPBuilder) { 1198 if (!OMPBuilder) 1199 return; 1200 1201 // The following callback is the crucial part of clangs cleanup process. 1202 // 1203 // NOTE: 1204 // Once the OpenMPIRBuilder is used to create parallel regions (and 1205 // similar), the cancellation destination (Dest below) is determined via 1206 // IP. That means if we have variables to finalize we split the block at IP, 1207 // use the new block (=BB) as destination to build a JumpDest (via 1208 // getJumpDestInCurrentScope(BB)) which then is fed to 1209 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1210 // to push & pop an FinalizationInfo object. 1211 // The FiniCB will still be needed but at the point where the 1212 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1213 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1214 assert(IP.getBlock()->end() == IP.getPoint() && 1215 "Clang CG should cause non-terminated block!"); 1216 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1217 CGF.Builder.restoreIP(IP); 1218 CodeGenFunction::JumpDest Dest = 1219 CGF.getOMPCancelDestination(OMPD_parallel); 1220 CGF.EmitBranchThroughCleanup(Dest); 1221 }; 1222 1223 // TODO: Remove this once we emit parallel regions through the 1224 // OpenMPIRBuilder as it can do this setup internally. 1225 llvm::OpenMPIRBuilder::FinalizationInfo FI( 1226 {FiniCB, OMPD_parallel, HasCancel}); 1227 OMPBuilder->pushFinalizationCB(std::move(FI)); 1228 } 1229 ~PushAndPopStackRAII() { 1230 if (OMPBuilder) 1231 OMPBuilder->popFinalizationCB(); 1232 } 1233 llvm::OpenMPIRBuilder *OMPBuilder; 1234 }; 1235 } // namespace 1236 1237 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1238 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1239 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1240 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1241 assert(ThreadIDVar->getType()->isPointerType() && 1242 "thread id variable must be of type kmp_int32 *"); 1243 CodeGenFunction CGF(CGM, true); 1244 bool HasCancel = false; 1245 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1246 HasCancel = OPD->hasCancel(); 1247 else if (const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D)) 1248 HasCancel = OPD->hasCancel(); 1249 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1250 HasCancel = OPSD->hasCancel(); 1251 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1252 HasCancel = OPFD->hasCancel(); 1253 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1254 HasCancel = OPFD->hasCancel(); 1255 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1256 HasCancel = OPFD->hasCancel(); 1257 else if (const auto *OPFD = 1258 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1259 HasCancel = OPFD->hasCancel(); 1260 else if (const auto *OPFD = 1261 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1262 HasCancel = OPFD->hasCancel(); 1263 1264 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1265 // parallel region to make cancellation barriers work properly. 1266 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); 1267 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel); 1268 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1269 HasCancel, OutlinedHelperName); 1270 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1271 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1272 } 1273 1274 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1275 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1276 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1277 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1278 return emitParallelOrTeamsOutlinedFunction( 1279 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1280 } 1281 1282 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1283 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1284 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1285 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1286 return emitParallelOrTeamsOutlinedFunction( 1287 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1288 } 1289 1290 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1291 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1292 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1293 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1294 bool Tied, unsigned &NumberOfParts) { 1295 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1296 PrePostActionTy &) { 1297 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1298 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1299 llvm::Value *TaskArgs[] = { 1300 UpLoc, ThreadID, 1301 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1302 TaskTVar->getType()->castAs<PointerType>()) 1303 .getPointer(CGF)}; 1304 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1305 CGM.getModule(), OMPRTL___kmpc_omp_task), 1306 TaskArgs); 1307 }; 1308 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1309 UntiedCodeGen); 1310 CodeGen.setAction(Action); 1311 assert(!ThreadIDVar->getType()->isPointerType() && 1312 "thread id variable must be of type kmp_int32 for tasks"); 1313 const OpenMPDirectiveKind Region = 1314 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1315 : OMPD_task; 1316 const CapturedStmt *CS = D.getCapturedStmt(Region); 1317 bool HasCancel = false; 1318 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1319 HasCancel = TD->hasCancel(); 1320 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1321 HasCancel = TD->hasCancel(); 1322 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1323 HasCancel = TD->hasCancel(); 1324 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1325 HasCancel = TD->hasCancel(); 1326 1327 CodeGenFunction CGF(CGM, true); 1328 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1329 InnermostKind, HasCancel, Action); 1330 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1331 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1332 if (!Tied) 1333 NumberOfParts = Action.getNumberOfParts(); 1334 return Res; 1335 } 1336 1337 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1338 const RecordDecl *RD, const CGRecordLayout &RL, 1339 ArrayRef<llvm::Constant *> Data) { 1340 llvm::StructType *StructTy = RL.getLLVMType(); 1341 unsigned PrevIdx = 0; 1342 ConstantInitBuilder CIBuilder(CGM); 1343 auto DI = Data.begin(); 1344 for (const FieldDecl *FD : RD->fields()) { 1345 unsigned Idx = RL.getLLVMFieldNo(FD); 1346 // Fill the alignment. 1347 for (unsigned I = PrevIdx; I < Idx; ++I) 1348 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1349 PrevIdx = Idx + 1; 1350 Fields.add(*DI); 1351 ++DI; 1352 } 1353 } 1354 1355 template <class... As> 1356 static llvm::GlobalVariable * 1357 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1358 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1359 As &&... Args) { 1360 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1361 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1362 ConstantInitBuilder CIBuilder(CGM); 1363 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1364 buildStructValue(Fields, CGM, RD, RL, Data); 1365 return Fields.finishAndCreateGlobal( 1366 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1367 std::forward<As>(Args)...); 1368 } 1369 1370 template <typename T> 1371 static void 1372 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1373 ArrayRef<llvm::Constant *> Data, 1374 T &Parent) { 1375 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1376 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1377 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1378 buildStructValue(Fields, CGM, RD, RL, Data); 1379 Fields.finishAndAddTo(Parent); 1380 } 1381 1382 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1383 bool AtCurrentPoint) { 1384 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1385 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1386 1387 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1388 if (AtCurrentPoint) { 1389 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1390 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1391 } else { 1392 Elem.second.ServiceInsertPt = 1393 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1394 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1395 } 1396 } 1397 1398 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1399 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1400 if (Elem.second.ServiceInsertPt) { 1401 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1402 Elem.second.ServiceInsertPt = nullptr; 1403 Ptr->eraseFromParent(); 1404 } 1405 } 1406 1407 static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, 1408 SourceLocation Loc, 1409 SmallString<128> &Buffer) { 1410 llvm::raw_svector_ostream OS(Buffer); 1411 // Build debug location 1412 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1413 OS << ";" << PLoc.getFilename() << ";"; 1414 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1415 OS << FD->getQualifiedNameAsString(); 1416 OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1417 return OS.str(); 1418 } 1419 1420 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1421 SourceLocation Loc, 1422 unsigned Flags) { 1423 llvm::Constant *SrcLocStr; 1424 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1425 Loc.isInvalid()) { 1426 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(); 1427 } else { 1428 std::string FunctionName = ""; 1429 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1430 FunctionName = FD->getQualifiedNameAsString(); 1431 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1432 const char *FileName = PLoc.getFilename(); 1433 unsigned Line = PLoc.getLine(); 1434 unsigned Column = PLoc.getColumn(); 1435 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FunctionName.c_str(), FileName, 1436 Line, Column); 1437 } 1438 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1439 return OMPBuilder.getOrCreateIdent(SrcLocStr, llvm::omp::IdentFlag(Flags), 1440 Reserved2Flags); 1441 } 1442 1443 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1444 SourceLocation Loc) { 1445 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1446 // If the OpenMPIRBuilder is used we need to use it for all thread id calls as 1447 // the clang invariants used below might be broken. 1448 if (CGM.getLangOpts().OpenMPIRBuilder) { 1449 SmallString<128> Buffer; 1450 OMPBuilder.updateToLocation(CGF.Builder.saveIP()); 1451 auto *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr( 1452 getIdentStringFromSourceLocation(CGF, Loc, Buffer)); 1453 return OMPBuilder.getOrCreateThreadID( 1454 OMPBuilder.getOrCreateIdent(SrcLocStr)); 1455 } 1456 1457 llvm::Value *ThreadID = nullptr; 1458 // Check whether we've already cached a load of the thread id in this 1459 // function. 1460 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1461 if (I != OpenMPLocThreadIDMap.end()) { 1462 ThreadID = I->second.ThreadID; 1463 if (ThreadID != nullptr) 1464 return ThreadID; 1465 } 1466 // If exceptions are enabled, do not use parameter to avoid possible crash. 1467 if (auto *OMPRegionInfo = 1468 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1469 if (OMPRegionInfo->getThreadIDVariable()) { 1470 // Check if this an outlined function with thread id passed as argument. 1471 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1472 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1473 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1474 !CGF.getLangOpts().CXXExceptions || 1475 CGF.Builder.GetInsertBlock() == TopBlock || 1476 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1477 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1478 TopBlock || 1479 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1480 CGF.Builder.GetInsertBlock()) { 1481 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1482 // If value loaded in entry block, cache it and use it everywhere in 1483 // function. 1484 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1485 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1486 Elem.second.ThreadID = ThreadID; 1487 } 1488 return ThreadID; 1489 } 1490 } 1491 } 1492 1493 // This is not an outlined function region - need to call __kmpc_int32 1494 // kmpc_global_thread_num(ident_t *loc). 1495 // Generate thread id value and cache this value for use across the 1496 // function. 1497 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1498 if (!Elem.second.ServiceInsertPt) 1499 setLocThreadIdInsertPt(CGF); 1500 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1501 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1502 llvm::CallInst *Call = CGF.Builder.CreateCall( 1503 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 1504 OMPRTL___kmpc_global_thread_num), 1505 emitUpdateLocation(CGF, Loc)); 1506 Call->setCallingConv(CGF.getRuntimeCC()); 1507 Elem.second.ThreadID = Call; 1508 return Call; 1509 } 1510 1511 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1512 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1513 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1514 clearLocThreadIdInsertPt(CGF); 1515 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1516 } 1517 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1518 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1519 UDRMap.erase(D); 1520 FunctionUDRMap.erase(CGF.CurFn); 1521 } 1522 auto I = FunctionUDMMap.find(CGF.CurFn); 1523 if (I != FunctionUDMMap.end()) { 1524 for(const auto *D : I->second) 1525 UDMMap.erase(D); 1526 FunctionUDMMap.erase(I); 1527 } 1528 LastprivateConditionalToTypes.erase(CGF.CurFn); 1529 } 1530 1531 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1532 return OMPBuilder.IdentPtr; 1533 } 1534 1535 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1536 if (!Kmpc_MicroTy) { 1537 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1538 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1539 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1540 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1541 } 1542 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1543 } 1544 1545 llvm::FunctionCallee 1546 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 1547 assert((IVSize == 32 || IVSize == 64) && 1548 "IV size is not compatible with the omp runtime"); 1549 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 1550 : "__kmpc_for_static_init_4u") 1551 : (IVSigned ? "__kmpc_for_static_init_8" 1552 : "__kmpc_for_static_init_8u"); 1553 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1554 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1555 llvm::Type *TypeParams[] = { 1556 getIdentTyPointerTy(), // loc 1557 CGM.Int32Ty, // tid 1558 CGM.Int32Ty, // schedtype 1559 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1560 PtrTy, // p_lower 1561 PtrTy, // p_upper 1562 PtrTy, // p_stride 1563 ITy, // incr 1564 ITy // chunk 1565 }; 1566 auto *FnTy = 1567 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1568 return CGM.CreateRuntimeFunction(FnTy, Name); 1569 } 1570 1571 llvm::FunctionCallee 1572 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 1573 assert((IVSize == 32 || IVSize == 64) && 1574 "IV size is not compatible with the omp runtime"); 1575 StringRef Name = 1576 IVSize == 32 1577 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 1578 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 1579 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1580 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 1581 CGM.Int32Ty, // tid 1582 CGM.Int32Ty, // schedtype 1583 ITy, // lower 1584 ITy, // upper 1585 ITy, // stride 1586 ITy // chunk 1587 }; 1588 auto *FnTy = 1589 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1590 return CGM.CreateRuntimeFunction(FnTy, Name); 1591 } 1592 1593 llvm::FunctionCallee 1594 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 1595 assert((IVSize == 32 || IVSize == 64) && 1596 "IV size is not compatible with the omp runtime"); 1597 StringRef Name = 1598 IVSize == 32 1599 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 1600 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 1601 llvm::Type *TypeParams[] = { 1602 getIdentTyPointerTy(), // loc 1603 CGM.Int32Ty, // tid 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::createDispatchNextFunction(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_next_4" : "__kmpc_dispatch_next_4u") 1617 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 1618 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1619 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1620 llvm::Type *TypeParams[] = { 1621 getIdentTyPointerTy(), // loc 1622 CGM.Int32Ty, // tid 1623 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1624 PtrTy, // p_lower 1625 PtrTy, // p_upper 1626 PtrTy // p_stride 1627 }; 1628 auto *FnTy = 1629 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1630 return CGM.CreateRuntimeFunction(FnTy, Name); 1631 } 1632 1633 /// Obtain information that uniquely identifies a target entry. This 1634 /// consists of the file and device IDs as well as line number associated with 1635 /// the relevant entry source location. 1636 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 1637 unsigned &DeviceID, unsigned &FileID, 1638 unsigned &LineNum) { 1639 SourceManager &SM = C.getSourceManager(); 1640 1641 // The loc should be always valid and have a file ID (the user cannot use 1642 // #pragma directives in macros) 1643 1644 assert(Loc.isValid() && "Source location is expected to be always valid."); 1645 1646 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 1647 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1648 1649 llvm::sys::fs::UniqueID ID; 1650 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 1651 SM.getDiagnostics().Report(diag::err_cannot_open_file) 1652 << PLoc.getFilename() << EC.message(); 1653 1654 DeviceID = ID.getDevice(); 1655 FileID = ID.getFile(); 1656 LineNum = PLoc.getLine(); 1657 } 1658 1659 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 1660 if (CGM.getLangOpts().OpenMPSimd) 1661 return Address::invalid(); 1662 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1663 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1664 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 1665 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1666 HasRequiresUnifiedSharedMemory))) { 1667 SmallString<64> PtrName; 1668 { 1669 llvm::raw_svector_ostream OS(PtrName); 1670 OS << CGM.getMangledName(GlobalDecl(VD)); 1671 if (!VD->isExternallyVisible()) { 1672 unsigned DeviceID, FileID, Line; 1673 getTargetEntryUniqueInfo(CGM.getContext(), 1674 VD->getCanonicalDecl()->getBeginLoc(), 1675 DeviceID, FileID, Line); 1676 OS << llvm::format("_%x", FileID); 1677 } 1678 OS << "_decl_tgt_ref_ptr"; 1679 } 1680 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 1681 if (!Ptr) { 1682 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 1683 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 1684 PtrName); 1685 1686 auto *GV = cast<llvm::GlobalVariable>(Ptr); 1687 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 1688 1689 if (!CGM.getLangOpts().OpenMPIsDevice) 1690 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 1691 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 1692 } 1693 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 1694 } 1695 return Address::invalid(); 1696 } 1697 1698 llvm::Constant * 1699 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 1700 assert(!CGM.getLangOpts().OpenMPUseTLS || 1701 !CGM.getContext().getTargetInfo().isTLSSupported()); 1702 // Lookup the entry, lazily creating it if necessary. 1703 std::string Suffix = getName({"cache", ""}); 1704 return getOrCreateInternalVariable( 1705 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 1706 } 1707 1708 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 1709 const VarDecl *VD, 1710 Address VDAddr, 1711 SourceLocation Loc) { 1712 if (CGM.getLangOpts().OpenMPUseTLS && 1713 CGM.getContext().getTargetInfo().isTLSSupported()) 1714 return VDAddr; 1715 1716 llvm::Type *VarTy = VDAddr.getElementType(); 1717 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1718 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1719 CGM.Int8PtrTy), 1720 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 1721 getOrCreateThreadPrivateCache(VD)}; 1722 return Address(CGF.EmitRuntimeCall( 1723 OMPBuilder.getOrCreateRuntimeFunction( 1724 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 1725 Args), 1726 VDAddr.getAlignment()); 1727 } 1728 1729 void CGOpenMPRuntime::emitThreadPrivateVarInit( 1730 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 1731 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 1732 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 1733 // library. 1734 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 1735 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1736 CGM.getModule(), OMPRTL___kmpc_global_thread_num), 1737 OMPLoc); 1738 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 1739 // to register constructor/destructor for variable. 1740 llvm::Value *Args[] = { 1741 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 1742 Ctor, CopyCtor, Dtor}; 1743 CGF.EmitRuntimeCall( 1744 OMPBuilder.getOrCreateRuntimeFunction( 1745 CGM.getModule(), OMPRTL___kmpc_threadprivate_register), 1746 Args); 1747 } 1748 1749 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 1750 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 1751 bool PerformInit, CodeGenFunction *CGF) { 1752 if (CGM.getLangOpts().OpenMPUseTLS && 1753 CGM.getContext().getTargetInfo().isTLSSupported()) 1754 return nullptr; 1755 1756 VD = VD->getDefinition(CGM.getContext()); 1757 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 1758 QualType ASTTy = VD->getType(); 1759 1760 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 1761 const Expr *Init = VD->getAnyInitializer(); 1762 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1763 // Generate function that re-emits the declaration's initializer into the 1764 // threadprivate copy of the variable VD 1765 CodeGenFunction CtorCGF(CGM); 1766 FunctionArgList Args; 1767 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1768 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1769 ImplicitParamDecl::Other); 1770 Args.push_back(&Dst); 1771 1772 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1773 CGM.getContext().VoidPtrTy, Args); 1774 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1775 std::string Name = getName({"__kmpc_global_ctor_", ""}); 1776 llvm::Function *Fn = 1777 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1778 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 1779 Args, Loc, Loc); 1780 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 1781 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1782 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1783 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 1784 Arg = CtorCGF.Builder.CreateElementBitCast( 1785 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 1786 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1787 /*IsInitializer=*/true); 1788 ArgVal = CtorCGF.EmitLoadOfScalar( 1789 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1790 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1791 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1792 CtorCGF.FinishFunction(); 1793 Ctor = Fn; 1794 } 1795 if (VD->getType().isDestructedType() != QualType::DK_none) { 1796 // Generate function that emits destructor call for the threadprivate copy 1797 // of the variable VD 1798 CodeGenFunction DtorCGF(CGM); 1799 FunctionArgList Args; 1800 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1801 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1802 ImplicitParamDecl::Other); 1803 Args.push_back(&Dst); 1804 1805 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1806 CGM.getContext().VoidTy, Args); 1807 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1808 std::string Name = getName({"__kmpc_global_dtor_", ""}); 1809 llvm::Function *Fn = 1810 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1811 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1812 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1813 Loc, Loc); 1814 // Create a scope with an artificial location for the body of this function. 1815 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1816 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 1817 DtorCGF.GetAddrOfLocalVar(&Dst), 1818 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 1819 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 1820 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1821 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1822 DtorCGF.FinishFunction(); 1823 Dtor = Fn; 1824 } 1825 // Do not emit init function if it is not required. 1826 if (!Ctor && !Dtor) 1827 return nullptr; 1828 1829 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1830 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1831 /*isVarArg=*/false) 1832 ->getPointerTo(); 1833 // Copying constructor for the threadprivate variable. 1834 // Must be NULL - reserved by runtime, but currently it requires that this 1835 // parameter is always NULL. Otherwise it fires assertion. 1836 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1837 if (Ctor == nullptr) { 1838 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1839 /*isVarArg=*/false) 1840 ->getPointerTo(); 1841 Ctor = llvm::Constant::getNullValue(CtorTy); 1842 } 1843 if (Dtor == nullptr) { 1844 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1845 /*isVarArg=*/false) 1846 ->getPointerTo(); 1847 Dtor = llvm::Constant::getNullValue(DtorTy); 1848 } 1849 if (!CGF) { 1850 auto *InitFunctionTy = 1851 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1852 std::string Name = getName({"__omp_threadprivate_init_", ""}); 1853 llvm::Function *InitFunction = CGM.CreateGlobalInitOrCleanUpFunction( 1854 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 1855 CodeGenFunction InitCGF(CGM); 1856 FunctionArgList ArgList; 1857 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1858 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1859 Loc, Loc); 1860 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1861 InitCGF.FinishFunction(); 1862 return InitFunction; 1863 } 1864 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1865 } 1866 return nullptr; 1867 } 1868 1869 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 1870 llvm::GlobalVariable *Addr, 1871 bool PerformInit) { 1872 if (CGM.getLangOpts().OMPTargetTriples.empty() && 1873 !CGM.getLangOpts().OpenMPIsDevice) 1874 return false; 1875 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1876 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1877 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 1878 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1879 HasRequiresUnifiedSharedMemory)) 1880 return CGM.getLangOpts().OpenMPIsDevice; 1881 VD = VD->getDefinition(CGM.getContext()); 1882 assert(VD && "Unknown VarDecl"); 1883 1884 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 1885 return CGM.getLangOpts().OpenMPIsDevice; 1886 1887 QualType ASTTy = VD->getType(); 1888 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 1889 1890 // Produce the unique prefix to identify the new target regions. We use 1891 // the source location of the variable declaration which we know to not 1892 // conflict with any target region. 1893 unsigned DeviceID; 1894 unsigned FileID; 1895 unsigned Line; 1896 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 1897 SmallString<128> Buffer, Out; 1898 { 1899 llvm::raw_svector_ostream OS(Buffer); 1900 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 1901 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 1902 } 1903 1904 const Expr *Init = VD->getAnyInitializer(); 1905 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1906 llvm::Constant *Ctor; 1907 llvm::Constant *ID; 1908 if (CGM.getLangOpts().OpenMPIsDevice) { 1909 // Generate function that re-emits the declaration's initializer into 1910 // the threadprivate copy of the variable VD 1911 CodeGenFunction CtorCGF(CGM); 1912 1913 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1914 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1915 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1916 FTy, Twine(Buffer, "_ctor"), FI, Loc); 1917 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 1918 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1919 FunctionArgList(), Loc, Loc); 1920 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 1921 CtorCGF.EmitAnyExprToMem(Init, 1922 Address(Addr, CGM.getContext().getDeclAlign(VD)), 1923 Init->getType().getQualifiers(), 1924 /*IsInitializer=*/true); 1925 CtorCGF.FinishFunction(); 1926 Ctor = Fn; 1927 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1928 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 1929 } else { 1930 Ctor = new llvm::GlobalVariable( 1931 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1932 llvm::GlobalValue::PrivateLinkage, 1933 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 1934 ID = Ctor; 1935 } 1936 1937 // Register the information for the entry associated with the constructor. 1938 Out.clear(); 1939 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 1940 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 1941 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 1942 } 1943 if (VD->getType().isDestructedType() != QualType::DK_none) { 1944 llvm::Constant *Dtor; 1945 llvm::Constant *ID; 1946 if (CGM.getLangOpts().OpenMPIsDevice) { 1947 // Generate function that emits destructor call for the threadprivate 1948 // copy of the variable VD 1949 CodeGenFunction DtorCGF(CGM); 1950 1951 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1952 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1953 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1954 FTy, Twine(Buffer, "_dtor"), FI, Loc); 1955 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1956 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1957 FunctionArgList(), Loc, Loc); 1958 // Create a scope with an artificial location for the body of this 1959 // function. 1960 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1961 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 1962 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1963 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1964 DtorCGF.FinishFunction(); 1965 Dtor = Fn; 1966 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1967 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 1968 } else { 1969 Dtor = new llvm::GlobalVariable( 1970 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1971 llvm::GlobalValue::PrivateLinkage, 1972 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 1973 ID = Dtor; 1974 } 1975 // Register the information for the entry associated with the destructor. 1976 Out.clear(); 1977 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 1978 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 1979 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 1980 } 1981 return CGM.getLangOpts().OpenMPIsDevice; 1982 } 1983 1984 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 1985 QualType VarType, 1986 StringRef Name) { 1987 std::string Suffix = getName({"artificial", ""}); 1988 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 1989 llvm::Value *GAddr = 1990 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 1991 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 1992 CGM.getTarget().isTLSSupported()) { 1993 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 1994 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 1995 } 1996 std::string CacheSuffix = getName({"cache", ""}); 1997 llvm::Value *Args[] = { 1998 emitUpdateLocation(CGF, SourceLocation()), 1999 getThreadID(CGF, SourceLocation()), 2000 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2001 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2002 /*isSigned=*/false), 2003 getOrCreateInternalVariable( 2004 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2005 return Address( 2006 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2007 CGF.EmitRuntimeCall( 2008 OMPBuilder.getOrCreateRuntimeFunction( 2009 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 2010 Args), 2011 VarLVType->getPointerTo(/*AddrSpace=*/0)), 2012 CGM.getContext().getTypeAlignInChars(VarType)); 2013 } 2014 2015 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 2016 const RegionCodeGenTy &ThenGen, 2017 const RegionCodeGenTy &ElseGen) { 2018 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 2019 2020 // If the condition constant folds and can be elided, try to avoid emitting 2021 // the condition and the dead arm of the if/else. 2022 bool CondConstant; 2023 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 2024 if (CondConstant) 2025 ThenGen(CGF); 2026 else 2027 ElseGen(CGF); 2028 return; 2029 } 2030 2031 // Otherwise, the condition did not fold, or we couldn't elide it. Just 2032 // emit the conditional branch. 2033 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2034 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 2035 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 2036 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 2037 2038 // Emit the 'then' code. 2039 CGF.EmitBlock(ThenBlock); 2040 ThenGen(CGF); 2041 CGF.EmitBranch(ContBlock); 2042 // Emit the 'else' code if present. 2043 // There is no need to emit line number for unconditional branch. 2044 (void)ApplyDebugLocation::CreateEmpty(CGF); 2045 CGF.EmitBlock(ElseBlock); 2046 ElseGen(CGF); 2047 // There is no need to emit line number for unconditional branch. 2048 (void)ApplyDebugLocation::CreateEmpty(CGF); 2049 CGF.EmitBranch(ContBlock); 2050 // Emit the continuation block for code after the if. 2051 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 2052 } 2053 2054 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 2055 llvm::Function *OutlinedFn, 2056 ArrayRef<llvm::Value *> CapturedVars, 2057 const Expr *IfCond) { 2058 if (!CGF.HaveInsertPoint()) 2059 return; 2060 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 2061 auto &M = CGM.getModule(); 2062 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc, 2063 this](CodeGenFunction &CGF, PrePostActionTy &) { 2064 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 2065 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2066 llvm::Value *Args[] = { 2067 RTLoc, 2068 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 2069 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 2070 llvm::SmallVector<llvm::Value *, 16> RealArgs; 2071 RealArgs.append(std::begin(Args), std::end(Args)); 2072 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 2073 2074 llvm::FunctionCallee RTLFn = 2075 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call); 2076 CGF.EmitRuntimeCall(RTLFn, RealArgs); 2077 }; 2078 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc, 2079 this](CodeGenFunction &CGF, PrePostActionTy &) { 2080 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2081 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 2082 // Build calls: 2083 // __kmpc_serialized_parallel(&Loc, GTid); 2084 llvm::Value *Args[] = {RTLoc, ThreadID}; 2085 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2086 M, OMPRTL___kmpc_serialized_parallel), 2087 Args); 2088 2089 // OutlinedFn(>id, &zero_bound, CapturedStruct); 2090 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 2091 Address ZeroAddrBound = 2092 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 2093 /*Name=*/".bound.zero.addr"); 2094 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 2095 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 2096 // ThreadId for serialized parallels is 0. 2097 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 2098 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 2099 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 2100 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 2101 2102 // __kmpc_end_serialized_parallel(&Loc, GTid); 2103 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 2104 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2105 M, OMPRTL___kmpc_end_serialized_parallel), 2106 EndArgs); 2107 }; 2108 if (IfCond) { 2109 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 2110 } else { 2111 RegionCodeGenTy ThenRCG(ThenGen); 2112 ThenRCG(CGF); 2113 } 2114 } 2115 2116 // If we're inside an (outlined) parallel region, use the region info's 2117 // thread-ID variable (it is passed in a first argument of the outlined function 2118 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 2119 // regular serial code region, get thread ID by calling kmp_int32 2120 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 2121 // return the address of that temp. 2122 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 2123 SourceLocation Loc) { 2124 if (auto *OMPRegionInfo = 2125 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2126 if (OMPRegionInfo->getThreadIDVariable()) 2127 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 2128 2129 llvm::Value *ThreadID = getThreadID(CGF, Loc); 2130 QualType Int32Ty = 2131 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 2132 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 2133 CGF.EmitStoreOfScalar(ThreadID, 2134 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 2135 2136 return ThreadIDTemp; 2137 } 2138 2139 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 2140 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 2141 SmallString<256> Buffer; 2142 llvm::raw_svector_ostream Out(Buffer); 2143 Out << Name; 2144 StringRef RuntimeName = Out.str(); 2145 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 2146 if (Elem.second) { 2147 assert(Elem.second->getType()->getPointerElementType() == Ty && 2148 "OMP internal variable has different type than requested"); 2149 return &*Elem.second; 2150 } 2151 2152 return Elem.second = new llvm::GlobalVariable( 2153 CGM.getModule(), Ty, /*IsConstant*/ false, 2154 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 2155 Elem.first(), /*InsertBefore=*/nullptr, 2156 llvm::GlobalValue::NotThreadLocal, AddressSpace); 2157 } 2158 2159 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 2160 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 2161 std::string Name = getName({Prefix, "var"}); 2162 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 2163 } 2164 2165 namespace { 2166 /// Common pre(post)-action for different OpenMP constructs. 2167 class CommonActionTy final : public PrePostActionTy { 2168 llvm::FunctionCallee EnterCallee; 2169 ArrayRef<llvm::Value *> EnterArgs; 2170 llvm::FunctionCallee ExitCallee; 2171 ArrayRef<llvm::Value *> ExitArgs; 2172 bool Conditional; 2173 llvm::BasicBlock *ContBlock = nullptr; 2174 2175 public: 2176 CommonActionTy(llvm::FunctionCallee EnterCallee, 2177 ArrayRef<llvm::Value *> EnterArgs, 2178 llvm::FunctionCallee ExitCallee, 2179 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 2180 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 2181 ExitArgs(ExitArgs), Conditional(Conditional) {} 2182 void Enter(CodeGenFunction &CGF) override { 2183 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 2184 if (Conditional) { 2185 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 2186 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2187 ContBlock = CGF.createBasicBlock("omp_if.end"); 2188 // Generate the branch (If-stmt) 2189 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 2190 CGF.EmitBlock(ThenBlock); 2191 } 2192 } 2193 void Done(CodeGenFunction &CGF) { 2194 // Emit the rest of blocks/branches 2195 CGF.EmitBranch(ContBlock); 2196 CGF.EmitBlock(ContBlock, true); 2197 } 2198 void Exit(CodeGenFunction &CGF) override { 2199 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 2200 } 2201 }; 2202 } // anonymous namespace 2203 2204 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 2205 StringRef CriticalName, 2206 const RegionCodeGenTy &CriticalOpGen, 2207 SourceLocation Loc, const Expr *Hint) { 2208 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 2209 // CriticalOpGen(); 2210 // __kmpc_end_critical(ident_t *, gtid, Lock); 2211 // Prepare arguments and build a call to __kmpc_critical 2212 if (!CGF.HaveInsertPoint()) 2213 return; 2214 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2215 getCriticalRegionLock(CriticalName)}; 2216 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 2217 std::end(Args)); 2218 if (Hint) { 2219 EnterArgs.push_back(CGF.Builder.CreateIntCast( 2220 CGF.EmitScalarExpr(Hint), CGM.Int32Ty, /*isSigned=*/false)); 2221 } 2222 CommonActionTy Action( 2223 OMPBuilder.getOrCreateRuntimeFunction( 2224 CGM.getModule(), 2225 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical), 2226 EnterArgs, 2227 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2228 OMPRTL___kmpc_end_critical), 2229 Args); 2230 CriticalOpGen.setAction(Action); 2231 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 2232 } 2233 2234 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 2235 const RegionCodeGenTy &MasterOpGen, 2236 SourceLocation Loc) { 2237 if (!CGF.HaveInsertPoint()) 2238 return; 2239 // if(__kmpc_master(ident_t *, gtid)) { 2240 // MasterOpGen(); 2241 // __kmpc_end_master(ident_t *, gtid); 2242 // } 2243 // Prepare arguments and build a call to __kmpc_master 2244 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2245 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2246 CGM.getModule(), OMPRTL___kmpc_master), 2247 Args, 2248 OMPBuilder.getOrCreateRuntimeFunction( 2249 CGM.getModule(), OMPRTL___kmpc_end_master), 2250 Args, 2251 /*Conditional=*/true); 2252 MasterOpGen.setAction(Action); 2253 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 2254 Action.Done(CGF); 2255 } 2256 2257 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 2258 SourceLocation Loc) { 2259 if (!CGF.HaveInsertPoint()) 2260 return; 2261 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2262 OMPBuilder.CreateTaskyield(CGF.Builder); 2263 } else { 2264 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 2265 llvm::Value *Args[] = { 2266 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2267 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 2268 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2269 CGM.getModule(), OMPRTL___kmpc_omp_taskyield), 2270 Args); 2271 } 2272 2273 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2274 Region->emitUntiedSwitch(CGF); 2275 } 2276 2277 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 2278 const RegionCodeGenTy &TaskgroupOpGen, 2279 SourceLocation Loc) { 2280 if (!CGF.HaveInsertPoint()) 2281 return; 2282 // __kmpc_taskgroup(ident_t *, gtid); 2283 // TaskgroupOpGen(); 2284 // __kmpc_end_taskgroup(ident_t *, gtid); 2285 // Prepare arguments and build a call to __kmpc_taskgroup 2286 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2287 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2288 CGM.getModule(), OMPRTL___kmpc_taskgroup), 2289 Args, 2290 OMPBuilder.getOrCreateRuntimeFunction( 2291 CGM.getModule(), OMPRTL___kmpc_end_taskgroup), 2292 Args); 2293 TaskgroupOpGen.setAction(Action); 2294 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 2295 } 2296 2297 /// Given an array of pointers to variables, project the address of a 2298 /// given variable. 2299 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 2300 unsigned Index, const VarDecl *Var) { 2301 // Pull out the pointer to the variable. 2302 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 2303 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 2304 2305 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 2306 Addr = CGF.Builder.CreateElementBitCast( 2307 Addr, CGF.ConvertTypeForMem(Var->getType())); 2308 return Addr; 2309 } 2310 2311 static llvm::Value *emitCopyprivateCopyFunction( 2312 CodeGenModule &CGM, llvm::Type *ArgsType, 2313 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 2314 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 2315 SourceLocation Loc) { 2316 ASTContext &C = CGM.getContext(); 2317 // void copy_func(void *LHSArg, void *RHSArg); 2318 FunctionArgList Args; 2319 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2320 ImplicitParamDecl::Other); 2321 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2322 ImplicitParamDecl::Other); 2323 Args.push_back(&LHSArg); 2324 Args.push_back(&RHSArg); 2325 const auto &CGFI = 2326 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2327 std::string Name = 2328 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 2329 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 2330 llvm::GlobalValue::InternalLinkage, Name, 2331 &CGM.getModule()); 2332 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 2333 Fn->setDoesNotRecurse(); 2334 CodeGenFunction CGF(CGM); 2335 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 2336 // Dest = (void*[n])(LHSArg); 2337 // Src = (void*[n])(RHSArg); 2338 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2339 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 2340 ArgsType), CGF.getPointerAlign()); 2341 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2342 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 2343 ArgsType), CGF.getPointerAlign()); 2344 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 2345 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 2346 // ... 2347 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 2348 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 2349 const auto *DestVar = 2350 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 2351 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 2352 2353 const auto *SrcVar = 2354 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 2355 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 2356 2357 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 2358 QualType Type = VD->getType(); 2359 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 2360 } 2361 CGF.FinishFunction(); 2362 return Fn; 2363 } 2364 2365 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 2366 const RegionCodeGenTy &SingleOpGen, 2367 SourceLocation Loc, 2368 ArrayRef<const Expr *> CopyprivateVars, 2369 ArrayRef<const Expr *> SrcExprs, 2370 ArrayRef<const Expr *> DstExprs, 2371 ArrayRef<const Expr *> AssignmentOps) { 2372 if (!CGF.HaveInsertPoint()) 2373 return; 2374 assert(CopyprivateVars.size() == SrcExprs.size() && 2375 CopyprivateVars.size() == DstExprs.size() && 2376 CopyprivateVars.size() == AssignmentOps.size()); 2377 ASTContext &C = CGM.getContext(); 2378 // int32 did_it = 0; 2379 // if(__kmpc_single(ident_t *, gtid)) { 2380 // SingleOpGen(); 2381 // __kmpc_end_single(ident_t *, gtid); 2382 // did_it = 1; 2383 // } 2384 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2385 // <copy_func>, did_it); 2386 2387 Address DidIt = Address::invalid(); 2388 if (!CopyprivateVars.empty()) { 2389 // int32 did_it = 0; 2390 QualType KmpInt32Ty = 2391 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2392 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 2393 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 2394 } 2395 // Prepare arguments and build a call to __kmpc_single 2396 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2397 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2398 CGM.getModule(), OMPRTL___kmpc_single), 2399 Args, 2400 OMPBuilder.getOrCreateRuntimeFunction( 2401 CGM.getModule(), OMPRTL___kmpc_end_single), 2402 Args, 2403 /*Conditional=*/true); 2404 SingleOpGen.setAction(Action); 2405 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 2406 if (DidIt.isValid()) { 2407 // did_it = 1; 2408 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 2409 } 2410 Action.Done(CGF); 2411 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2412 // <copy_func>, did_it); 2413 if (DidIt.isValid()) { 2414 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 2415 QualType CopyprivateArrayTy = C.getConstantArrayType( 2416 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 2417 /*IndexTypeQuals=*/0); 2418 // Create a list of all private variables for copyprivate. 2419 Address CopyprivateList = 2420 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 2421 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 2422 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 2423 CGF.Builder.CreateStore( 2424 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2425 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 2426 CGF.VoidPtrTy), 2427 Elem); 2428 } 2429 // Build function that copies private values from single region to all other 2430 // threads in the corresponding parallel region. 2431 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 2432 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 2433 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 2434 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 2435 Address CL = 2436 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 2437 CGF.VoidPtrTy); 2438 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 2439 llvm::Value *Args[] = { 2440 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 2441 getThreadID(CGF, Loc), // i32 <gtid> 2442 BufSize, // size_t <buf_size> 2443 CL.getPointer(), // void *<copyprivate list> 2444 CpyFn, // void (*) (void *, void *) <copy_func> 2445 DidItVal // i32 did_it 2446 }; 2447 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2448 CGM.getModule(), OMPRTL___kmpc_copyprivate), 2449 Args); 2450 } 2451 } 2452 2453 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 2454 const RegionCodeGenTy &OrderedOpGen, 2455 SourceLocation Loc, bool IsThreads) { 2456 if (!CGF.HaveInsertPoint()) 2457 return; 2458 // __kmpc_ordered(ident_t *, gtid); 2459 // OrderedOpGen(); 2460 // __kmpc_end_ordered(ident_t *, gtid); 2461 // Prepare arguments and build a call to __kmpc_ordered 2462 if (IsThreads) { 2463 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2464 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2465 CGM.getModule(), OMPRTL___kmpc_ordered), 2466 Args, 2467 OMPBuilder.getOrCreateRuntimeFunction( 2468 CGM.getModule(), OMPRTL___kmpc_end_ordered), 2469 Args); 2470 OrderedOpGen.setAction(Action); 2471 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2472 return; 2473 } 2474 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2475 } 2476 2477 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 2478 unsigned Flags; 2479 if (Kind == OMPD_for) 2480 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 2481 else if (Kind == OMPD_sections) 2482 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 2483 else if (Kind == OMPD_single) 2484 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 2485 else if (Kind == OMPD_barrier) 2486 Flags = OMP_IDENT_BARRIER_EXPL; 2487 else 2488 Flags = OMP_IDENT_BARRIER_IMPL; 2489 return Flags; 2490 } 2491 2492 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 2493 CodeGenFunction &CGF, const OMPLoopDirective &S, 2494 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 2495 // Check if the loop directive is actually a doacross loop directive. In this 2496 // case choose static, 1 schedule. 2497 if (llvm::any_of( 2498 S.getClausesOfKind<OMPOrderedClause>(), 2499 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 2500 ScheduleKind = OMPC_SCHEDULE_static; 2501 // Chunk size is 1 in this case. 2502 llvm::APInt ChunkSize(32, 1); 2503 ChunkExpr = IntegerLiteral::Create( 2504 CGF.getContext(), ChunkSize, 2505 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 2506 SourceLocation()); 2507 } 2508 } 2509 2510 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 2511 OpenMPDirectiveKind Kind, bool EmitChecks, 2512 bool ForceSimpleCall) { 2513 // Check if we should use the OMPBuilder 2514 auto *OMPRegionInfo = 2515 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 2516 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2517 CGF.Builder.restoreIP(OMPBuilder.CreateBarrier( 2518 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 2519 return; 2520 } 2521 2522 if (!CGF.HaveInsertPoint()) 2523 return; 2524 // Build call __kmpc_cancel_barrier(loc, thread_id); 2525 // Build call __kmpc_barrier(loc, thread_id); 2526 unsigned Flags = getDefaultFlagsForBarriers(Kind); 2527 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 2528 // thread_id); 2529 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 2530 getThreadID(CGF, Loc)}; 2531 if (OMPRegionInfo) { 2532 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 2533 llvm::Value *Result = CGF.EmitRuntimeCall( 2534 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2535 OMPRTL___kmpc_cancel_barrier), 2536 Args); 2537 if (EmitChecks) { 2538 // if (__kmpc_cancel_barrier()) { 2539 // exit from construct; 2540 // } 2541 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2542 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 2543 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 2544 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2545 CGF.EmitBlock(ExitBB); 2546 // exit from construct; 2547 CodeGenFunction::JumpDest CancelDestination = 2548 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2549 CGF.EmitBranchThroughCleanup(CancelDestination); 2550 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2551 } 2552 return; 2553 } 2554 } 2555 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2556 CGM.getModule(), OMPRTL___kmpc_barrier), 2557 Args); 2558 } 2559 2560 /// Map the OpenMP loop schedule to the runtime enumeration. 2561 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 2562 bool Chunked, bool Ordered) { 2563 switch (ScheduleKind) { 2564 case OMPC_SCHEDULE_static: 2565 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 2566 : (Ordered ? OMP_ord_static : OMP_sch_static); 2567 case OMPC_SCHEDULE_dynamic: 2568 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 2569 case OMPC_SCHEDULE_guided: 2570 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 2571 case OMPC_SCHEDULE_runtime: 2572 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 2573 case OMPC_SCHEDULE_auto: 2574 return Ordered ? OMP_ord_auto : OMP_sch_auto; 2575 case OMPC_SCHEDULE_unknown: 2576 assert(!Chunked && "chunk was specified but schedule kind not known"); 2577 return Ordered ? OMP_ord_static : OMP_sch_static; 2578 } 2579 llvm_unreachable("Unexpected runtime schedule"); 2580 } 2581 2582 /// Map the OpenMP distribute schedule to the runtime enumeration. 2583 static OpenMPSchedType 2584 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 2585 // only static is allowed for dist_schedule 2586 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 2587 } 2588 2589 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 2590 bool Chunked) const { 2591 OpenMPSchedType Schedule = 2592 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2593 return Schedule == OMP_sch_static; 2594 } 2595 2596 bool CGOpenMPRuntime::isStaticNonchunked( 2597 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2598 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2599 return Schedule == OMP_dist_sch_static; 2600 } 2601 2602 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 2603 bool Chunked) const { 2604 OpenMPSchedType Schedule = 2605 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2606 return Schedule == OMP_sch_static_chunked; 2607 } 2608 2609 bool CGOpenMPRuntime::isStaticChunked( 2610 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2611 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2612 return Schedule == OMP_dist_sch_static_chunked; 2613 } 2614 2615 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 2616 OpenMPSchedType Schedule = 2617 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 2618 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 2619 return Schedule != OMP_sch_static; 2620 } 2621 2622 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 2623 OpenMPScheduleClauseModifier M1, 2624 OpenMPScheduleClauseModifier M2) { 2625 int Modifier = 0; 2626 switch (M1) { 2627 case OMPC_SCHEDULE_MODIFIER_monotonic: 2628 Modifier = OMP_sch_modifier_monotonic; 2629 break; 2630 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2631 Modifier = OMP_sch_modifier_nonmonotonic; 2632 break; 2633 case OMPC_SCHEDULE_MODIFIER_simd: 2634 if (Schedule == OMP_sch_static_chunked) 2635 Schedule = OMP_sch_static_balanced_chunked; 2636 break; 2637 case OMPC_SCHEDULE_MODIFIER_last: 2638 case OMPC_SCHEDULE_MODIFIER_unknown: 2639 break; 2640 } 2641 switch (M2) { 2642 case OMPC_SCHEDULE_MODIFIER_monotonic: 2643 Modifier = OMP_sch_modifier_monotonic; 2644 break; 2645 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2646 Modifier = OMP_sch_modifier_nonmonotonic; 2647 break; 2648 case OMPC_SCHEDULE_MODIFIER_simd: 2649 if (Schedule == OMP_sch_static_chunked) 2650 Schedule = OMP_sch_static_balanced_chunked; 2651 break; 2652 case OMPC_SCHEDULE_MODIFIER_last: 2653 case OMPC_SCHEDULE_MODIFIER_unknown: 2654 break; 2655 } 2656 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 2657 // If the static schedule kind is specified or if the ordered clause is 2658 // specified, and if the nonmonotonic modifier is not specified, the effect is 2659 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 2660 // modifier is specified, the effect is as if the nonmonotonic modifier is 2661 // specified. 2662 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 2663 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 2664 Schedule == OMP_sch_static_balanced_chunked || 2665 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 2666 Schedule == OMP_dist_sch_static_chunked || 2667 Schedule == OMP_dist_sch_static)) 2668 Modifier = OMP_sch_modifier_nonmonotonic; 2669 } 2670 return Schedule | Modifier; 2671 } 2672 2673 void CGOpenMPRuntime::emitForDispatchInit( 2674 CodeGenFunction &CGF, SourceLocation Loc, 2675 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 2676 bool Ordered, const DispatchRTInput &DispatchValues) { 2677 if (!CGF.HaveInsertPoint()) 2678 return; 2679 OpenMPSchedType Schedule = getRuntimeSchedule( 2680 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 2681 assert(Ordered || 2682 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 2683 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 2684 Schedule != OMP_sch_static_balanced_chunked)); 2685 // Call __kmpc_dispatch_init( 2686 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 2687 // kmp_int[32|64] lower, kmp_int[32|64] upper, 2688 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 2689 2690 // If the Chunk was not specified in the clause - use default value 1. 2691 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 2692 : CGF.Builder.getIntN(IVSize, 1); 2693 llvm::Value *Args[] = { 2694 emitUpdateLocation(CGF, Loc), 2695 getThreadID(CGF, Loc), 2696 CGF.Builder.getInt32(addMonoNonMonoModifier( 2697 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 2698 DispatchValues.LB, // Lower 2699 DispatchValues.UB, // Upper 2700 CGF.Builder.getIntN(IVSize, 1), // Stride 2701 Chunk // Chunk 2702 }; 2703 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 2704 } 2705 2706 static void emitForStaticInitCall( 2707 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 2708 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 2709 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 2710 const CGOpenMPRuntime::StaticRTInput &Values) { 2711 if (!CGF.HaveInsertPoint()) 2712 return; 2713 2714 assert(!Values.Ordered); 2715 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 2716 Schedule == OMP_sch_static_balanced_chunked || 2717 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 2718 Schedule == OMP_dist_sch_static || 2719 Schedule == OMP_dist_sch_static_chunked); 2720 2721 // Call __kmpc_for_static_init( 2722 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 2723 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 2724 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 2725 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 2726 llvm::Value *Chunk = Values.Chunk; 2727 if (Chunk == nullptr) { 2728 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 2729 Schedule == OMP_dist_sch_static) && 2730 "expected static non-chunked schedule"); 2731 // If the Chunk was not specified in the clause - use default value 1. 2732 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 2733 } else { 2734 assert((Schedule == OMP_sch_static_chunked || 2735 Schedule == OMP_sch_static_balanced_chunked || 2736 Schedule == OMP_ord_static_chunked || 2737 Schedule == OMP_dist_sch_static_chunked) && 2738 "expected static chunked schedule"); 2739 } 2740 llvm::Value *Args[] = { 2741 UpdateLocation, 2742 ThreadId, 2743 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 2744 M2)), // Schedule type 2745 Values.IL.getPointer(), // &isLastIter 2746 Values.LB.getPointer(), // &LB 2747 Values.UB.getPointer(), // &UB 2748 Values.ST.getPointer(), // &Stride 2749 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 2750 Chunk // Chunk 2751 }; 2752 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 2753 } 2754 2755 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 2756 SourceLocation Loc, 2757 OpenMPDirectiveKind DKind, 2758 const OpenMPScheduleTy &ScheduleKind, 2759 const StaticRTInput &Values) { 2760 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 2761 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 2762 assert(isOpenMPWorksharingDirective(DKind) && 2763 "Expected loop-based or sections-based directive."); 2764 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 2765 isOpenMPLoopDirective(DKind) 2766 ? OMP_IDENT_WORK_LOOP 2767 : OMP_IDENT_WORK_SECTIONS); 2768 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2769 llvm::FunctionCallee StaticInitFunction = 2770 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 2771 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2772 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2773 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 2774 } 2775 2776 void CGOpenMPRuntime::emitDistributeStaticInit( 2777 CodeGenFunction &CGF, SourceLocation Loc, 2778 OpenMPDistScheduleClauseKind SchedKind, 2779 const CGOpenMPRuntime::StaticRTInput &Values) { 2780 OpenMPSchedType ScheduleNum = 2781 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 2782 llvm::Value *UpdatedLocation = 2783 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 2784 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2785 llvm::FunctionCallee StaticInitFunction = 2786 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 2787 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2788 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 2789 OMPC_SCHEDULE_MODIFIER_unknown, Values); 2790 } 2791 2792 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 2793 SourceLocation Loc, 2794 OpenMPDirectiveKind DKind) { 2795 if (!CGF.HaveInsertPoint()) 2796 return; 2797 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 2798 llvm::Value *Args[] = { 2799 emitUpdateLocation(CGF, Loc, 2800 isOpenMPDistributeDirective(DKind) 2801 ? OMP_IDENT_WORK_DISTRIBUTE 2802 : isOpenMPLoopDirective(DKind) 2803 ? OMP_IDENT_WORK_LOOP 2804 : OMP_IDENT_WORK_SECTIONS), 2805 getThreadID(CGF, Loc)}; 2806 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2807 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2808 CGM.getModule(), OMPRTL___kmpc_for_static_fini), 2809 Args); 2810 } 2811 2812 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 2813 SourceLocation Loc, 2814 unsigned IVSize, 2815 bool IVSigned) { 2816 if (!CGF.HaveInsertPoint()) 2817 return; 2818 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 2819 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2820 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 2821 } 2822 2823 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 2824 SourceLocation Loc, unsigned IVSize, 2825 bool IVSigned, Address IL, 2826 Address LB, Address UB, 2827 Address ST) { 2828 // Call __kmpc_dispatch_next( 2829 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 2830 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 2831 // kmp_int[32|64] *p_stride); 2832 llvm::Value *Args[] = { 2833 emitUpdateLocation(CGF, Loc), 2834 getThreadID(CGF, Loc), 2835 IL.getPointer(), // &isLastIter 2836 LB.getPointer(), // &Lower 2837 UB.getPointer(), // &Upper 2838 ST.getPointer() // &Stride 2839 }; 2840 llvm::Value *Call = 2841 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 2842 return CGF.EmitScalarConversion( 2843 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 2844 CGF.getContext().BoolTy, Loc); 2845 } 2846 2847 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 2848 llvm::Value *NumThreads, 2849 SourceLocation Loc) { 2850 if (!CGF.HaveInsertPoint()) 2851 return; 2852 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 2853 llvm::Value *Args[] = { 2854 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2855 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 2856 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2857 CGM.getModule(), OMPRTL___kmpc_push_num_threads), 2858 Args); 2859 } 2860 2861 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 2862 ProcBindKind ProcBind, 2863 SourceLocation Loc) { 2864 if (!CGF.HaveInsertPoint()) 2865 return; 2866 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 2867 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 2868 llvm::Value *Args[] = { 2869 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2870 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 2871 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2872 CGM.getModule(), OMPRTL___kmpc_push_proc_bind), 2873 Args); 2874 } 2875 2876 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 2877 SourceLocation Loc, llvm::AtomicOrdering AO) { 2878 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2879 OMPBuilder.CreateFlush(CGF.Builder); 2880 } else { 2881 if (!CGF.HaveInsertPoint()) 2882 return; 2883 // Build call void __kmpc_flush(ident_t *loc) 2884 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2885 CGM.getModule(), OMPRTL___kmpc_flush), 2886 emitUpdateLocation(CGF, Loc)); 2887 } 2888 } 2889 2890 namespace { 2891 /// Indexes of fields for type kmp_task_t. 2892 enum KmpTaskTFields { 2893 /// List of shared variables. 2894 KmpTaskTShareds, 2895 /// Task routine. 2896 KmpTaskTRoutine, 2897 /// Partition id for the untied tasks. 2898 KmpTaskTPartId, 2899 /// Function with call of destructors for private variables. 2900 Data1, 2901 /// Task priority. 2902 Data2, 2903 /// (Taskloops only) Lower bound. 2904 KmpTaskTLowerBound, 2905 /// (Taskloops only) Upper bound. 2906 KmpTaskTUpperBound, 2907 /// (Taskloops only) Stride. 2908 KmpTaskTStride, 2909 /// (Taskloops only) Is last iteration flag. 2910 KmpTaskTLastIter, 2911 /// (Taskloops only) Reduction data. 2912 KmpTaskTReductions, 2913 }; 2914 } // anonymous namespace 2915 2916 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 2917 return OffloadEntriesTargetRegion.empty() && 2918 OffloadEntriesDeviceGlobalVar.empty(); 2919 } 2920 2921 /// Initialize target region entry. 2922 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2923 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2924 StringRef ParentName, unsigned LineNum, 2925 unsigned Order) { 2926 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 2927 "only required for the device " 2928 "code generation."); 2929 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 2930 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 2931 OMPTargetRegionEntryTargetRegion); 2932 ++OffloadingEntriesNum; 2933 } 2934 2935 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2936 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2937 StringRef ParentName, unsigned LineNum, 2938 llvm::Constant *Addr, llvm::Constant *ID, 2939 OMPTargetRegionEntryKind Flags) { 2940 // If we are emitting code for a target, the entry is already initialized, 2941 // only has to be registered. 2942 if (CGM.getLangOpts().OpenMPIsDevice) { 2943 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 2944 unsigned DiagID = CGM.getDiags().getCustomDiagID( 2945 DiagnosticsEngine::Error, 2946 "Unable to find target region on line '%0' in the device code."); 2947 CGM.getDiags().Report(DiagID) << LineNum; 2948 return; 2949 } 2950 auto &Entry = 2951 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 2952 assert(Entry.isValid() && "Entry not initialized!"); 2953 Entry.setAddress(Addr); 2954 Entry.setID(ID); 2955 Entry.setFlags(Flags); 2956 } else { 2957 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 2958 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 2959 ++OffloadingEntriesNum; 2960 } 2961 } 2962 2963 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 2964 unsigned DeviceID, unsigned FileID, StringRef ParentName, 2965 unsigned LineNum) const { 2966 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 2967 if (PerDevice == OffloadEntriesTargetRegion.end()) 2968 return false; 2969 auto PerFile = PerDevice->second.find(FileID); 2970 if (PerFile == PerDevice->second.end()) 2971 return false; 2972 auto PerParentName = PerFile->second.find(ParentName); 2973 if (PerParentName == PerFile->second.end()) 2974 return false; 2975 auto PerLine = PerParentName->second.find(LineNum); 2976 if (PerLine == PerParentName->second.end()) 2977 return false; 2978 // Fail if this entry is already registered. 2979 if (PerLine->second.getAddress() || PerLine->second.getID()) 2980 return false; 2981 return true; 2982 } 2983 2984 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 2985 const OffloadTargetRegionEntryInfoActTy &Action) { 2986 // Scan all target region entries and perform the provided action. 2987 for (const auto &D : OffloadEntriesTargetRegion) 2988 for (const auto &F : D.second) 2989 for (const auto &P : F.second) 2990 for (const auto &L : P.second) 2991 Action(D.first, F.first, P.first(), L.first, L.second); 2992 } 2993 2994 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2995 initializeDeviceGlobalVarEntryInfo(StringRef Name, 2996 OMPTargetGlobalVarEntryKind Flags, 2997 unsigned Order) { 2998 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 2999 "only required for the device " 3000 "code generation."); 3001 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3002 ++OffloadingEntriesNum; 3003 } 3004 3005 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3006 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3007 CharUnits VarSize, 3008 OMPTargetGlobalVarEntryKind Flags, 3009 llvm::GlobalValue::LinkageTypes Linkage) { 3010 if (CGM.getLangOpts().OpenMPIsDevice) { 3011 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3012 assert(Entry.isValid() && Entry.getFlags() == Flags && 3013 "Entry not initialized!"); 3014 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3015 "Resetting with the new address."); 3016 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3017 if (Entry.getVarSize().isZero()) { 3018 Entry.setVarSize(VarSize); 3019 Entry.setLinkage(Linkage); 3020 } 3021 return; 3022 } 3023 Entry.setVarSize(VarSize); 3024 Entry.setLinkage(Linkage); 3025 Entry.setAddress(Addr); 3026 } else { 3027 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3028 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3029 assert(Entry.isValid() && Entry.getFlags() == Flags && 3030 "Entry not initialized!"); 3031 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3032 "Resetting with the new address."); 3033 if (Entry.getVarSize().isZero()) { 3034 Entry.setVarSize(VarSize); 3035 Entry.setLinkage(Linkage); 3036 } 3037 return; 3038 } 3039 OffloadEntriesDeviceGlobalVar.try_emplace( 3040 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3041 ++OffloadingEntriesNum; 3042 } 3043 } 3044 3045 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3046 actOnDeviceGlobalVarEntriesInfo( 3047 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 3048 // Scan all target region entries and perform the provided action. 3049 for (const auto &E : OffloadEntriesDeviceGlobalVar) 3050 Action(E.getKey(), E.getValue()); 3051 } 3052 3053 void CGOpenMPRuntime::createOffloadEntry( 3054 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 3055 llvm::GlobalValue::LinkageTypes Linkage) { 3056 StringRef Name = Addr->getName(); 3057 llvm::Module &M = CGM.getModule(); 3058 llvm::LLVMContext &C = M.getContext(); 3059 3060 // Create constant string with the name. 3061 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 3062 3063 std::string StringName = getName({"omp_offloading", "entry_name"}); 3064 auto *Str = new llvm::GlobalVariable( 3065 M, StrPtrInit->getType(), /*isConstant=*/true, 3066 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 3067 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 3068 3069 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 3070 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 3071 llvm::ConstantInt::get(CGM.SizeTy, Size), 3072 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 3073 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 3074 std::string EntryName = getName({"omp_offloading", "entry", ""}); 3075 llvm::GlobalVariable *Entry = createGlobalStruct( 3076 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 3077 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 3078 3079 // The entry has to be created in the section the linker expects it to be. 3080 Entry->setSection("omp_offloading_entries"); 3081 } 3082 3083 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 3084 // Emit the offloading entries and metadata so that the device codegen side 3085 // can easily figure out what to emit. The produced metadata looks like 3086 // this: 3087 // 3088 // !omp_offload.info = !{!1, ...} 3089 // 3090 // Right now we only generate metadata for function that contain target 3091 // regions. 3092 3093 // If we are in simd mode or there are no entries, we don't need to do 3094 // anything. 3095 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 3096 return; 3097 3098 llvm::Module &M = CGM.getModule(); 3099 llvm::LLVMContext &C = M.getContext(); 3100 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 3101 SourceLocation, StringRef>, 3102 16> 3103 OrderedEntries(OffloadEntriesInfoManager.size()); 3104 llvm::SmallVector<StringRef, 16> ParentFunctions( 3105 OffloadEntriesInfoManager.size()); 3106 3107 // Auxiliary methods to create metadata values and strings. 3108 auto &&GetMDInt = [this](unsigned V) { 3109 return llvm::ConstantAsMetadata::get( 3110 llvm::ConstantInt::get(CGM.Int32Ty, V)); 3111 }; 3112 3113 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 3114 3115 // Create the offloading info metadata node. 3116 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 3117 3118 // Create function that emits metadata for each target region entry; 3119 auto &&TargetRegionMetadataEmitter = 3120 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 3121 &GetMDString]( 3122 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3123 unsigned Line, 3124 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 3125 // Generate metadata for target regions. Each entry of this metadata 3126 // contains: 3127 // - Entry 0 -> Kind of this type of metadata (0). 3128 // - Entry 1 -> Device ID of the file where the entry was identified. 3129 // - Entry 2 -> File ID of the file where the entry was identified. 3130 // - Entry 3 -> Mangled name of the function where the entry was 3131 // identified. 3132 // - Entry 4 -> Line in the file where the entry was identified. 3133 // - Entry 5 -> Order the entry was created. 3134 // The first element of the metadata node is the kind. 3135 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 3136 GetMDInt(FileID), GetMDString(ParentName), 3137 GetMDInt(Line), GetMDInt(E.getOrder())}; 3138 3139 SourceLocation Loc; 3140 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 3141 E = CGM.getContext().getSourceManager().fileinfo_end(); 3142 I != E; ++I) { 3143 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 3144 I->getFirst()->getUniqueID().getFile() == FileID) { 3145 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 3146 I->getFirst(), Line, 1); 3147 break; 3148 } 3149 } 3150 // Save this entry in the right position of the ordered entries array. 3151 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 3152 ParentFunctions[E.getOrder()] = ParentName; 3153 3154 // Add metadata to the named metadata node. 3155 MD->addOperand(llvm::MDNode::get(C, Ops)); 3156 }; 3157 3158 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 3159 TargetRegionMetadataEmitter); 3160 3161 // Create function that emits metadata for each device global variable entry; 3162 auto &&DeviceGlobalVarMetadataEmitter = 3163 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 3164 MD](StringRef MangledName, 3165 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 3166 &E) { 3167 // Generate metadata for global variables. Each entry of this metadata 3168 // contains: 3169 // - Entry 0 -> Kind of this type of metadata (1). 3170 // - Entry 1 -> Mangled name of the variable. 3171 // - Entry 2 -> Declare target kind. 3172 // - Entry 3 -> Order the entry was created. 3173 // The first element of the metadata node is the kind. 3174 llvm::Metadata *Ops[] = { 3175 GetMDInt(E.getKind()), GetMDString(MangledName), 3176 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 3177 3178 // Save this entry in the right position of the ordered entries array. 3179 OrderedEntries[E.getOrder()] = 3180 std::make_tuple(&E, SourceLocation(), MangledName); 3181 3182 // Add metadata to the named metadata node. 3183 MD->addOperand(llvm::MDNode::get(C, Ops)); 3184 }; 3185 3186 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 3187 DeviceGlobalVarMetadataEmitter); 3188 3189 for (const auto &E : OrderedEntries) { 3190 assert(std::get<0>(E) && "All ordered entries must exist!"); 3191 if (const auto *CE = 3192 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 3193 std::get<0>(E))) { 3194 if (!CE->getID() || !CE->getAddress()) { 3195 // Do not blame the entry if the parent funtion is not emitted. 3196 StringRef FnName = ParentFunctions[CE->getOrder()]; 3197 if (!CGM.GetGlobalValue(FnName)) 3198 continue; 3199 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3200 DiagnosticsEngine::Error, 3201 "Offloading entry for target region in %0 is incorrect: either the " 3202 "address or the ID is invalid."); 3203 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 3204 continue; 3205 } 3206 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 3207 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 3208 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 3209 OffloadEntryInfoDeviceGlobalVar>( 3210 std::get<0>(E))) { 3211 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 3212 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3213 CE->getFlags()); 3214 switch (Flags) { 3215 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 3216 if (CGM.getLangOpts().OpenMPIsDevice && 3217 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 3218 continue; 3219 if (!CE->getAddress()) { 3220 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3221 DiagnosticsEngine::Error, "Offloading entry for declare target " 3222 "variable %0 is incorrect: the " 3223 "address is invalid."); 3224 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 3225 continue; 3226 } 3227 // The vaiable has no definition - no need to add the entry. 3228 if (CE->getVarSize().isZero()) 3229 continue; 3230 break; 3231 } 3232 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 3233 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 3234 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 3235 "Declaret target link address is set."); 3236 if (CGM.getLangOpts().OpenMPIsDevice) 3237 continue; 3238 if (!CE->getAddress()) { 3239 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3240 DiagnosticsEngine::Error, 3241 "Offloading entry for declare target variable is incorrect: the " 3242 "address is invalid."); 3243 CGM.getDiags().Report(DiagID); 3244 continue; 3245 } 3246 break; 3247 } 3248 createOffloadEntry(CE->getAddress(), CE->getAddress(), 3249 CE->getVarSize().getQuantity(), Flags, 3250 CE->getLinkage()); 3251 } else { 3252 llvm_unreachable("Unsupported entry kind."); 3253 } 3254 } 3255 } 3256 3257 /// Loads all the offload entries information from the host IR 3258 /// metadata. 3259 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 3260 // If we are in target mode, load the metadata from the host IR. This code has 3261 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 3262 3263 if (!CGM.getLangOpts().OpenMPIsDevice) 3264 return; 3265 3266 if (CGM.getLangOpts().OMPHostIRFile.empty()) 3267 return; 3268 3269 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 3270 if (auto EC = Buf.getError()) { 3271 CGM.getDiags().Report(diag::err_cannot_open_file) 3272 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3273 return; 3274 } 3275 3276 llvm::LLVMContext C; 3277 auto ME = expectedToErrorOrAndEmitErrors( 3278 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 3279 3280 if (auto EC = ME.getError()) { 3281 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3282 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 3283 CGM.getDiags().Report(DiagID) 3284 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3285 return; 3286 } 3287 3288 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 3289 if (!MD) 3290 return; 3291 3292 for (llvm::MDNode *MN : MD->operands()) { 3293 auto &&GetMDInt = [MN](unsigned Idx) { 3294 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 3295 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 3296 }; 3297 3298 auto &&GetMDString = [MN](unsigned Idx) { 3299 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 3300 return V->getString(); 3301 }; 3302 3303 switch (GetMDInt(0)) { 3304 default: 3305 llvm_unreachable("Unexpected metadata!"); 3306 break; 3307 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3308 OffloadingEntryInfoTargetRegion: 3309 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 3310 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 3311 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 3312 /*Order=*/GetMDInt(5)); 3313 break; 3314 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3315 OffloadingEntryInfoDeviceGlobalVar: 3316 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 3317 /*MangledName=*/GetMDString(1), 3318 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3319 /*Flags=*/GetMDInt(2)), 3320 /*Order=*/GetMDInt(3)); 3321 break; 3322 } 3323 } 3324 } 3325 3326 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 3327 if (!KmpRoutineEntryPtrTy) { 3328 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 3329 ASTContext &C = CGM.getContext(); 3330 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 3331 FunctionProtoType::ExtProtoInfo EPI; 3332 KmpRoutineEntryPtrQTy = C.getPointerType( 3333 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 3334 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 3335 } 3336 } 3337 3338 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 3339 // Make sure the type of the entry is already created. This is the type we 3340 // have to create: 3341 // struct __tgt_offload_entry{ 3342 // void *addr; // Pointer to the offload entry info. 3343 // // (function or global) 3344 // char *name; // Name of the function or global. 3345 // size_t size; // Size of the entry info (0 if it a function). 3346 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 3347 // int32_t reserved; // Reserved, to use by the runtime library. 3348 // }; 3349 if (TgtOffloadEntryQTy.isNull()) { 3350 ASTContext &C = CGM.getContext(); 3351 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 3352 RD->startDefinition(); 3353 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3354 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 3355 addFieldToRecordDecl(C, RD, C.getSizeType()); 3356 addFieldToRecordDecl( 3357 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3358 addFieldToRecordDecl( 3359 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3360 RD->completeDefinition(); 3361 RD->addAttr(PackedAttr::CreateImplicit(C)); 3362 TgtOffloadEntryQTy = C.getRecordType(RD); 3363 } 3364 return TgtOffloadEntryQTy; 3365 } 3366 3367 namespace { 3368 struct PrivateHelpersTy { 3369 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original, 3370 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit) 3371 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy), 3372 PrivateElemInit(PrivateElemInit) {} 3373 PrivateHelpersTy(const VarDecl *Original) : Original(Original) {} 3374 const Expr *OriginalRef = nullptr; 3375 const VarDecl *Original = nullptr; 3376 const VarDecl *PrivateCopy = nullptr; 3377 const VarDecl *PrivateElemInit = nullptr; 3378 bool isLocalPrivate() const { 3379 return !OriginalRef && !PrivateCopy && !PrivateElemInit; 3380 } 3381 }; 3382 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 3383 } // anonymous namespace 3384 3385 static RecordDecl * 3386 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 3387 if (!Privates.empty()) { 3388 ASTContext &C = CGM.getContext(); 3389 // Build struct .kmp_privates_t. { 3390 // /* private vars */ 3391 // }; 3392 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 3393 RD->startDefinition(); 3394 for (const auto &Pair : Privates) { 3395 const VarDecl *VD = Pair.second.Original; 3396 QualType Type = VD->getType().getNonReferenceType(); 3397 // If the private variable is a local variable with lvalue ref type, 3398 // allocate the pointer instead of the pointee type. 3399 if (Pair.second.isLocalPrivate() && 3400 VD->getType()->isLValueReferenceType()) 3401 Type = C.getPointerType(Type); 3402 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 3403 if (VD->hasAttrs()) { 3404 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 3405 E(VD->getAttrs().end()); 3406 I != E; ++I) 3407 FD->addAttr(*I); 3408 } 3409 } 3410 RD->completeDefinition(); 3411 return RD; 3412 } 3413 return nullptr; 3414 } 3415 3416 static RecordDecl * 3417 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 3418 QualType KmpInt32Ty, 3419 QualType KmpRoutineEntryPointerQTy) { 3420 ASTContext &C = CGM.getContext(); 3421 // Build struct kmp_task_t { 3422 // void * shareds; 3423 // kmp_routine_entry_t routine; 3424 // kmp_int32 part_id; 3425 // kmp_cmplrdata_t data1; 3426 // kmp_cmplrdata_t data2; 3427 // For taskloops additional fields: 3428 // kmp_uint64 lb; 3429 // kmp_uint64 ub; 3430 // kmp_int64 st; 3431 // kmp_int32 liter; 3432 // void * reductions; 3433 // }; 3434 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 3435 UD->startDefinition(); 3436 addFieldToRecordDecl(C, UD, KmpInt32Ty); 3437 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 3438 UD->completeDefinition(); 3439 QualType KmpCmplrdataTy = C.getRecordType(UD); 3440 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 3441 RD->startDefinition(); 3442 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3443 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 3444 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3445 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3446 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3447 if (isOpenMPTaskLoopDirective(Kind)) { 3448 QualType KmpUInt64Ty = 3449 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 3450 QualType KmpInt64Ty = 3451 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 3452 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3453 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3454 addFieldToRecordDecl(C, RD, KmpInt64Ty); 3455 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3456 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3457 } 3458 RD->completeDefinition(); 3459 return RD; 3460 } 3461 3462 static RecordDecl * 3463 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 3464 ArrayRef<PrivateDataTy> Privates) { 3465 ASTContext &C = CGM.getContext(); 3466 // Build struct kmp_task_t_with_privates { 3467 // kmp_task_t task_data; 3468 // .kmp_privates_t. privates; 3469 // }; 3470 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 3471 RD->startDefinition(); 3472 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 3473 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 3474 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 3475 RD->completeDefinition(); 3476 return RD; 3477 } 3478 3479 /// Emit a proxy function which accepts kmp_task_t as the second 3480 /// argument. 3481 /// \code 3482 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 3483 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 3484 /// For taskloops: 3485 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3486 /// tt->reductions, tt->shareds); 3487 /// return 0; 3488 /// } 3489 /// \endcode 3490 static llvm::Function * 3491 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 3492 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 3493 QualType KmpTaskTWithPrivatesPtrQTy, 3494 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 3495 QualType SharedsPtrTy, llvm::Function *TaskFunction, 3496 llvm::Value *TaskPrivatesMap) { 3497 ASTContext &C = CGM.getContext(); 3498 FunctionArgList Args; 3499 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3500 ImplicitParamDecl::Other); 3501 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3502 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3503 ImplicitParamDecl::Other); 3504 Args.push_back(&GtidArg); 3505 Args.push_back(&TaskTypeArg); 3506 const auto &TaskEntryFnInfo = 3507 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3508 llvm::FunctionType *TaskEntryTy = 3509 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 3510 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 3511 auto *TaskEntry = llvm::Function::Create( 3512 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3513 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 3514 TaskEntry->setDoesNotRecurse(); 3515 CodeGenFunction CGF(CGM); 3516 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 3517 Loc, Loc); 3518 3519 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 3520 // tt, 3521 // For taskloops: 3522 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3523 // tt->task_data.shareds); 3524 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 3525 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 3526 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3527 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3528 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3529 const auto *KmpTaskTWithPrivatesQTyRD = 3530 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3531 LValue Base = 3532 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3533 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3534 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 3535 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 3536 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 3537 3538 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 3539 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 3540 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3541 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 3542 CGF.ConvertTypeForMem(SharedsPtrTy)); 3543 3544 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 3545 llvm::Value *PrivatesParam; 3546 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 3547 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 3548 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3549 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 3550 } else { 3551 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3552 } 3553 3554 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 3555 TaskPrivatesMap, 3556 CGF.Builder 3557 .CreatePointerBitCastOrAddrSpaceCast( 3558 TDBase.getAddress(CGF), CGF.VoidPtrTy) 3559 .getPointer()}; 3560 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 3561 std::end(CommonArgs)); 3562 if (isOpenMPTaskLoopDirective(Kind)) { 3563 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 3564 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 3565 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 3566 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 3567 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 3568 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 3569 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 3570 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 3571 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 3572 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3573 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3574 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 3575 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 3576 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 3577 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 3578 CallArgs.push_back(LBParam); 3579 CallArgs.push_back(UBParam); 3580 CallArgs.push_back(StParam); 3581 CallArgs.push_back(LIParam); 3582 CallArgs.push_back(RParam); 3583 } 3584 CallArgs.push_back(SharedsParam); 3585 3586 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 3587 CallArgs); 3588 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 3589 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 3590 CGF.FinishFunction(); 3591 return TaskEntry; 3592 } 3593 3594 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 3595 SourceLocation Loc, 3596 QualType KmpInt32Ty, 3597 QualType KmpTaskTWithPrivatesPtrQTy, 3598 QualType KmpTaskTWithPrivatesQTy) { 3599 ASTContext &C = CGM.getContext(); 3600 FunctionArgList Args; 3601 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3602 ImplicitParamDecl::Other); 3603 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3604 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3605 ImplicitParamDecl::Other); 3606 Args.push_back(&GtidArg); 3607 Args.push_back(&TaskTypeArg); 3608 const auto &DestructorFnInfo = 3609 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3610 llvm::FunctionType *DestructorFnTy = 3611 CGM.getTypes().GetFunctionType(DestructorFnInfo); 3612 std::string Name = 3613 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 3614 auto *DestructorFn = 3615 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 3616 Name, &CGM.getModule()); 3617 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 3618 DestructorFnInfo); 3619 DestructorFn->setDoesNotRecurse(); 3620 CodeGenFunction CGF(CGM); 3621 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 3622 Args, Loc, Loc); 3623 3624 LValue Base = CGF.EmitLoadOfPointerLValue( 3625 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3626 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3627 const auto *KmpTaskTWithPrivatesQTyRD = 3628 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3629 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3630 Base = CGF.EmitLValueForField(Base, *FI); 3631 for (const auto *Field : 3632 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 3633 if (QualType::DestructionKind DtorKind = 3634 Field->getType().isDestructedType()) { 3635 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 3636 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 3637 } 3638 } 3639 CGF.FinishFunction(); 3640 return DestructorFn; 3641 } 3642 3643 /// Emit a privates mapping function for correct handling of private and 3644 /// firstprivate variables. 3645 /// \code 3646 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 3647 /// **noalias priv1,..., <tyn> **noalias privn) { 3648 /// *priv1 = &.privates.priv1; 3649 /// ...; 3650 /// *privn = &.privates.privn; 3651 /// } 3652 /// \endcode 3653 static llvm::Value * 3654 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 3655 const OMPTaskDataTy &Data, QualType PrivatesQTy, 3656 ArrayRef<PrivateDataTy> Privates) { 3657 ASTContext &C = CGM.getContext(); 3658 FunctionArgList Args; 3659 ImplicitParamDecl TaskPrivatesArg( 3660 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3661 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 3662 ImplicitParamDecl::Other); 3663 Args.push_back(&TaskPrivatesArg); 3664 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, unsigned> PrivateVarsPos; 3665 unsigned Counter = 1; 3666 for (const Expr *E : Data.PrivateVars) { 3667 Args.push_back(ImplicitParamDecl::Create( 3668 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3669 C.getPointerType(C.getPointerType(E->getType())) 3670 .withConst() 3671 .withRestrict(), 3672 ImplicitParamDecl::Other)); 3673 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3674 PrivateVarsPos[VD] = Counter; 3675 ++Counter; 3676 } 3677 for (const Expr *E : Data.FirstprivateVars) { 3678 Args.push_back(ImplicitParamDecl::Create( 3679 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3680 C.getPointerType(C.getPointerType(E->getType())) 3681 .withConst() 3682 .withRestrict(), 3683 ImplicitParamDecl::Other)); 3684 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3685 PrivateVarsPos[VD] = Counter; 3686 ++Counter; 3687 } 3688 for (const Expr *E : Data.LastprivateVars) { 3689 Args.push_back(ImplicitParamDecl::Create( 3690 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3691 C.getPointerType(C.getPointerType(E->getType())) 3692 .withConst() 3693 .withRestrict(), 3694 ImplicitParamDecl::Other)); 3695 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3696 PrivateVarsPos[VD] = Counter; 3697 ++Counter; 3698 } 3699 for (const VarDecl *VD : Data.PrivateLocals) { 3700 QualType Ty = VD->getType().getNonReferenceType(); 3701 if (VD->getType()->isLValueReferenceType()) 3702 Ty = C.getPointerType(Ty); 3703 Args.push_back(ImplicitParamDecl::Create( 3704 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3705 C.getPointerType(C.getPointerType(Ty)).withConst().withRestrict(), 3706 ImplicitParamDecl::Other)); 3707 PrivateVarsPos[VD] = Counter; 3708 ++Counter; 3709 } 3710 const auto &TaskPrivatesMapFnInfo = 3711 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3712 llvm::FunctionType *TaskPrivatesMapTy = 3713 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 3714 std::string Name = 3715 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 3716 auto *TaskPrivatesMap = llvm::Function::Create( 3717 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 3718 &CGM.getModule()); 3719 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 3720 TaskPrivatesMapFnInfo); 3721 if (CGM.getLangOpts().Optimize) { 3722 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 3723 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 3724 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 3725 } 3726 CodeGenFunction CGF(CGM); 3727 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 3728 TaskPrivatesMapFnInfo, Args, Loc, Loc); 3729 3730 // *privi = &.privates.privi; 3731 LValue Base = CGF.EmitLoadOfPointerLValue( 3732 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 3733 TaskPrivatesArg.getType()->castAs<PointerType>()); 3734 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 3735 Counter = 0; 3736 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 3737 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 3738 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 3739 LValue RefLVal = 3740 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 3741 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 3742 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 3743 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 3744 ++Counter; 3745 } 3746 CGF.FinishFunction(); 3747 return TaskPrivatesMap; 3748 } 3749 3750 /// Emit initialization for private variables in task-based directives. 3751 static void emitPrivatesInit(CodeGenFunction &CGF, 3752 const OMPExecutableDirective &D, 3753 Address KmpTaskSharedsPtr, LValue TDBase, 3754 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3755 QualType SharedsTy, QualType SharedsPtrTy, 3756 const OMPTaskDataTy &Data, 3757 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 3758 ASTContext &C = CGF.getContext(); 3759 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3760 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 3761 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 3762 ? OMPD_taskloop 3763 : OMPD_task; 3764 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 3765 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 3766 LValue SrcBase; 3767 bool IsTargetTask = 3768 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 3769 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 3770 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 3771 // PointersArray and SizesArray. The original variables for these arrays are 3772 // not captured and we get their addresses explicitly. 3773 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) || 3774 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 3775 SrcBase = CGF.MakeAddrLValue( 3776 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3777 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 3778 SharedsTy); 3779 } 3780 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 3781 for (const PrivateDataTy &Pair : Privates) { 3782 // Do not initialize private locals. 3783 if (Pair.second.isLocalPrivate()) 3784 continue; 3785 const VarDecl *VD = Pair.second.PrivateCopy; 3786 const Expr *Init = VD->getAnyInitializer(); 3787 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 3788 !CGF.isTrivialInitializer(Init)))) { 3789 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 3790 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 3791 const VarDecl *OriginalVD = Pair.second.Original; 3792 // Check if the variable is the target-based BasePointersArray, 3793 // PointersArray or SizesArray. 3794 LValue SharedRefLValue; 3795 QualType Type = PrivateLValue.getType(); 3796 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 3797 if (IsTargetTask && !SharedField) { 3798 assert(isa<ImplicitParamDecl>(OriginalVD) && 3799 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 3800 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3801 ->getNumParams() == 0 && 3802 isa<TranslationUnitDecl>( 3803 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3804 ->getDeclContext()) && 3805 "Expected artificial target data variable."); 3806 SharedRefLValue = 3807 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 3808 } else if (ForDup) { 3809 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 3810 SharedRefLValue = CGF.MakeAddrLValue( 3811 Address(SharedRefLValue.getPointer(CGF), 3812 C.getDeclAlign(OriginalVD)), 3813 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 3814 SharedRefLValue.getTBAAInfo()); 3815 } else if (CGF.LambdaCaptureFields.count( 3816 Pair.second.Original->getCanonicalDecl()) > 0 || 3817 dyn_cast_or_null<BlockDecl>(CGF.CurCodeDecl)) { 3818 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3819 } else { 3820 // Processing for implicitly captured variables. 3821 InlinedOpenMPRegionRAII Region( 3822 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown, 3823 /*HasCancel=*/false); 3824 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3825 } 3826 if (Type->isArrayType()) { 3827 // Initialize firstprivate array. 3828 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 3829 // Perform simple memcpy. 3830 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 3831 } else { 3832 // Initialize firstprivate array using element-by-element 3833 // initialization. 3834 CGF.EmitOMPAggregateAssign( 3835 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 3836 Type, 3837 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 3838 Address SrcElement) { 3839 // Clean up any temporaries needed by the initialization. 3840 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3841 InitScope.addPrivate( 3842 Elem, [SrcElement]() -> Address { return SrcElement; }); 3843 (void)InitScope.Privatize(); 3844 // Emit initialization for single element. 3845 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 3846 CGF, &CapturesInfo); 3847 CGF.EmitAnyExprToMem(Init, DestElement, 3848 Init->getType().getQualifiers(), 3849 /*IsInitializer=*/false); 3850 }); 3851 } 3852 } else { 3853 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3854 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 3855 return SharedRefLValue.getAddress(CGF); 3856 }); 3857 (void)InitScope.Privatize(); 3858 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 3859 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 3860 /*capturedByInit=*/false); 3861 } 3862 } else { 3863 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 3864 } 3865 } 3866 ++FI; 3867 } 3868 } 3869 3870 /// Check if duplication function is required for taskloops. 3871 static bool checkInitIsRequired(CodeGenFunction &CGF, 3872 ArrayRef<PrivateDataTy> Privates) { 3873 bool InitRequired = false; 3874 for (const PrivateDataTy &Pair : Privates) { 3875 if (Pair.second.isLocalPrivate()) 3876 continue; 3877 const VarDecl *VD = Pair.second.PrivateCopy; 3878 const Expr *Init = VD->getAnyInitializer(); 3879 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 3880 !CGF.isTrivialInitializer(Init)); 3881 if (InitRequired) 3882 break; 3883 } 3884 return InitRequired; 3885 } 3886 3887 3888 /// Emit task_dup function (for initialization of 3889 /// private/firstprivate/lastprivate vars and last_iter flag) 3890 /// \code 3891 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 3892 /// lastpriv) { 3893 /// // setup lastprivate flag 3894 /// task_dst->last = lastpriv; 3895 /// // could be constructor calls here... 3896 /// } 3897 /// \endcode 3898 static llvm::Value * 3899 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 3900 const OMPExecutableDirective &D, 3901 QualType KmpTaskTWithPrivatesPtrQTy, 3902 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3903 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 3904 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 3905 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 3906 ASTContext &C = CGM.getContext(); 3907 FunctionArgList Args; 3908 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3909 KmpTaskTWithPrivatesPtrQTy, 3910 ImplicitParamDecl::Other); 3911 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3912 KmpTaskTWithPrivatesPtrQTy, 3913 ImplicitParamDecl::Other); 3914 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 3915 ImplicitParamDecl::Other); 3916 Args.push_back(&DstArg); 3917 Args.push_back(&SrcArg); 3918 Args.push_back(&LastprivArg); 3919 const auto &TaskDupFnInfo = 3920 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3921 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 3922 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 3923 auto *TaskDup = llvm::Function::Create( 3924 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3925 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 3926 TaskDup->setDoesNotRecurse(); 3927 CodeGenFunction CGF(CGM); 3928 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 3929 Loc); 3930 3931 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3932 CGF.GetAddrOfLocalVar(&DstArg), 3933 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3934 // task_dst->liter = lastpriv; 3935 if (WithLastIter) { 3936 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3937 LValue Base = CGF.EmitLValueForField( 3938 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3939 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3940 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 3941 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 3942 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 3943 } 3944 3945 // Emit initial values for private copies (if any). 3946 assert(!Privates.empty()); 3947 Address KmpTaskSharedsPtr = Address::invalid(); 3948 if (!Data.FirstprivateVars.empty()) { 3949 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3950 CGF.GetAddrOfLocalVar(&SrcArg), 3951 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3952 LValue Base = CGF.EmitLValueForField( 3953 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3954 KmpTaskSharedsPtr = Address( 3955 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 3956 Base, *std::next(KmpTaskTQTyRD->field_begin(), 3957 KmpTaskTShareds)), 3958 Loc), 3959 CGM.getNaturalTypeAlignment(SharedsTy)); 3960 } 3961 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 3962 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 3963 CGF.FinishFunction(); 3964 return TaskDup; 3965 } 3966 3967 /// Checks if destructor function is required to be generated. 3968 /// \return true if cleanups are required, false otherwise. 3969 static bool 3970 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3971 ArrayRef<PrivateDataTy> Privates) { 3972 for (const PrivateDataTy &P : Privates) { 3973 if (P.second.isLocalPrivate()) 3974 continue; 3975 QualType Ty = P.second.Original->getType().getNonReferenceType(); 3976 if (Ty.isDestructedType()) 3977 return true; 3978 } 3979 return false; 3980 } 3981 3982 namespace { 3983 /// Loop generator for OpenMP iterator expression. 3984 class OMPIteratorGeneratorScope final 3985 : public CodeGenFunction::OMPPrivateScope { 3986 CodeGenFunction &CGF; 3987 const OMPIteratorExpr *E = nullptr; 3988 SmallVector<CodeGenFunction::JumpDest, 4> ContDests; 3989 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests; 3990 OMPIteratorGeneratorScope() = delete; 3991 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete; 3992 3993 public: 3994 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E) 3995 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) { 3996 if (!E) 3997 return; 3998 SmallVector<llvm::Value *, 4> Uppers; 3999 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4000 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper)); 4001 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I)); 4002 addPrivate(VD, [&CGF, VD]() { 4003 return CGF.CreateMemTemp(VD->getType(), VD->getName()); 4004 }); 4005 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4006 addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() { 4007 return CGF.CreateMemTemp(HelperData.CounterVD->getType(), 4008 "counter.addr"); 4009 }); 4010 } 4011 Privatize(); 4012 4013 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4014 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4015 LValue CLVal = 4016 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD), 4017 HelperData.CounterVD->getType()); 4018 // Counter = 0; 4019 CGF.EmitStoreOfScalar( 4020 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0), 4021 CLVal); 4022 CodeGenFunction::JumpDest &ContDest = 4023 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont")); 4024 CodeGenFunction::JumpDest &ExitDest = 4025 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit")); 4026 // N = <number-of_iterations>; 4027 llvm::Value *N = Uppers[I]; 4028 // cont: 4029 // if (Counter < N) goto body; else goto exit; 4030 CGF.EmitBlock(ContDest.getBlock()); 4031 auto *CVal = 4032 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation()); 4033 llvm::Value *Cmp = 4034 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType() 4035 ? CGF.Builder.CreateICmpSLT(CVal, N) 4036 : CGF.Builder.CreateICmpULT(CVal, N); 4037 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body"); 4038 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock()); 4039 // body: 4040 CGF.EmitBlock(BodyBB); 4041 // Iteri = Begini + Counter * Stepi; 4042 CGF.EmitIgnoredExpr(HelperData.Update); 4043 } 4044 } 4045 ~OMPIteratorGeneratorScope() { 4046 if (!E) 4047 return; 4048 for (unsigned I = E->numOfIterators(); I > 0; --I) { 4049 // Counter = Counter + 1; 4050 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1); 4051 CGF.EmitIgnoredExpr(HelperData.CounterUpdate); 4052 // goto cont; 4053 CGF.EmitBranchThroughCleanup(ContDests[I - 1]); 4054 // exit: 4055 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1); 4056 } 4057 } 4058 }; 4059 } // namespace 4060 4061 static std::pair<llvm::Value *, llvm::Value *> 4062 getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { 4063 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E); 4064 llvm::Value *Addr; 4065 if (OASE) { 4066 const Expr *Base = OASE->getBase(); 4067 Addr = CGF.EmitScalarExpr(Base); 4068 } else { 4069 Addr = CGF.EmitLValue(E).getPointer(CGF); 4070 } 4071 llvm::Value *SizeVal; 4072 QualType Ty = E->getType(); 4073 if (OASE) { 4074 SizeVal = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType()); 4075 for (const Expr *SE : OASE->getDimensions()) { 4076 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 4077 Sz = CGF.EmitScalarConversion( 4078 Sz, SE->getType(), CGF.getContext().getSizeType(), SE->getExprLoc()); 4079 SizeVal = CGF.Builder.CreateNUWMul(SizeVal, Sz); 4080 } 4081 } else if (const auto *ASE = 4082 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 4083 LValue UpAddrLVal = 4084 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 4085 llvm::Value *UpAddr = 4086 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 4087 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); 4088 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); 4089 SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 4090 } else { 4091 SizeVal = CGF.getTypeSize(Ty); 4092 } 4093 return std::make_pair(Addr, SizeVal); 4094 } 4095 4096 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4097 static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) { 4098 QualType FlagsTy = C.getIntTypeForBitwidth(32, /*Signed=*/false); 4099 if (KmpTaskAffinityInfoTy.isNull()) { 4100 RecordDecl *KmpAffinityInfoRD = 4101 C.buildImplicitRecord("kmp_task_affinity_info_t"); 4102 KmpAffinityInfoRD->startDefinition(); 4103 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getIntPtrType()); 4104 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType()); 4105 addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy); 4106 KmpAffinityInfoRD->completeDefinition(); 4107 KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD); 4108 } 4109 } 4110 4111 CGOpenMPRuntime::TaskResultTy 4112 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4113 const OMPExecutableDirective &D, 4114 llvm::Function *TaskFunction, QualType SharedsTy, 4115 Address Shareds, const OMPTaskDataTy &Data) { 4116 ASTContext &C = CGM.getContext(); 4117 llvm::SmallVector<PrivateDataTy, 4> Privates; 4118 // Aggregate privates and sort them by the alignment. 4119 const auto *I = Data.PrivateCopies.begin(); 4120 for (const Expr *E : Data.PrivateVars) { 4121 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4122 Privates.emplace_back( 4123 C.getDeclAlign(VD), 4124 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4125 /*PrivateElemInit=*/nullptr)); 4126 ++I; 4127 } 4128 I = Data.FirstprivateCopies.begin(); 4129 const auto *IElemInitRef = Data.FirstprivateInits.begin(); 4130 for (const Expr *E : Data.FirstprivateVars) { 4131 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4132 Privates.emplace_back( 4133 C.getDeclAlign(VD), 4134 PrivateHelpersTy( 4135 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4136 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4137 ++I; 4138 ++IElemInitRef; 4139 } 4140 I = Data.LastprivateCopies.begin(); 4141 for (const Expr *E : Data.LastprivateVars) { 4142 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4143 Privates.emplace_back( 4144 C.getDeclAlign(VD), 4145 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4146 /*PrivateElemInit=*/nullptr)); 4147 ++I; 4148 } 4149 for (const VarDecl *VD : Data.PrivateLocals) 4150 Privates.emplace_back(C.getDeclAlign(VD), PrivateHelpersTy(VD)); 4151 llvm::stable_sort(Privates, 4152 [](const PrivateDataTy &L, const PrivateDataTy &R) { 4153 return L.first > R.first; 4154 }); 4155 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4156 // Build type kmp_routine_entry_t (if not built yet). 4157 emitKmpRoutineEntryT(KmpInt32Ty); 4158 // Build type kmp_task_t (if not built yet). 4159 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 4160 if (SavedKmpTaskloopTQTy.isNull()) { 4161 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4162 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4163 } 4164 KmpTaskTQTy = SavedKmpTaskloopTQTy; 4165 } else { 4166 assert((D.getDirectiveKind() == OMPD_task || 4167 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 4168 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 4169 "Expected taskloop, task or target directive"); 4170 if (SavedKmpTaskTQTy.isNull()) { 4171 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4172 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4173 } 4174 KmpTaskTQTy = SavedKmpTaskTQTy; 4175 } 4176 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4177 // Build particular struct kmp_task_t for the given task. 4178 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 4179 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 4180 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 4181 QualType KmpTaskTWithPrivatesPtrQTy = 4182 C.getPointerType(KmpTaskTWithPrivatesQTy); 4183 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 4184 llvm::Type *KmpTaskTWithPrivatesPtrTy = 4185 KmpTaskTWithPrivatesTy->getPointerTo(); 4186 llvm::Value *KmpTaskTWithPrivatesTySize = 4187 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 4188 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 4189 4190 // Emit initial values for private copies (if any). 4191 llvm::Value *TaskPrivatesMap = nullptr; 4192 llvm::Type *TaskPrivatesMapTy = 4193 std::next(TaskFunction->arg_begin(), 3)->getType(); 4194 if (!Privates.empty()) { 4195 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4196 TaskPrivatesMap = 4197 emitTaskPrivateMappingFunction(CGM, Loc, Data, FI->getType(), Privates); 4198 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4199 TaskPrivatesMap, TaskPrivatesMapTy); 4200 } else { 4201 TaskPrivatesMap = llvm::ConstantPointerNull::get( 4202 cast<llvm::PointerType>(TaskPrivatesMapTy)); 4203 } 4204 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 4205 // kmp_task_t *tt); 4206 llvm::Function *TaskEntry = emitProxyTaskFunction( 4207 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4208 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 4209 TaskPrivatesMap); 4210 4211 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 4212 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 4213 // kmp_routine_entry_t *task_entry); 4214 // Task flags. Format is taken from 4215 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 4216 // description of kmp_tasking_flags struct. 4217 enum { 4218 TiedFlag = 0x1, 4219 FinalFlag = 0x2, 4220 DestructorsFlag = 0x8, 4221 PriorityFlag = 0x20, 4222 DetachableFlag = 0x40, 4223 }; 4224 unsigned Flags = Data.Tied ? TiedFlag : 0; 4225 bool NeedsCleanup = false; 4226 if (!Privates.empty()) { 4227 NeedsCleanup = 4228 checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD, Privates); 4229 if (NeedsCleanup) 4230 Flags = Flags | DestructorsFlag; 4231 } 4232 if (Data.Priority.getInt()) 4233 Flags = Flags | PriorityFlag; 4234 if (D.hasClausesOfKind<OMPDetachClause>()) 4235 Flags = Flags | DetachableFlag; 4236 llvm::Value *TaskFlags = 4237 Data.Final.getPointer() 4238 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 4239 CGF.Builder.getInt32(FinalFlag), 4240 CGF.Builder.getInt32(/*C=*/0)) 4241 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 4242 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 4243 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 4244 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 4245 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 4246 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4247 TaskEntry, KmpRoutineEntryPtrTy)}; 4248 llvm::Value *NewTask; 4249 if (D.hasClausesOfKind<OMPNowaitClause>()) { 4250 // Check if we have any device clause associated with the directive. 4251 const Expr *Device = nullptr; 4252 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 4253 Device = C->getDevice(); 4254 // Emit device ID if any otherwise use default value. 4255 llvm::Value *DeviceID; 4256 if (Device) 4257 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 4258 CGF.Int64Ty, /*isSigned=*/true); 4259 else 4260 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 4261 AllocArgs.push_back(DeviceID); 4262 NewTask = CGF.EmitRuntimeCall( 4263 OMPBuilder.getOrCreateRuntimeFunction( 4264 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc), 4265 AllocArgs); 4266 } else { 4267 NewTask = 4268 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 4269 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc), 4270 AllocArgs); 4271 } 4272 // Emit detach clause initialization. 4273 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid, 4274 // task_descriptor); 4275 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) { 4276 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts(); 4277 LValue EvtLVal = CGF.EmitLValue(Evt); 4278 4279 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 4280 // int gtid, kmp_task_t *task); 4281 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc()); 4282 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc()); 4283 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false); 4284 llvm::Value *EvtVal = CGF.EmitRuntimeCall( 4285 OMPBuilder.getOrCreateRuntimeFunction( 4286 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event), 4287 {Loc, Tid, NewTask}); 4288 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(), 4289 Evt->getExprLoc()); 4290 CGF.EmitStoreOfScalar(EvtVal, EvtLVal); 4291 } 4292 // Process affinity clauses. 4293 if (D.hasClausesOfKind<OMPAffinityClause>()) { 4294 // Process list of affinity data. 4295 ASTContext &C = CGM.getContext(); 4296 Address AffinitiesArray = Address::invalid(); 4297 // Calculate number of elements to form the array of affinity data. 4298 llvm::Value *NumOfElements = nullptr; 4299 unsigned NumAffinities = 0; 4300 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4301 if (const Expr *Modifier = C->getModifier()) { 4302 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts()); 4303 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4304 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4305 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4306 NumOfElements = 4307 NumOfElements ? CGF.Builder.CreateNUWMul(NumOfElements, Sz) : Sz; 4308 } 4309 } else { 4310 NumAffinities += C->varlist_size(); 4311 } 4312 } 4313 getKmpAffinityType(CGM.getContext(), KmpTaskAffinityInfoTy); 4314 // Fields ids in kmp_task_affinity_info record. 4315 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags }; 4316 4317 QualType KmpTaskAffinityInfoArrayTy; 4318 if (NumOfElements) { 4319 NumOfElements = CGF.Builder.CreateNUWAdd( 4320 llvm::ConstantInt::get(CGF.SizeTy, NumAffinities), NumOfElements); 4321 OpaqueValueExpr OVE( 4322 Loc, 4323 C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0), 4324 VK_RValue); 4325 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 4326 RValue::get(NumOfElements)); 4327 KmpTaskAffinityInfoArrayTy = 4328 C.getVariableArrayType(KmpTaskAffinityInfoTy, &OVE, ArrayType::Normal, 4329 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4330 // Properly emit variable-sized array. 4331 auto *PD = ImplicitParamDecl::Create(C, KmpTaskAffinityInfoArrayTy, 4332 ImplicitParamDecl::Other); 4333 CGF.EmitVarDecl(*PD); 4334 AffinitiesArray = CGF.GetAddrOfLocalVar(PD); 4335 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4336 /*isSigned=*/false); 4337 } else { 4338 KmpTaskAffinityInfoArrayTy = C.getConstantArrayType( 4339 KmpTaskAffinityInfoTy, 4340 llvm::APInt(C.getTypeSize(C.getSizeType()), NumAffinities), nullptr, 4341 ArrayType::Normal, /*IndexTypeQuals=*/0); 4342 AffinitiesArray = 4343 CGF.CreateMemTemp(KmpTaskAffinityInfoArrayTy, ".affs.arr.addr"); 4344 AffinitiesArray = CGF.Builder.CreateConstArrayGEP(AffinitiesArray, 0); 4345 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumAffinities, 4346 /*isSigned=*/false); 4347 } 4348 4349 const auto *KmpAffinityInfoRD = KmpTaskAffinityInfoTy->getAsRecordDecl(); 4350 // Fill array by elements without iterators. 4351 unsigned Pos = 0; 4352 bool HasIterator = false; 4353 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4354 if (C->getModifier()) { 4355 HasIterator = true; 4356 continue; 4357 } 4358 for (const Expr *E : C->varlists()) { 4359 llvm::Value *Addr; 4360 llvm::Value *Size; 4361 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4362 LValue Base = 4363 CGF.MakeAddrLValue(CGF.Builder.CreateConstGEP(AffinitiesArray, Pos), 4364 KmpTaskAffinityInfoTy); 4365 // affs[i].base_addr = &<Affinities[i].second>; 4366 LValue BaseAddrLVal = CGF.EmitLValueForField( 4367 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4368 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4369 BaseAddrLVal); 4370 // affs[i].len = sizeof(<Affinities[i].second>); 4371 LValue LenLVal = CGF.EmitLValueForField( 4372 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4373 CGF.EmitStoreOfScalar(Size, LenLVal); 4374 ++Pos; 4375 } 4376 } 4377 LValue PosLVal; 4378 if (HasIterator) { 4379 PosLVal = CGF.MakeAddrLValue( 4380 CGF.CreateMemTemp(C.getSizeType(), "affs.counter.addr"), 4381 C.getSizeType()); 4382 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4383 } 4384 // Process elements with iterators. 4385 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4386 const Expr *Modifier = C->getModifier(); 4387 if (!Modifier) 4388 continue; 4389 OMPIteratorGeneratorScope IteratorScope( 4390 CGF, cast_or_null<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts())); 4391 for (const Expr *E : C->varlists()) { 4392 llvm::Value *Addr; 4393 llvm::Value *Size; 4394 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4395 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4396 LValue Base = CGF.MakeAddrLValue( 4397 Address(CGF.Builder.CreateGEP(AffinitiesArray.getPointer(), Idx), 4398 AffinitiesArray.getAlignment()), 4399 KmpTaskAffinityInfoTy); 4400 // affs[i].base_addr = &<Affinities[i].second>; 4401 LValue BaseAddrLVal = CGF.EmitLValueForField( 4402 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4403 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4404 BaseAddrLVal); 4405 // affs[i].len = sizeof(<Affinities[i].second>); 4406 LValue LenLVal = CGF.EmitLValueForField( 4407 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4408 CGF.EmitStoreOfScalar(Size, LenLVal); 4409 Idx = CGF.Builder.CreateNUWAdd( 4410 Idx, llvm::ConstantInt::get(Idx->getType(), 1)); 4411 CGF.EmitStoreOfScalar(Idx, PosLVal); 4412 } 4413 } 4414 // Call to kmp_int32 __kmpc_omp_reg_task_with_affinity(ident_t *loc_ref, 4415 // kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 4416 // naffins, kmp_task_affinity_info_t *affin_list); 4417 llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); 4418 llvm::Value *GTid = getThreadID(CGF, Loc); 4419 llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4420 AffinitiesArray.getPointer(), CGM.VoidPtrTy); 4421 // FIXME: Emit the function and ignore its result for now unless the 4422 // runtime function is properly implemented. 4423 (void)CGF.EmitRuntimeCall( 4424 OMPBuilder.getOrCreateRuntimeFunction( 4425 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity), 4426 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr}); 4427 } 4428 llvm::Value *NewTaskNewTaskTTy = 4429 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4430 NewTask, KmpTaskTWithPrivatesPtrTy); 4431 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 4432 KmpTaskTWithPrivatesQTy); 4433 LValue TDBase = 4434 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4435 // Fill the data in the resulting kmp_task_t record. 4436 // Copy shareds if there are any. 4437 Address KmpTaskSharedsPtr = Address::invalid(); 4438 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 4439 KmpTaskSharedsPtr = 4440 Address(CGF.EmitLoadOfScalar( 4441 CGF.EmitLValueForField( 4442 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 4443 KmpTaskTShareds)), 4444 Loc), 4445 CGM.getNaturalTypeAlignment(SharedsTy)); 4446 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 4447 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 4448 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 4449 } 4450 // Emit initial values for private copies (if any). 4451 TaskResultTy Result; 4452 if (!Privates.empty()) { 4453 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 4454 SharedsTy, SharedsPtrTy, Data, Privates, 4455 /*ForDup=*/false); 4456 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 4457 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 4458 Result.TaskDupFn = emitTaskDupFunction( 4459 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 4460 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 4461 /*WithLastIter=*/!Data.LastprivateVars.empty()); 4462 } 4463 } 4464 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 4465 enum { Priority = 0, Destructors = 1 }; 4466 // Provide pointer to function with destructors for privates. 4467 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 4468 const RecordDecl *KmpCmplrdataUD = 4469 (*FI)->getType()->getAsUnionType()->getDecl(); 4470 if (NeedsCleanup) { 4471 llvm::Value *DestructorFn = emitDestructorsFunction( 4472 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4473 KmpTaskTWithPrivatesQTy); 4474 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 4475 LValue DestructorsLV = CGF.EmitLValueForField( 4476 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 4477 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4478 DestructorFn, KmpRoutineEntryPtrTy), 4479 DestructorsLV); 4480 } 4481 // Set priority. 4482 if (Data.Priority.getInt()) { 4483 LValue Data2LV = CGF.EmitLValueForField( 4484 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 4485 LValue PriorityLV = CGF.EmitLValueForField( 4486 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 4487 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 4488 } 4489 Result.NewTask = NewTask; 4490 Result.TaskEntry = TaskEntry; 4491 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 4492 Result.TDBase = TDBase; 4493 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 4494 return Result; 4495 } 4496 4497 namespace { 4498 /// Dependence kind for RTL. 4499 enum RTLDependenceKindTy { 4500 DepIn = 0x01, 4501 DepInOut = 0x3, 4502 DepMutexInOutSet = 0x4 4503 }; 4504 /// Fields ids in kmp_depend_info record. 4505 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 4506 } // namespace 4507 4508 /// Translates internal dependency kind into the runtime kind. 4509 static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { 4510 RTLDependenceKindTy DepKind; 4511 switch (K) { 4512 case OMPC_DEPEND_in: 4513 DepKind = DepIn; 4514 break; 4515 // Out and InOut dependencies must use the same code. 4516 case OMPC_DEPEND_out: 4517 case OMPC_DEPEND_inout: 4518 DepKind = DepInOut; 4519 break; 4520 case OMPC_DEPEND_mutexinoutset: 4521 DepKind = DepMutexInOutSet; 4522 break; 4523 case OMPC_DEPEND_source: 4524 case OMPC_DEPEND_sink: 4525 case OMPC_DEPEND_depobj: 4526 case OMPC_DEPEND_unknown: 4527 llvm_unreachable("Unknown task dependence type"); 4528 } 4529 return DepKind; 4530 } 4531 4532 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4533 static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, 4534 QualType &FlagsTy) { 4535 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 4536 if (KmpDependInfoTy.isNull()) { 4537 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 4538 KmpDependInfoRD->startDefinition(); 4539 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 4540 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 4541 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 4542 KmpDependInfoRD->completeDefinition(); 4543 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 4544 } 4545 } 4546 4547 std::pair<llvm::Value *, LValue> 4548 CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, 4549 SourceLocation Loc) { 4550 ASTContext &C = CGM.getContext(); 4551 QualType FlagsTy; 4552 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4553 RecordDecl *KmpDependInfoRD = 4554 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4555 LValue Base = CGF.EmitLoadOfPointerLValue( 4556 DepobjLVal.getAddress(CGF), 4557 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4558 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4559 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4560 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 4561 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4562 Base.getTBAAInfo()); 4563 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4564 Addr.getPointer(), 4565 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4566 LValue NumDepsBase = CGF.MakeAddrLValue( 4567 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4568 Base.getBaseInfo(), Base.getTBAAInfo()); 4569 // NumDeps = deps[i].base_addr; 4570 LValue BaseAddrLVal = CGF.EmitLValueForField( 4571 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4572 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc); 4573 return std::make_pair(NumDeps, Base); 4574 } 4575 4576 static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4577 llvm::PointerUnion<unsigned *, LValue *> Pos, 4578 const OMPTaskDataTy::DependData &Data, 4579 Address DependenciesArray) { 4580 CodeGenModule &CGM = CGF.CGM; 4581 ASTContext &C = CGM.getContext(); 4582 QualType FlagsTy; 4583 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4584 RecordDecl *KmpDependInfoRD = 4585 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4586 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 4587 4588 OMPIteratorGeneratorScope IteratorScope( 4589 CGF, cast_or_null<OMPIteratorExpr>( 4590 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4591 : nullptr)); 4592 for (const Expr *E : Data.DepExprs) { 4593 llvm::Value *Addr; 4594 llvm::Value *Size; 4595 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4596 LValue Base; 4597 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4598 Base = CGF.MakeAddrLValue( 4599 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy); 4600 } else { 4601 LValue &PosLVal = *Pos.get<LValue *>(); 4602 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4603 Base = CGF.MakeAddrLValue( 4604 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Idx), 4605 DependenciesArray.getAlignment()), 4606 KmpDependInfoTy); 4607 } 4608 // deps[i].base_addr = &<Dependencies[i].second>; 4609 LValue BaseAddrLVal = CGF.EmitLValueForField( 4610 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4611 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4612 BaseAddrLVal); 4613 // deps[i].len = sizeof(<Dependencies[i].second>); 4614 LValue LenLVal = CGF.EmitLValueForField( 4615 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 4616 CGF.EmitStoreOfScalar(Size, LenLVal); 4617 // deps[i].flags = <Dependencies[i].first>; 4618 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind); 4619 LValue FlagsLVal = CGF.EmitLValueForField( 4620 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 4621 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 4622 FlagsLVal); 4623 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4624 ++(*P); 4625 } else { 4626 LValue &PosLVal = *Pos.get<LValue *>(); 4627 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4628 Idx = CGF.Builder.CreateNUWAdd(Idx, 4629 llvm::ConstantInt::get(Idx->getType(), 1)); 4630 CGF.EmitStoreOfScalar(Idx, PosLVal); 4631 } 4632 } 4633 } 4634 4635 static SmallVector<llvm::Value *, 4> 4636 emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4637 const OMPTaskDataTy::DependData &Data) { 4638 assert(Data.DepKind == OMPC_DEPEND_depobj && 4639 "Expected depobj dependecy kind."); 4640 SmallVector<llvm::Value *, 4> Sizes; 4641 SmallVector<LValue, 4> SizeLVals; 4642 ASTContext &C = CGF.getContext(); 4643 QualType FlagsTy; 4644 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4645 RecordDecl *KmpDependInfoRD = 4646 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4647 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4648 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4649 { 4650 OMPIteratorGeneratorScope IteratorScope( 4651 CGF, cast_or_null<OMPIteratorExpr>( 4652 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4653 : nullptr)); 4654 for (const Expr *E : Data.DepExprs) { 4655 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4656 LValue Base = CGF.EmitLoadOfPointerLValue( 4657 DepobjLVal.getAddress(CGF), 4658 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4659 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4660 Base.getAddress(CGF), KmpDependInfoPtrT); 4661 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4662 Base.getTBAAInfo()); 4663 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4664 Addr.getPointer(), 4665 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4666 LValue NumDepsBase = CGF.MakeAddrLValue( 4667 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4668 Base.getBaseInfo(), Base.getTBAAInfo()); 4669 // NumDeps = deps[i].base_addr; 4670 LValue BaseAddrLVal = CGF.EmitLValueForField( 4671 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4672 llvm::Value *NumDeps = 4673 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4674 LValue NumLVal = CGF.MakeAddrLValue( 4675 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"), 4676 C.getUIntPtrType()); 4677 CGF.InitTempAlloca(NumLVal.getAddress(CGF), 4678 llvm::ConstantInt::get(CGF.IntPtrTy, 0)); 4679 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc()); 4680 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps); 4681 CGF.EmitStoreOfScalar(Add, NumLVal); 4682 SizeLVals.push_back(NumLVal); 4683 } 4684 } 4685 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) { 4686 llvm::Value *Size = 4687 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc()); 4688 Sizes.push_back(Size); 4689 } 4690 return Sizes; 4691 } 4692 4693 static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4694 LValue PosLVal, 4695 const OMPTaskDataTy::DependData &Data, 4696 Address DependenciesArray) { 4697 assert(Data.DepKind == OMPC_DEPEND_depobj && 4698 "Expected depobj dependecy kind."); 4699 ASTContext &C = CGF.getContext(); 4700 QualType FlagsTy; 4701 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4702 RecordDecl *KmpDependInfoRD = 4703 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4704 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4705 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4706 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy); 4707 { 4708 OMPIteratorGeneratorScope IteratorScope( 4709 CGF, cast_or_null<OMPIteratorExpr>( 4710 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4711 : nullptr)); 4712 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) { 4713 const Expr *E = Data.DepExprs[I]; 4714 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4715 LValue Base = CGF.EmitLoadOfPointerLValue( 4716 DepobjLVal.getAddress(CGF), 4717 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4718 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4719 Base.getAddress(CGF), KmpDependInfoPtrT); 4720 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4721 Base.getTBAAInfo()); 4722 4723 // Get number of elements in a single depobj. 4724 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4725 Addr.getPointer(), 4726 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4727 LValue NumDepsBase = CGF.MakeAddrLValue( 4728 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4729 Base.getBaseInfo(), Base.getTBAAInfo()); 4730 // NumDeps = deps[i].base_addr; 4731 LValue BaseAddrLVal = CGF.EmitLValueForField( 4732 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4733 llvm::Value *NumDeps = 4734 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4735 4736 // memcopy dependency data. 4737 llvm::Value *Size = CGF.Builder.CreateNUWMul( 4738 ElSize, 4739 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); 4740 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4741 Address DepAddr = 4742 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Pos), 4743 DependenciesArray.getAlignment()); 4744 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); 4745 4746 // Increase pos. 4747 // pos += size; 4748 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps); 4749 CGF.EmitStoreOfScalar(Add, PosLVal); 4750 } 4751 } 4752 } 4753 4754 std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause( 4755 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies, 4756 SourceLocation Loc) { 4757 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) { 4758 return D.DepExprs.empty(); 4759 })) 4760 return std::make_pair(nullptr, Address::invalid()); 4761 // Process list of dependencies. 4762 ASTContext &C = CGM.getContext(); 4763 Address DependenciesArray = Address::invalid(); 4764 llvm::Value *NumOfElements = nullptr; 4765 unsigned NumDependencies = std::accumulate( 4766 Dependencies.begin(), Dependencies.end(), 0, 4767 [](unsigned V, const OMPTaskDataTy::DependData &D) { 4768 return D.DepKind == OMPC_DEPEND_depobj 4769 ? V 4770 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size())); 4771 }); 4772 QualType FlagsTy; 4773 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4774 bool HasDepobjDeps = false; 4775 bool HasRegularWithIterators = false; 4776 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0); 4777 llvm::Value *NumOfRegularWithIterators = 4778 llvm::ConstantInt::get(CGF.IntPtrTy, 1); 4779 // Calculate number of depobj dependecies and regular deps with the iterators. 4780 for (const OMPTaskDataTy::DependData &D : Dependencies) { 4781 if (D.DepKind == OMPC_DEPEND_depobj) { 4782 SmallVector<llvm::Value *, 4> Sizes = 4783 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D); 4784 for (llvm::Value *Size : Sizes) { 4785 NumOfDepobjElements = 4786 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size); 4787 } 4788 HasDepobjDeps = true; 4789 continue; 4790 } 4791 // Include number of iterations, if any. 4792 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) { 4793 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4794 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4795 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false); 4796 NumOfRegularWithIterators = 4797 CGF.Builder.CreateNUWMul(NumOfRegularWithIterators, Sz); 4798 } 4799 HasRegularWithIterators = true; 4800 continue; 4801 } 4802 } 4803 4804 QualType KmpDependInfoArrayTy; 4805 if (HasDepobjDeps || HasRegularWithIterators) { 4806 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies, 4807 /*isSigned=*/false); 4808 if (HasDepobjDeps) { 4809 NumOfElements = 4810 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements); 4811 } 4812 if (HasRegularWithIterators) { 4813 NumOfElements = 4814 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements); 4815 } 4816 OpaqueValueExpr OVE(Loc, 4817 C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0), 4818 VK_RValue); 4819 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 4820 RValue::get(NumOfElements)); 4821 KmpDependInfoArrayTy = 4822 C.getVariableArrayType(KmpDependInfoTy, &OVE, ArrayType::Normal, 4823 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4824 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy); 4825 // Properly emit variable-sized array. 4826 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy, 4827 ImplicitParamDecl::Other); 4828 CGF.EmitVarDecl(*PD); 4829 DependenciesArray = CGF.GetAddrOfLocalVar(PD); 4830 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4831 /*isSigned=*/false); 4832 } else { 4833 KmpDependInfoArrayTy = C.getConstantArrayType( 4834 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr, 4835 ArrayType::Normal, /*IndexTypeQuals=*/0); 4836 DependenciesArray = 4837 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 4838 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0); 4839 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 4840 /*isSigned=*/false); 4841 } 4842 unsigned Pos = 0; 4843 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4844 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4845 Dependencies[I].IteratorExpr) 4846 continue; 4847 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I], 4848 DependenciesArray); 4849 } 4850 // Copy regular dependecies with iterators. 4851 LValue PosLVal = CGF.MakeAddrLValue( 4852 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType()); 4853 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4854 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4855 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4856 !Dependencies[I].IteratorExpr) 4857 continue; 4858 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I], 4859 DependenciesArray); 4860 } 4861 // Copy final depobj arrays without iterators. 4862 if (HasDepobjDeps) { 4863 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4864 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj) 4865 continue; 4866 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I], 4867 DependenciesArray); 4868 } 4869 } 4870 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4871 DependenciesArray, CGF.VoidPtrTy); 4872 return std::make_pair(NumOfElements, DependenciesArray); 4873 } 4874 4875 Address CGOpenMPRuntime::emitDepobjDependClause( 4876 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, 4877 SourceLocation Loc) { 4878 if (Dependencies.DepExprs.empty()) 4879 return Address::invalid(); 4880 // Process list of dependencies. 4881 ASTContext &C = CGM.getContext(); 4882 Address DependenciesArray = Address::invalid(); 4883 unsigned NumDependencies = Dependencies.DepExprs.size(); 4884 QualType FlagsTy; 4885 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4886 RecordDecl *KmpDependInfoRD = 4887 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4888 4889 llvm::Value *Size; 4890 // Define type kmp_depend_info[<Dependencies.size()>]; 4891 // For depobj reserve one extra element to store the number of elements. 4892 // It is required to handle depobj(x) update(in) construct. 4893 // kmp_depend_info[<Dependencies.size()>] deps; 4894 llvm::Value *NumDepsVal; 4895 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy); 4896 if (const auto *IE = 4897 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) { 4898 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1); 4899 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4900 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4901 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4902 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz); 4903 } 4904 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1), 4905 NumDepsVal); 4906 CharUnits SizeInBytes = 4907 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align); 4908 llvm::Value *RecSize = CGM.getSize(SizeInBytes); 4909 Size = CGF.Builder.CreateNUWMul(Size, RecSize); 4910 NumDepsVal = 4911 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false); 4912 } else { 4913 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 4914 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1), 4915 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 4916 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy); 4917 Size = CGM.getSize(Sz.alignTo(Align)); 4918 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies); 4919 } 4920 // Need to allocate on the dynamic memory. 4921 llvm::Value *ThreadID = getThreadID(CGF, Loc); 4922 // Use default allocator. 4923 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4924 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 4925 4926 llvm::Value *Addr = 4927 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 4928 CGM.getModule(), OMPRTL___kmpc_alloc), 4929 Args, ".dep.arr.addr"); 4930 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4931 Addr, CGF.ConvertTypeForMem(KmpDependInfoTy)->getPointerTo()); 4932 DependenciesArray = Address(Addr, Align); 4933 // Write number of elements in the first element of array for depobj. 4934 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy); 4935 // deps[i].base_addr = NumDependencies; 4936 LValue BaseAddrLVal = CGF.EmitLValueForField( 4937 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4938 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal); 4939 llvm::PointerUnion<unsigned *, LValue *> Pos; 4940 unsigned Idx = 1; 4941 LValue PosLVal; 4942 if (Dependencies.IteratorExpr) { 4943 PosLVal = CGF.MakeAddrLValue( 4944 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"), 4945 C.getSizeType()); 4946 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal, 4947 /*IsInit=*/true); 4948 Pos = &PosLVal; 4949 } else { 4950 Pos = &Idx; 4951 } 4952 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray); 4953 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4954 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy); 4955 return DependenciesArray; 4956 } 4957 4958 void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 4959 SourceLocation Loc) { 4960 ASTContext &C = CGM.getContext(); 4961 QualType FlagsTy; 4962 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4963 LValue Base = CGF.EmitLoadOfPointerLValue( 4964 DepobjLVal.getAddress(CGF), 4965 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4966 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4967 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4968 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 4969 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4970 Addr.getPointer(), 4971 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4972 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, 4973 CGF.VoidPtrTy); 4974 llvm::Value *ThreadID = getThreadID(CGF, Loc); 4975 // Use default allocator. 4976 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4977 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator}; 4978 4979 // _kmpc_free(gtid, addr, nullptr); 4980 (void)CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 4981 CGM.getModule(), OMPRTL___kmpc_free), 4982 Args); 4983 } 4984 4985 void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 4986 OpenMPDependClauseKind NewDepKind, 4987 SourceLocation Loc) { 4988 ASTContext &C = CGM.getContext(); 4989 QualType FlagsTy; 4990 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4991 RecordDecl *KmpDependInfoRD = 4992 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4993 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 4994 llvm::Value *NumDeps; 4995 LValue Base; 4996 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 4997 4998 Address Begin = Base.getAddress(CGF); 4999 // Cast from pointer to array type to pointer to single element. 5000 llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps); 5001 // The basic structure here is a while-do loop. 5002 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); 5003 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); 5004 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5005 CGF.EmitBlock(BodyBB); 5006 llvm::PHINode *ElementPHI = 5007 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); 5008 ElementPHI->addIncoming(Begin.getPointer(), EntryBB); 5009 Begin = Address(ElementPHI, Begin.getAlignment()); 5010 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), 5011 Base.getTBAAInfo()); 5012 // deps[i].flags = NewDepKind; 5013 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind); 5014 LValue FlagsLVal = CGF.EmitLValueForField( 5015 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5016 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5017 FlagsLVal); 5018 5019 // Shift the address forward by one element. 5020 Address ElementNext = 5021 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); 5022 ElementPHI->addIncoming(ElementNext.getPointer(), 5023 CGF.Builder.GetInsertBlock()); 5024 llvm::Value *IsEmpty = 5025 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); 5026 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5027 // Done. 5028 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5029 } 5030 5031 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5032 const OMPExecutableDirective &D, 5033 llvm::Function *TaskFunction, 5034 QualType SharedsTy, Address Shareds, 5035 const Expr *IfCond, 5036 const OMPTaskDataTy &Data) { 5037 if (!CGF.HaveInsertPoint()) 5038 return; 5039 5040 TaskResultTy Result = 5041 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5042 llvm::Value *NewTask = Result.NewTask; 5043 llvm::Function *TaskEntry = Result.TaskEntry; 5044 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5045 LValue TDBase = Result.TDBase; 5046 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5047 // Process list of dependences. 5048 Address DependenciesArray = Address::invalid(); 5049 llvm::Value *NumOfElements; 5050 std::tie(NumOfElements, DependenciesArray) = 5051 emitDependClause(CGF, Data.Dependences, Loc); 5052 5053 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5054 // libcall. 5055 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5056 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5057 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5058 // list is not empty 5059 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5060 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5061 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5062 llvm::Value *DepTaskArgs[7]; 5063 if (!Data.Dependences.empty()) { 5064 DepTaskArgs[0] = UpLoc; 5065 DepTaskArgs[1] = ThreadID; 5066 DepTaskArgs[2] = NewTask; 5067 DepTaskArgs[3] = NumOfElements; 5068 DepTaskArgs[4] = DependenciesArray.getPointer(); 5069 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5070 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5071 } 5072 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs, 5073 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5074 if (!Data.Tied) { 5075 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5076 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5077 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5078 } 5079 if (!Data.Dependences.empty()) { 5080 CGF.EmitRuntimeCall( 5081 OMPBuilder.getOrCreateRuntimeFunction( 5082 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps), 5083 DepTaskArgs); 5084 } else { 5085 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5086 CGM.getModule(), OMPRTL___kmpc_omp_task), 5087 TaskArgs); 5088 } 5089 // Check if parent region is untied and build return for untied task; 5090 if (auto *Region = 5091 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5092 Region->emitUntiedSwitch(CGF); 5093 }; 5094 5095 llvm::Value *DepWaitTaskArgs[6]; 5096 if (!Data.Dependences.empty()) { 5097 DepWaitTaskArgs[0] = UpLoc; 5098 DepWaitTaskArgs[1] = ThreadID; 5099 DepWaitTaskArgs[2] = NumOfElements; 5100 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5101 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5102 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5103 } 5104 auto &M = CGM.getModule(); 5105 auto &&ElseCodeGen = [this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy, 5106 TaskEntry, &Data, &DepWaitTaskArgs, 5107 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5108 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5109 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5110 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5111 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5112 // is specified. 5113 if (!Data.Dependences.empty()) 5114 CGF.EmitRuntimeCall( 5115 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps), 5116 DepWaitTaskArgs); 5117 // Call proxy_task_entry(gtid, new_task); 5118 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5119 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5120 Action.Enter(CGF); 5121 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5122 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5123 OutlinedFnArgs); 5124 }; 5125 5126 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5127 // kmp_task_t *new_task); 5128 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5129 // kmp_task_t *new_task); 5130 RegionCodeGenTy RCG(CodeGen); 5131 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 5132 M, OMPRTL___kmpc_omp_task_begin_if0), 5133 TaskArgs, 5134 OMPBuilder.getOrCreateRuntimeFunction( 5135 M, OMPRTL___kmpc_omp_task_complete_if0), 5136 TaskArgs); 5137 RCG.setAction(Action); 5138 RCG(CGF); 5139 }; 5140 5141 if (IfCond) { 5142 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5143 } else { 5144 RegionCodeGenTy ThenRCG(ThenCodeGen); 5145 ThenRCG(CGF); 5146 } 5147 } 5148 5149 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5150 const OMPLoopDirective &D, 5151 llvm::Function *TaskFunction, 5152 QualType SharedsTy, Address Shareds, 5153 const Expr *IfCond, 5154 const OMPTaskDataTy &Data) { 5155 if (!CGF.HaveInsertPoint()) 5156 return; 5157 TaskResultTy Result = 5158 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5159 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5160 // libcall. 5161 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5162 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5163 // sched, kmp_uint64 grainsize, void *task_dup); 5164 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5165 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5166 llvm::Value *IfVal; 5167 if (IfCond) { 5168 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5169 /*isSigned=*/true); 5170 } else { 5171 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5172 } 5173 5174 LValue LBLVal = CGF.EmitLValueForField( 5175 Result.TDBase, 5176 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5177 const auto *LBVar = 5178 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5179 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5180 LBLVal.getQuals(), 5181 /*IsInitializer=*/true); 5182 LValue UBLVal = CGF.EmitLValueForField( 5183 Result.TDBase, 5184 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5185 const auto *UBVar = 5186 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5187 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5188 UBLVal.getQuals(), 5189 /*IsInitializer=*/true); 5190 LValue StLVal = CGF.EmitLValueForField( 5191 Result.TDBase, 5192 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5193 const auto *StVar = 5194 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5195 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5196 StLVal.getQuals(), 5197 /*IsInitializer=*/true); 5198 // Store reductions address. 5199 LValue RedLVal = CGF.EmitLValueForField( 5200 Result.TDBase, 5201 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5202 if (Data.Reductions) { 5203 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5204 } else { 5205 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5206 CGF.getContext().VoidPtrTy); 5207 } 5208 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5209 llvm::Value *TaskArgs[] = { 5210 UpLoc, 5211 ThreadID, 5212 Result.NewTask, 5213 IfVal, 5214 LBLVal.getPointer(CGF), 5215 UBLVal.getPointer(CGF), 5216 CGF.EmitLoadOfScalar(StLVal, Loc), 5217 llvm::ConstantInt::getSigned( 5218 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5219 llvm::ConstantInt::getSigned( 5220 CGF.IntTy, Data.Schedule.getPointer() 5221 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5222 : NoSchedule), 5223 Data.Schedule.getPointer() 5224 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5225 /*isSigned=*/false) 5226 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5227 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5228 Result.TaskDupFn, CGF.VoidPtrTy) 5229 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5230 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5231 CGM.getModule(), OMPRTL___kmpc_taskloop), 5232 TaskArgs); 5233 } 5234 5235 /// Emit reduction operation for each element of array (required for 5236 /// array sections) LHS op = RHS. 5237 /// \param Type Type of array. 5238 /// \param LHSVar Variable on the left side of the reduction operation 5239 /// (references element of array in original variable). 5240 /// \param RHSVar Variable on the right side of the reduction operation 5241 /// (references element of array in original variable). 5242 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5243 /// RHSVar. 5244 static void EmitOMPAggregateReduction( 5245 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5246 const VarDecl *RHSVar, 5247 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5248 const Expr *, const Expr *)> &RedOpGen, 5249 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5250 const Expr *UpExpr = nullptr) { 5251 // Perform element-by-element initialization. 5252 QualType ElementTy; 5253 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5254 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5255 5256 // Drill down to the base element type on both arrays. 5257 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5258 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5259 5260 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5261 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5262 // Cast from pointer to array type to pointer to single element. 5263 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5264 // The basic structure here is a while-do loop. 5265 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5266 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5267 llvm::Value *IsEmpty = 5268 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5269 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5270 5271 // Enter the loop body, making that address the current address. 5272 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5273 CGF.EmitBlock(BodyBB); 5274 5275 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5276 5277 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5278 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5279 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5280 Address RHSElementCurrent = 5281 Address(RHSElementPHI, 5282 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5283 5284 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5285 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5286 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5287 Address LHSElementCurrent = 5288 Address(LHSElementPHI, 5289 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5290 5291 // Emit copy. 5292 CodeGenFunction::OMPPrivateScope Scope(CGF); 5293 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5294 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5295 Scope.Privatize(); 5296 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5297 Scope.ForceCleanup(); 5298 5299 // Shift the address forward by one element. 5300 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5301 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5302 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5303 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5304 // Check whether we've reached the end. 5305 llvm::Value *Done = 5306 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5307 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5308 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5309 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5310 5311 // Done. 5312 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5313 } 5314 5315 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5316 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5317 /// UDR combiner function. 5318 static void emitReductionCombiner(CodeGenFunction &CGF, 5319 const Expr *ReductionOp) { 5320 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5321 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5322 if (const auto *DRE = 5323 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5324 if (const auto *DRD = 5325 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5326 std::pair<llvm::Function *, llvm::Function *> Reduction = 5327 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5328 RValue Func = RValue::get(Reduction.first); 5329 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5330 CGF.EmitIgnoredExpr(ReductionOp); 5331 return; 5332 } 5333 CGF.EmitIgnoredExpr(ReductionOp); 5334 } 5335 5336 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5337 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5338 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5339 ArrayRef<const Expr *> ReductionOps) { 5340 ASTContext &C = CGM.getContext(); 5341 5342 // void reduction_func(void *LHSArg, void *RHSArg); 5343 FunctionArgList Args; 5344 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5345 ImplicitParamDecl::Other); 5346 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5347 ImplicitParamDecl::Other); 5348 Args.push_back(&LHSArg); 5349 Args.push_back(&RHSArg); 5350 const auto &CGFI = 5351 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5352 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5353 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5354 llvm::GlobalValue::InternalLinkage, Name, 5355 &CGM.getModule()); 5356 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5357 Fn->setDoesNotRecurse(); 5358 CodeGenFunction CGF(CGM); 5359 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5360 5361 // Dst = (void*[n])(LHSArg); 5362 // Src = (void*[n])(RHSArg); 5363 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5364 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5365 ArgsType), CGF.getPointerAlign()); 5366 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5367 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5368 ArgsType), CGF.getPointerAlign()); 5369 5370 // ... 5371 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5372 // ... 5373 CodeGenFunction::OMPPrivateScope Scope(CGF); 5374 auto IPriv = Privates.begin(); 5375 unsigned Idx = 0; 5376 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5377 const auto *RHSVar = 5378 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5379 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5380 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5381 }); 5382 const auto *LHSVar = 5383 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5384 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5385 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5386 }); 5387 QualType PrivTy = (*IPriv)->getType(); 5388 if (PrivTy->isVariablyModifiedType()) { 5389 // Get array size and emit VLA type. 5390 ++Idx; 5391 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5392 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5393 const VariableArrayType *VLA = 5394 CGF.getContext().getAsVariableArrayType(PrivTy); 5395 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5396 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5397 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5398 CGF.EmitVariablyModifiedType(PrivTy); 5399 } 5400 } 5401 Scope.Privatize(); 5402 IPriv = Privates.begin(); 5403 auto ILHS = LHSExprs.begin(); 5404 auto IRHS = RHSExprs.begin(); 5405 for (const Expr *E : ReductionOps) { 5406 if ((*IPriv)->getType()->isArrayType()) { 5407 // Emit reduction for array section. 5408 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5409 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5410 EmitOMPAggregateReduction( 5411 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5412 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5413 emitReductionCombiner(CGF, E); 5414 }); 5415 } else { 5416 // Emit reduction for array subscript or single variable. 5417 emitReductionCombiner(CGF, E); 5418 } 5419 ++IPriv; 5420 ++ILHS; 5421 ++IRHS; 5422 } 5423 Scope.ForceCleanup(); 5424 CGF.FinishFunction(); 5425 return Fn; 5426 } 5427 5428 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5429 const Expr *ReductionOp, 5430 const Expr *PrivateRef, 5431 const DeclRefExpr *LHS, 5432 const DeclRefExpr *RHS) { 5433 if (PrivateRef->getType()->isArrayType()) { 5434 // Emit reduction for array section. 5435 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5436 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5437 EmitOMPAggregateReduction( 5438 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5439 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5440 emitReductionCombiner(CGF, ReductionOp); 5441 }); 5442 } else { 5443 // Emit reduction for array subscript or single variable. 5444 emitReductionCombiner(CGF, ReductionOp); 5445 } 5446 } 5447 5448 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5449 ArrayRef<const Expr *> Privates, 5450 ArrayRef<const Expr *> LHSExprs, 5451 ArrayRef<const Expr *> RHSExprs, 5452 ArrayRef<const Expr *> ReductionOps, 5453 ReductionOptionsTy Options) { 5454 if (!CGF.HaveInsertPoint()) 5455 return; 5456 5457 bool WithNowait = Options.WithNowait; 5458 bool SimpleReduction = Options.SimpleReduction; 5459 5460 // Next code should be emitted for reduction: 5461 // 5462 // static kmp_critical_name lock = { 0 }; 5463 // 5464 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5465 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5466 // ... 5467 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5468 // *(Type<n>-1*)rhs[<n>-1]); 5469 // } 5470 // 5471 // ... 5472 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5473 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5474 // RedList, reduce_func, &<lock>)) { 5475 // case 1: 5476 // ... 5477 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5478 // ... 5479 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5480 // break; 5481 // case 2: 5482 // ... 5483 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5484 // ... 5485 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5486 // break; 5487 // default:; 5488 // } 5489 // 5490 // if SimpleReduction is true, only the next code is generated: 5491 // ... 5492 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5493 // ... 5494 5495 ASTContext &C = CGM.getContext(); 5496 5497 if (SimpleReduction) { 5498 CodeGenFunction::RunCleanupsScope Scope(CGF); 5499 auto IPriv = Privates.begin(); 5500 auto ILHS = LHSExprs.begin(); 5501 auto IRHS = RHSExprs.begin(); 5502 for (const Expr *E : ReductionOps) { 5503 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5504 cast<DeclRefExpr>(*IRHS)); 5505 ++IPriv; 5506 ++ILHS; 5507 ++IRHS; 5508 } 5509 return; 5510 } 5511 5512 // 1. Build a list of reduction variables. 5513 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5514 auto Size = RHSExprs.size(); 5515 for (const Expr *E : Privates) { 5516 if (E->getType()->isVariablyModifiedType()) 5517 // Reserve place for array size. 5518 ++Size; 5519 } 5520 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5521 QualType ReductionArrayTy = 5522 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5523 /*IndexTypeQuals=*/0); 5524 Address ReductionList = 5525 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5526 auto IPriv = Privates.begin(); 5527 unsigned Idx = 0; 5528 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5529 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5530 CGF.Builder.CreateStore( 5531 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5532 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5533 Elem); 5534 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5535 // Store array size. 5536 ++Idx; 5537 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5538 llvm::Value *Size = CGF.Builder.CreateIntCast( 5539 CGF.getVLASize( 5540 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5541 .NumElts, 5542 CGF.SizeTy, /*isSigned=*/false); 5543 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5544 Elem); 5545 } 5546 } 5547 5548 // 2. Emit reduce_func(). 5549 llvm::Function *ReductionFn = emitReductionFunction( 5550 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5551 LHSExprs, RHSExprs, ReductionOps); 5552 5553 // 3. Create static kmp_critical_name lock = { 0 }; 5554 std::string Name = getName({"reduction"}); 5555 llvm::Value *Lock = getCriticalRegionLock(Name); 5556 5557 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5558 // RedList, reduce_func, &<lock>); 5559 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5560 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5561 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5562 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5563 ReductionList.getPointer(), CGF.VoidPtrTy); 5564 llvm::Value *Args[] = { 5565 IdentTLoc, // ident_t *<loc> 5566 ThreadId, // i32 <gtid> 5567 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5568 ReductionArrayTySize, // size_type sizeof(RedList) 5569 RL, // void *RedList 5570 ReductionFn, // void (*) (void *, void *) <reduce_func> 5571 Lock // kmp_critical_name *&<lock> 5572 }; 5573 llvm::Value *Res = CGF.EmitRuntimeCall( 5574 OMPBuilder.getOrCreateRuntimeFunction( 5575 CGM.getModule(), 5576 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce), 5577 Args); 5578 5579 // 5. Build switch(res) 5580 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5581 llvm::SwitchInst *SwInst = 5582 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5583 5584 // 6. Build case 1: 5585 // ... 5586 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5587 // ... 5588 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5589 // break; 5590 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5591 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5592 CGF.EmitBlock(Case1BB); 5593 5594 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5595 llvm::Value *EndArgs[] = { 5596 IdentTLoc, // ident_t *<loc> 5597 ThreadId, // i32 <gtid> 5598 Lock // kmp_critical_name *&<lock> 5599 }; 5600 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5601 CodeGenFunction &CGF, PrePostActionTy &Action) { 5602 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5603 auto IPriv = Privates.begin(); 5604 auto ILHS = LHSExprs.begin(); 5605 auto IRHS = RHSExprs.begin(); 5606 for (const Expr *E : ReductionOps) { 5607 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5608 cast<DeclRefExpr>(*IRHS)); 5609 ++IPriv; 5610 ++ILHS; 5611 ++IRHS; 5612 } 5613 }; 5614 RegionCodeGenTy RCG(CodeGen); 5615 CommonActionTy Action( 5616 nullptr, llvm::None, 5617 OMPBuilder.getOrCreateRuntimeFunction( 5618 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait 5619 : OMPRTL___kmpc_end_reduce), 5620 EndArgs); 5621 RCG.setAction(Action); 5622 RCG(CGF); 5623 5624 CGF.EmitBranch(DefaultBB); 5625 5626 // 7. Build case 2: 5627 // ... 5628 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5629 // ... 5630 // break; 5631 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5632 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5633 CGF.EmitBlock(Case2BB); 5634 5635 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5636 CodeGenFunction &CGF, PrePostActionTy &Action) { 5637 auto ILHS = LHSExprs.begin(); 5638 auto IRHS = RHSExprs.begin(); 5639 auto IPriv = Privates.begin(); 5640 for (const Expr *E : ReductionOps) { 5641 const Expr *XExpr = nullptr; 5642 const Expr *EExpr = nullptr; 5643 const Expr *UpExpr = nullptr; 5644 BinaryOperatorKind BO = BO_Comma; 5645 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5646 if (BO->getOpcode() == BO_Assign) { 5647 XExpr = BO->getLHS(); 5648 UpExpr = BO->getRHS(); 5649 } 5650 } 5651 // Try to emit update expression as a simple atomic. 5652 const Expr *RHSExpr = UpExpr; 5653 if (RHSExpr) { 5654 // Analyze RHS part of the whole expression. 5655 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5656 RHSExpr->IgnoreParenImpCasts())) { 5657 // If this is a conditional operator, analyze its condition for 5658 // min/max reduction operator. 5659 RHSExpr = ACO->getCond(); 5660 } 5661 if (const auto *BORHS = 5662 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5663 EExpr = BORHS->getRHS(); 5664 BO = BORHS->getOpcode(); 5665 } 5666 } 5667 if (XExpr) { 5668 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5669 auto &&AtomicRedGen = [BO, VD, 5670 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5671 const Expr *EExpr, const Expr *UpExpr) { 5672 LValue X = CGF.EmitLValue(XExpr); 5673 RValue E; 5674 if (EExpr) 5675 E = CGF.EmitAnyExpr(EExpr); 5676 CGF.EmitOMPAtomicSimpleUpdateExpr( 5677 X, E, BO, /*IsXLHSInRHSPart=*/true, 5678 llvm::AtomicOrdering::Monotonic, Loc, 5679 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5680 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5681 PrivateScope.addPrivate( 5682 VD, [&CGF, VD, XRValue, Loc]() { 5683 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5684 CGF.emitOMPSimpleStore( 5685 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5686 VD->getType().getNonReferenceType(), Loc); 5687 return LHSTemp; 5688 }); 5689 (void)PrivateScope.Privatize(); 5690 return CGF.EmitAnyExpr(UpExpr); 5691 }); 5692 }; 5693 if ((*IPriv)->getType()->isArrayType()) { 5694 // Emit atomic reduction for array section. 5695 const auto *RHSVar = 5696 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5697 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5698 AtomicRedGen, XExpr, EExpr, UpExpr); 5699 } else { 5700 // Emit atomic reduction for array subscript or single variable. 5701 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5702 } 5703 } else { 5704 // Emit as a critical region. 5705 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5706 const Expr *, const Expr *) { 5707 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5708 std::string Name = RT.getName({"atomic_reduction"}); 5709 RT.emitCriticalRegion( 5710 CGF, Name, 5711 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5712 Action.Enter(CGF); 5713 emitReductionCombiner(CGF, E); 5714 }, 5715 Loc); 5716 }; 5717 if ((*IPriv)->getType()->isArrayType()) { 5718 const auto *LHSVar = 5719 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5720 const auto *RHSVar = 5721 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5722 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5723 CritRedGen); 5724 } else { 5725 CritRedGen(CGF, nullptr, nullptr, nullptr); 5726 } 5727 } 5728 ++ILHS; 5729 ++IRHS; 5730 ++IPriv; 5731 } 5732 }; 5733 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5734 if (!WithNowait) { 5735 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5736 llvm::Value *EndArgs[] = { 5737 IdentTLoc, // ident_t *<loc> 5738 ThreadId, // i32 <gtid> 5739 Lock // kmp_critical_name *&<lock> 5740 }; 5741 CommonActionTy Action(nullptr, llvm::None, 5742 OMPBuilder.getOrCreateRuntimeFunction( 5743 CGM.getModule(), OMPRTL___kmpc_end_reduce), 5744 EndArgs); 5745 AtomicRCG.setAction(Action); 5746 AtomicRCG(CGF); 5747 } else { 5748 AtomicRCG(CGF); 5749 } 5750 5751 CGF.EmitBranch(DefaultBB); 5752 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5753 } 5754 5755 /// Generates unique name for artificial threadprivate variables. 5756 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5757 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5758 const Expr *Ref) { 5759 SmallString<256> Buffer; 5760 llvm::raw_svector_ostream Out(Buffer); 5761 const clang::DeclRefExpr *DE; 5762 const VarDecl *D = ::getBaseDecl(Ref, DE); 5763 if (!D) 5764 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5765 D = D->getCanonicalDecl(); 5766 std::string Name = CGM.getOpenMPRuntime().getName( 5767 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5768 Out << Prefix << Name << "_" 5769 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5770 return std::string(Out.str()); 5771 } 5772 5773 /// Emits reduction initializer function: 5774 /// \code 5775 /// void @.red_init(void* %arg, void* %orig) { 5776 /// %0 = bitcast void* %arg to <type>* 5777 /// store <type> <init>, <type>* %0 5778 /// ret void 5779 /// } 5780 /// \endcode 5781 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 5782 SourceLocation Loc, 5783 ReductionCodeGen &RCG, unsigned N) { 5784 ASTContext &C = CGM.getContext(); 5785 QualType VoidPtrTy = C.VoidPtrTy; 5786 VoidPtrTy.addRestrict(); 5787 FunctionArgList Args; 5788 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5789 ImplicitParamDecl::Other); 5790 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5791 ImplicitParamDecl::Other); 5792 Args.emplace_back(&Param); 5793 Args.emplace_back(&ParamOrig); 5794 const auto &FnInfo = 5795 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5796 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5797 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 5798 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5799 Name, &CGM.getModule()); 5800 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5801 Fn->setDoesNotRecurse(); 5802 CodeGenFunction CGF(CGM); 5803 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5804 Address PrivateAddr = CGF.EmitLoadOfPointer( 5805 CGF.GetAddrOfLocalVar(&Param), 5806 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5807 llvm::Value *Size = nullptr; 5808 // If the size of the reduction item is non-constant, load it from global 5809 // threadprivate variable. 5810 if (RCG.getSizes(N).second) { 5811 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5812 CGF, CGM.getContext().getSizeType(), 5813 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5814 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5815 CGM.getContext().getSizeType(), Loc); 5816 } 5817 RCG.emitAggregateType(CGF, N, Size); 5818 LValue OrigLVal; 5819 // If initializer uses initializer from declare reduction construct, emit a 5820 // pointer to the address of the original reduction item (reuired by reduction 5821 // initializer) 5822 if (RCG.usesReductionInitializer(N)) { 5823 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig); 5824 SharedAddr = CGF.EmitLoadOfPointer( 5825 SharedAddr, 5826 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 5827 OrigLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 5828 } else { 5829 OrigLVal = CGF.MakeNaturalAlignAddrLValue( 5830 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 5831 CGM.getContext().VoidPtrTy); 5832 } 5833 // Emit the initializer: 5834 // %0 = bitcast void* %arg to <type>* 5835 // store <type> <init>, <type>* %0 5836 RCG.emitInitialization(CGF, N, PrivateAddr, OrigLVal, 5837 [](CodeGenFunction &) { return false; }); 5838 CGF.FinishFunction(); 5839 return Fn; 5840 } 5841 5842 /// Emits reduction combiner function: 5843 /// \code 5844 /// void @.red_comb(void* %arg0, void* %arg1) { 5845 /// %lhs = bitcast void* %arg0 to <type>* 5846 /// %rhs = bitcast void* %arg1 to <type>* 5847 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 5848 /// store <type> %2, <type>* %lhs 5849 /// ret void 5850 /// } 5851 /// \endcode 5852 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 5853 SourceLocation Loc, 5854 ReductionCodeGen &RCG, unsigned N, 5855 const Expr *ReductionOp, 5856 const Expr *LHS, const Expr *RHS, 5857 const Expr *PrivateRef) { 5858 ASTContext &C = CGM.getContext(); 5859 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 5860 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 5861 FunctionArgList Args; 5862 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 5863 C.VoidPtrTy, ImplicitParamDecl::Other); 5864 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5865 ImplicitParamDecl::Other); 5866 Args.emplace_back(&ParamInOut); 5867 Args.emplace_back(&ParamIn); 5868 const auto &FnInfo = 5869 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5870 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5871 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 5872 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5873 Name, &CGM.getModule()); 5874 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5875 Fn->setDoesNotRecurse(); 5876 CodeGenFunction CGF(CGM); 5877 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5878 llvm::Value *Size = nullptr; 5879 // If the size of the reduction item is non-constant, load it from global 5880 // threadprivate variable. 5881 if (RCG.getSizes(N).second) { 5882 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5883 CGF, CGM.getContext().getSizeType(), 5884 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5885 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5886 CGM.getContext().getSizeType(), Loc); 5887 } 5888 RCG.emitAggregateType(CGF, N, Size); 5889 // Remap lhs and rhs variables to the addresses of the function arguments. 5890 // %lhs = bitcast void* %arg0 to <type>* 5891 // %rhs = bitcast void* %arg1 to <type>* 5892 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5893 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 5894 // Pull out the pointer to the variable. 5895 Address PtrAddr = CGF.EmitLoadOfPointer( 5896 CGF.GetAddrOfLocalVar(&ParamInOut), 5897 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5898 return CGF.Builder.CreateElementBitCast( 5899 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 5900 }); 5901 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 5902 // Pull out the pointer to the variable. 5903 Address PtrAddr = CGF.EmitLoadOfPointer( 5904 CGF.GetAddrOfLocalVar(&ParamIn), 5905 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5906 return CGF.Builder.CreateElementBitCast( 5907 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 5908 }); 5909 PrivateScope.Privatize(); 5910 // Emit the combiner body: 5911 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 5912 // store <type> %2, <type>* %lhs 5913 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 5914 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 5915 cast<DeclRefExpr>(RHS)); 5916 CGF.FinishFunction(); 5917 return Fn; 5918 } 5919 5920 /// Emits reduction finalizer function: 5921 /// \code 5922 /// void @.red_fini(void* %arg) { 5923 /// %0 = bitcast void* %arg to <type>* 5924 /// <destroy>(<type>* %0) 5925 /// ret void 5926 /// } 5927 /// \endcode 5928 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 5929 SourceLocation Loc, 5930 ReductionCodeGen &RCG, unsigned N) { 5931 if (!RCG.needCleanups(N)) 5932 return nullptr; 5933 ASTContext &C = CGM.getContext(); 5934 FunctionArgList Args; 5935 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5936 ImplicitParamDecl::Other); 5937 Args.emplace_back(&Param); 5938 const auto &FnInfo = 5939 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5940 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5941 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 5942 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5943 Name, &CGM.getModule()); 5944 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5945 Fn->setDoesNotRecurse(); 5946 CodeGenFunction CGF(CGM); 5947 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5948 Address PrivateAddr = CGF.EmitLoadOfPointer( 5949 CGF.GetAddrOfLocalVar(&Param), 5950 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5951 llvm::Value *Size = nullptr; 5952 // If the size of the reduction item is non-constant, load it from global 5953 // threadprivate variable. 5954 if (RCG.getSizes(N).second) { 5955 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5956 CGF, CGM.getContext().getSizeType(), 5957 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5958 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5959 CGM.getContext().getSizeType(), Loc); 5960 } 5961 RCG.emitAggregateType(CGF, N, Size); 5962 // Emit the finalizer body: 5963 // <destroy>(<type>* %0) 5964 RCG.emitCleanups(CGF, N, PrivateAddr); 5965 CGF.FinishFunction(Loc); 5966 return Fn; 5967 } 5968 5969 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 5970 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 5971 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 5972 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 5973 return nullptr; 5974 5975 // Build typedef struct: 5976 // kmp_taskred_input { 5977 // void *reduce_shar; // shared reduction item 5978 // void *reduce_orig; // original reduction item used for initialization 5979 // size_t reduce_size; // size of data item 5980 // void *reduce_init; // data initialization routine 5981 // void *reduce_fini; // data finalization routine 5982 // void *reduce_comb; // data combiner routine 5983 // kmp_task_red_flags_t flags; // flags for additional info from compiler 5984 // } kmp_taskred_input_t; 5985 ASTContext &C = CGM.getContext(); 5986 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t"); 5987 RD->startDefinition(); 5988 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 5989 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 5990 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 5991 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 5992 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 5993 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 5994 const FieldDecl *FlagsFD = addFieldToRecordDecl( 5995 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 5996 RD->completeDefinition(); 5997 QualType RDType = C.getRecordType(RD); 5998 unsigned Size = Data.ReductionVars.size(); 5999 llvm::APInt ArraySize(/*numBits=*/64, Size); 6000 QualType ArrayRDType = C.getConstantArrayType( 6001 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6002 // kmp_task_red_input_t .rd_input.[Size]; 6003 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6004 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, 6005 Data.ReductionCopies, Data.ReductionOps); 6006 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6007 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6008 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6009 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6010 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6011 TaskRedInput.getPointer(), Idxs, 6012 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6013 ".rd_input.gep."); 6014 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6015 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6016 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6017 RCG.emitSharedOrigLValue(CGF, Cnt); 6018 llvm::Value *CastedShared = 6019 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6020 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6021 // ElemLVal.reduce_orig = &Origs[Cnt]; 6022 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD); 6023 llvm::Value *CastedOrig = 6024 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF)); 6025 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal); 6026 RCG.emitAggregateType(CGF, Cnt); 6027 llvm::Value *SizeValInChars; 6028 llvm::Value *SizeVal; 6029 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6030 // We use delayed creation/initialization for VLAs and array sections. It is 6031 // required because runtime does not provide the way to pass the sizes of 6032 // VLAs/array sections to initializer/combiner/finalizer functions. Instead 6033 // threadprivate global variables are used to store these values and use 6034 // them in the functions. 6035 bool DelayedCreation = !!SizeVal; 6036 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6037 /*isSigned=*/false); 6038 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6039 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6040 // ElemLVal.reduce_init = init; 6041 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6042 llvm::Value *InitAddr = 6043 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6044 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6045 // ElemLVal.reduce_fini = fini; 6046 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6047 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6048 llvm::Value *FiniAddr = Fini 6049 ? CGF.EmitCastToVoidPtr(Fini) 6050 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6051 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6052 // ElemLVal.reduce_comb = comb; 6053 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6054 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6055 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6056 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6057 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6058 // ElemLVal.flags = 0; 6059 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6060 if (DelayedCreation) { 6061 CGF.EmitStoreOfScalar( 6062 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6063 FlagsLVal); 6064 } else 6065 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6066 FlagsLVal.getType()); 6067 } 6068 if (Data.IsReductionWithTaskMod) { 6069 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6070 // is_ws, int num, void *data); 6071 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6072 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6073 CGM.IntTy, /*isSigned=*/true); 6074 llvm::Value *Args[] = { 6075 IdentTLoc, GTid, 6076 llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0, 6077 /*isSigned=*/true), 6078 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6079 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6080 TaskRedInput.getPointer(), CGM.VoidPtrTy)}; 6081 return CGF.EmitRuntimeCall( 6082 OMPBuilder.getOrCreateRuntimeFunction( 6083 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init), 6084 Args); 6085 } 6086 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data); 6087 llvm::Value *Args[] = { 6088 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6089 /*isSigned=*/true), 6090 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6091 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6092 CGM.VoidPtrTy)}; 6093 return CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6094 CGM.getModule(), OMPRTL___kmpc_taskred_init), 6095 Args); 6096 } 6097 6098 void CGOpenMPRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 6099 SourceLocation Loc, 6100 bool IsWorksharingReduction) { 6101 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6102 // is_ws, int num, void *data); 6103 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6104 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6105 CGM.IntTy, /*isSigned=*/true); 6106 llvm::Value *Args[] = {IdentTLoc, GTid, 6107 llvm::ConstantInt::get(CGM.IntTy, 6108 IsWorksharingReduction ? 1 : 0, 6109 /*isSigned=*/true)}; 6110 (void)CGF.EmitRuntimeCall( 6111 OMPBuilder.getOrCreateRuntimeFunction( 6112 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini), 6113 Args); 6114 } 6115 6116 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6117 SourceLocation Loc, 6118 ReductionCodeGen &RCG, 6119 unsigned N) { 6120 auto Sizes = RCG.getSizes(N); 6121 // Emit threadprivate global variable if the type is non-constant 6122 // (Sizes.second = nullptr). 6123 if (Sizes.second) { 6124 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6125 /*isSigned=*/false); 6126 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6127 CGF, CGM.getContext().getSizeType(), 6128 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6129 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6130 } 6131 } 6132 6133 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6134 SourceLocation Loc, 6135 llvm::Value *ReductionsPtr, 6136 LValue SharedLVal) { 6137 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6138 // *d); 6139 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6140 CGM.IntTy, 6141 /*isSigned=*/true), 6142 ReductionsPtr, 6143 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6144 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6145 return Address( 6146 CGF.EmitRuntimeCall( 6147 OMPBuilder.getOrCreateRuntimeFunction( 6148 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data), 6149 Args), 6150 SharedLVal.getAlignment()); 6151 } 6152 6153 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6154 SourceLocation Loc) { 6155 if (!CGF.HaveInsertPoint()) 6156 return; 6157 6158 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 6159 OMPBuilder.CreateTaskwait(CGF.Builder); 6160 } else { 6161 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6162 // global_tid); 6163 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6164 // Ignore return result until untied tasks are supported. 6165 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6166 CGM.getModule(), OMPRTL___kmpc_omp_taskwait), 6167 Args); 6168 } 6169 6170 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6171 Region->emitUntiedSwitch(CGF); 6172 } 6173 6174 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6175 OpenMPDirectiveKind InnerKind, 6176 const RegionCodeGenTy &CodeGen, 6177 bool HasCancel) { 6178 if (!CGF.HaveInsertPoint()) 6179 return; 6180 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6181 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6182 } 6183 6184 namespace { 6185 enum RTCancelKind { 6186 CancelNoreq = 0, 6187 CancelParallel = 1, 6188 CancelLoop = 2, 6189 CancelSections = 3, 6190 CancelTaskgroup = 4 6191 }; 6192 } // anonymous namespace 6193 6194 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6195 RTCancelKind CancelKind = CancelNoreq; 6196 if (CancelRegion == OMPD_parallel) 6197 CancelKind = CancelParallel; 6198 else if (CancelRegion == OMPD_for) 6199 CancelKind = CancelLoop; 6200 else if (CancelRegion == OMPD_sections) 6201 CancelKind = CancelSections; 6202 else { 6203 assert(CancelRegion == OMPD_taskgroup); 6204 CancelKind = CancelTaskgroup; 6205 } 6206 return CancelKind; 6207 } 6208 6209 void CGOpenMPRuntime::emitCancellationPointCall( 6210 CodeGenFunction &CGF, SourceLocation Loc, 6211 OpenMPDirectiveKind CancelRegion) { 6212 if (!CGF.HaveInsertPoint()) 6213 return; 6214 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6215 // global_tid, kmp_int32 cncl_kind); 6216 if (auto *OMPRegionInfo = 6217 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6218 // For 'cancellation point taskgroup', the task region info may not have a 6219 // cancel. This may instead happen in another adjacent task. 6220 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6221 llvm::Value *Args[] = { 6222 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6223 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6224 // Ignore return result until untied tasks are supported. 6225 llvm::Value *Result = CGF.EmitRuntimeCall( 6226 OMPBuilder.getOrCreateRuntimeFunction( 6227 CGM.getModule(), OMPRTL___kmpc_cancellationpoint), 6228 Args); 6229 // if (__kmpc_cancellationpoint()) { 6230 // exit from construct; 6231 // } 6232 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6233 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6234 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6235 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6236 CGF.EmitBlock(ExitBB); 6237 // exit from construct; 6238 CodeGenFunction::JumpDest CancelDest = 6239 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6240 CGF.EmitBranchThroughCleanup(CancelDest); 6241 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6242 } 6243 } 6244 } 6245 6246 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6247 const Expr *IfCond, 6248 OpenMPDirectiveKind CancelRegion) { 6249 if (!CGF.HaveInsertPoint()) 6250 return; 6251 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6252 // kmp_int32 cncl_kind); 6253 auto &M = CGM.getModule(); 6254 if (auto *OMPRegionInfo = 6255 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6256 auto &&ThenGen = [this, &M, Loc, CancelRegion, 6257 OMPRegionInfo](CodeGenFunction &CGF, PrePostActionTy &) { 6258 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6259 llvm::Value *Args[] = { 6260 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6261 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6262 // Ignore return result until untied tasks are supported. 6263 llvm::Value *Result = CGF.EmitRuntimeCall( 6264 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args); 6265 // if (__kmpc_cancel()) { 6266 // exit from construct; 6267 // } 6268 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6269 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6270 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6271 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6272 CGF.EmitBlock(ExitBB); 6273 // exit from construct; 6274 CodeGenFunction::JumpDest CancelDest = 6275 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6276 CGF.EmitBranchThroughCleanup(CancelDest); 6277 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6278 }; 6279 if (IfCond) { 6280 emitIfClause(CGF, IfCond, ThenGen, 6281 [](CodeGenFunction &, PrePostActionTy &) {}); 6282 } else { 6283 RegionCodeGenTy ThenRCG(ThenGen); 6284 ThenRCG(CGF); 6285 } 6286 } 6287 } 6288 6289 namespace { 6290 /// Cleanup action for uses_allocators support. 6291 class OMPUsesAllocatorsActionTy final : public PrePostActionTy { 6292 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators; 6293 6294 public: 6295 OMPUsesAllocatorsActionTy( 6296 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators) 6297 : Allocators(Allocators) {} 6298 void Enter(CodeGenFunction &CGF) override { 6299 if (!CGF.HaveInsertPoint()) 6300 return; 6301 for (const auto &AllocatorData : Allocators) { 6302 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsInit( 6303 CGF, AllocatorData.first, AllocatorData.second); 6304 } 6305 } 6306 void Exit(CodeGenFunction &CGF) override { 6307 if (!CGF.HaveInsertPoint()) 6308 return; 6309 for (const auto &AllocatorData : Allocators) { 6310 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsFini(CGF, 6311 AllocatorData.first); 6312 } 6313 } 6314 }; 6315 } // namespace 6316 6317 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6318 const OMPExecutableDirective &D, StringRef ParentName, 6319 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6320 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6321 assert(!ParentName.empty() && "Invalid target region parent name!"); 6322 HasEmittedTargetRegion = true; 6323 SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators; 6324 for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) { 6325 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 6326 const OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 6327 if (!D.AllocatorTraits) 6328 continue; 6329 Allocators.emplace_back(D.Allocator, D.AllocatorTraits); 6330 } 6331 } 6332 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators); 6333 CodeGen.setAction(UsesAllocatorAction); 6334 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6335 IsOffloadEntry, CodeGen); 6336 } 6337 6338 void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, 6339 const Expr *Allocator, 6340 const Expr *AllocatorTraits) { 6341 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6342 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6343 // Use default memspace handle. 6344 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 6345 llvm::Value *NumTraits = llvm::ConstantInt::get( 6346 CGF.IntTy, cast<ConstantArrayType>( 6347 AllocatorTraits->getType()->getAsArrayTypeUnsafe()) 6348 ->getSize() 6349 .getLimitedValue()); 6350 LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits); 6351 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6352 AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy); 6353 AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, 6354 AllocatorTraitsLVal.getBaseInfo(), 6355 AllocatorTraitsLVal.getTBAAInfo()); 6356 llvm::Value *Traits = 6357 CGF.EmitLoadOfScalar(AllocatorTraitsLVal, AllocatorTraits->getExprLoc()); 6358 6359 llvm::Value *AllocatorVal = 6360 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6361 CGM.getModule(), OMPRTL___kmpc_init_allocator), 6362 {ThreadId, MemSpaceHandle, NumTraits, Traits}); 6363 // Store to allocator. 6364 CGF.EmitVarDecl(*cast<VarDecl>( 6365 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl())); 6366 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6367 AllocatorVal = 6368 CGF.EmitScalarConversion(AllocatorVal, CGF.getContext().VoidPtrTy, 6369 Allocator->getType(), Allocator->getExprLoc()); 6370 CGF.EmitStoreOfScalar(AllocatorVal, AllocatorLVal); 6371 } 6372 6373 void CGOpenMPRuntime::emitUsesAllocatorsFini(CodeGenFunction &CGF, 6374 const Expr *Allocator) { 6375 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6376 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6377 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6378 llvm::Value *AllocatorVal = 6379 CGF.EmitLoadOfScalar(AllocatorLVal, Allocator->getExprLoc()); 6380 AllocatorVal = CGF.EmitScalarConversion(AllocatorVal, Allocator->getType(), 6381 CGF.getContext().VoidPtrTy, 6382 Allocator->getExprLoc()); 6383 (void)CGF.EmitRuntimeCall( 6384 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 6385 OMPRTL___kmpc_destroy_allocator), 6386 {ThreadId, AllocatorVal}); 6387 } 6388 6389 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6390 const OMPExecutableDirective &D, StringRef ParentName, 6391 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6392 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6393 // Create a unique name for the entry function using the source location 6394 // information of the current target region. The name will be something like: 6395 // 6396 // __omp_offloading_DD_FFFF_PP_lBB 6397 // 6398 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6399 // mangled name of the function that encloses the target region and BB is the 6400 // line number of the target region. 6401 6402 unsigned DeviceID; 6403 unsigned FileID; 6404 unsigned Line; 6405 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6406 Line); 6407 SmallString<64> EntryFnName; 6408 { 6409 llvm::raw_svector_ostream OS(EntryFnName); 6410 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6411 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6412 } 6413 6414 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6415 6416 CodeGenFunction CGF(CGM, true); 6417 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6418 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6419 6420 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6421 6422 // If this target outline function is not an offload entry, we don't need to 6423 // register it. 6424 if (!IsOffloadEntry) 6425 return; 6426 6427 // The target region ID is used by the runtime library to identify the current 6428 // target region, so it only has to be unique and not necessarily point to 6429 // anything. It could be the pointer to the outlined function that implements 6430 // the target region, but we aren't using that so that the compiler doesn't 6431 // need to keep that, and could therefore inline the host function if proven 6432 // worthwhile during optimization. In the other hand, if emitting code for the 6433 // device, the ID has to be the function address so that it can retrieved from 6434 // the offloading entry and launched by the runtime library. We also mark the 6435 // outlined function to have external linkage in case we are emitting code for 6436 // the device, because these functions will be entry points to the device. 6437 6438 if (CGM.getLangOpts().OpenMPIsDevice) { 6439 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6440 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6441 OutlinedFn->setDSOLocal(false); 6442 } else { 6443 std::string Name = getName({EntryFnName, "region_id"}); 6444 OutlinedFnID = new llvm::GlobalVariable( 6445 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6446 llvm::GlobalValue::WeakAnyLinkage, 6447 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6448 } 6449 6450 // Register the information for the entry associated with this target region. 6451 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6452 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6453 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6454 } 6455 6456 /// Checks if the expression is constant or does not have non-trivial function 6457 /// calls. 6458 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6459 // We can skip constant expressions. 6460 // We can skip expressions with trivial calls or simple expressions. 6461 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6462 !E->hasNonTrivialCall(Ctx)) && 6463 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6464 } 6465 6466 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6467 const Stmt *Body) { 6468 const Stmt *Child = Body->IgnoreContainers(); 6469 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6470 Child = nullptr; 6471 for (const Stmt *S : C->body()) { 6472 if (const auto *E = dyn_cast<Expr>(S)) { 6473 if (isTrivial(Ctx, E)) 6474 continue; 6475 } 6476 // Some of the statements can be ignored. 6477 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6478 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6479 continue; 6480 // Analyze declarations. 6481 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6482 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6483 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6484 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6485 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6486 isa<UsingDirectiveDecl>(D) || 6487 isa<OMPDeclareReductionDecl>(D) || 6488 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6489 return true; 6490 const auto *VD = dyn_cast<VarDecl>(D); 6491 if (!VD) 6492 return false; 6493 return VD->isConstexpr() || 6494 ((VD->getType().isTrivialType(Ctx) || 6495 VD->getType()->isReferenceType()) && 6496 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6497 })) 6498 continue; 6499 } 6500 // Found multiple children - cannot get the one child only. 6501 if (Child) 6502 return nullptr; 6503 Child = S; 6504 } 6505 if (Child) 6506 Child = Child->IgnoreContainers(); 6507 } 6508 return Child; 6509 } 6510 6511 /// Emit the number of teams for a target directive. Inspect the num_teams 6512 /// clause associated with a teams construct combined or closely nested 6513 /// with the target directive. 6514 /// 6515 /// Emit a team of size one for directives such as 'target parallel' that 6516 /// have no associated teams construct. 6517 /// 6518 /// Otherwise, return nullptr. 6519 static llvm::Value * 6520 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6521 const OMPExecutableDirective &D) { 6522 assert(!CGF.getLangOpts().OpenMPIsDevice && 6523 "Clauses associated with the teams directive expected to be emitted " 6524 "only for the host!"); 6525 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6526 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6527 "Expected target-based executable directive."); 6528 CGBuilderTy &Bld = CGF.Builder; 6529 switch (DirectiveKind) { 6530 case OMPD_target: { 6531 const auto *CS = D.getInnermostCapturedStmt(); 6532 const auto *Body = 6533 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6534 const Stmt *ChildStmt = 6535 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6536 if (const auto *NestedDir = 6537 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6538 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6539 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6540 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6541 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6542 const Expr *NumTeams = 6543 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6544 llvm::Value *NumTeamsVal = 6545 CGF.EmitScalarExpr(NumTeams, 6546 /*IgnoreResultAssign*/ true); 6547 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6548 /*isSigned=*/true); 6549 } 6550 return Bld.getInt32(0); 6551 } 6552 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6553 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6554 return Bld.getInt32(1); 6555 return Bld.getInt32(0); 6556 } 6557 return nullptr; 6558 } 6559 case OMPD_target_teams: 6560 case OMPD_target_teams_distribute: 6561 case OMPD_target_teams_distribute_simd: 6562 case OMPD_target_teams_distribute_parallel_for: 6563 case OMPD_target_teams_distribute_parallel_for_simd: { 6564 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6565 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6566 const Expr *NumTeams = 6567 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6568 llvm::Value *NumTeamsVal = 6569 CGF.EmitScalarExpr(NumTeams, 6570 /*IgnoreResultAssign*/ true); 6571 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6572 /*isSigned=*/true); 6573 } 6574 return Bld.getInt32(0); 6575 } 6576 case OMPD_target_parallel: 6577 case OMPD_target_parallel_for: 6578 case OMPD_target_parallel_for_simd: 6579 case OMPD_target_simd: 6580 return Bld.getInt32(1); 6581 case OMPD_parallel: 6582 case OMPD_for: 6583 case OMPD_parallel_for: 6584 case OMPD_parallel_master: 6585 case OMPD_parallel_sections: 6586 case OMPD_for_simd: 6587 case OMPD_parallel_for_simd: 6588 case OMPD_cancel: 6589 case OMPD_cancellation_point: 6590 case OMPD_ordered: 6591 case OMPD_threadprivate: 6592 case OMPD_allocate: 6593 case OMPD_task: 6594 case OMPD_simd: 6595 case OMPD_sections: 6596 case OMPD_section: 6597 case OMPD_single: 6598 case OMPD_master: 6599 case OMPD_critical: 6600 case OMPD_taskyield: 6601 case OMPD_barrier: 6602 case OMPD_taskwait: 6603 case OMPD_taskgroup: 6604 case OMPD_atomic: 6605 case OMPD_flush: 6606 case OMPD_depobj: 6607 case OMPD_scan: 6608 case OMPD_teams: 6609 case OMPD_target_data: 6610 case OMPD_target_exit_data: 6611 case OMPD_target_enter_data: 6612 case OMPD_distribute: 6613 case OMPD_distribute_simd: 6614 case OMPD_distribute_parallel_for: 6615 case OMPD_distribute_parallel_for_simd: 6616 case OMPD_teams_distribute: 6617 case OMPD_teams_distribute_simd: 6618 case OMPD_teams_distribute_parallel_for: 6619 case OMPD_teams_distribute_parallel_for_simd: 6620 case OMPD_target_update: 6621 case OMPD_declare_simd: 6622 case OMPD_declare_variant: 6623 case OMPD_begin_declare_variant: 6624 case OMPD_end_declare_variant: 6625 case OMPD_declare_target: 6626 case OMPD_end_declare_target: 6627 case OMPD_declare_reduction: 6628 case OMPD_declare_mapper: 6629 case OMPD_taskloop: 6630 case OMPD_taskloop_simd: 6631 case OMPD_master_taskloop: 6632 case OMPD_master_taskloop_simd: 6633 case OMPD_parallel_master_taskloop: 6634 case OMPD_parallel_master_taskloop_simd: 6635 case OMPD_requires: 6636 case OMPD_unknown: 6637 break; 6638 default: 6639 break; 6640 } 6641 llvm_unreachable("Unexpected directive kind."); 6642 } 6643 6644 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6645 llvm::Value *DefaultThreadLimitVal) { 6646 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6647 CGF.getContext(), CS->getCapturedStmt()); 6648 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6649 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6650 llvm::Value *NumThreads = nullptr; 6651 llvm::Value *CondVal = nullptr; 6652 // Handle if clause. If if clause present, the number of threads is 6653 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6654 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6655 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6656 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6657 const OMPIfClause *IfClause = nullptr; 6658 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6659 if (C->getNameModifier() == OMPD_unknown || 6660 C->getNameModifier() == OMPD_parallel) { 6661 IfClause = C; 6662 break; 6663 } 6664 } 6665 if (IfClause) { 6666 const Expr *Cond = IfClause->getCondition(); 6667 bool Result; 6668 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6669 if (!Result) 6670 return CGF.Builder.getInt32(1); 6671 } else { 6672 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6673 if (const auto *PreInit = 6674 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6675 for (const auto *I : PreInit->decls()) { 6676 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6677 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6678 } else { 6679 CodeGenFunction::AutoVarEmission Emission = 6680 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6681 CGF.EmitAutoVarCleanups(Emission); 6682 } 6683 } 6684 } 6685 CondVal = CGF.EvaluateExprAsBool(Cond); 6686 } 6687 } 6688 } 6689 // Check the value of num_threads clause iff if clause was not specified 6690 // or is not evaluated to false. 6691 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6692 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6693 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6694 const auto *NumThreadsClause = 6695 Dir->getSingleClause<OMPNumThreadsClause>(); 6696 CodeGenFunction::LexicalScope Scope( 6697 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6698 if (const auto *PreInit = 6699 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6700 for (const auto *I : PreInit->decls()) { 6701 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6702 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6703 } else { 6704 CodeGenFunction::AutoVarEmission Emission = 6705 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6706 CGF.EmitAutoVarCleanups(Emission); 6707 } 6708 } 6709 } 6710 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6711 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6712 /*isSigned=*/false); 6713 if (DefaultThreadLimitVal) 6714 NumThreads = CGF.Builder.CreateSelect( 6715 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6716 DefaultThreadLimitVal, NumThreads); 6717 } else { 6718 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6719 : CGF.Builder.getInt32(0); 6720 } 6721 // Process condition of the if clause. 6722 if (CondVal) { 6723 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6724 CGF.Builder.getInt32(1)); 6725 } 6726 return NumThreads; 6727 } 6728 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6729 return CGF.Builder.getInt32(1); 6730 return DefaultThreadLimitVal; 6731 } 6732 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6733 : CGF.Builder.getInt32(0); 6734 } 6735 6736 /// Emit the number of threads for a target directive. Inspect the 6737 /// thread_limit clause associated with a teams construct combined or closely 6738 /// nested with the target directive. 6739 /// 6740 /// Emit the num_threads clause for directives such as 'target parallel' that 6741 /// have no associated teams construct. 6742 /// 6743 /// Otherwise, return nullptr. 6744 static llvm::Value * 6745 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6746 const OMPExecutableDirective &D) { 6747 assert(!CGF.getLangOpts().OpenMPIsDevice && 6748 "Clauses associated with the teams directive expected to be emitted " 6749 "only for the host!"); 6750 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6751 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6752 "Expected target-based executable directive."); 6753 CGBuilderTy &Bld = CGF.Builder; 6754 llvm::Value *ThreadLimitVal = nullptr; 6755 llvm::Value *NumThreadsVal = nullptr; 6756 switch (DirectiveKind) { 6757 case OMPD_target: { 6758 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6759 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6760 return NumThreads; 6761 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6762 CGF.getContext(), CS->getCapturedStmt()); 6763 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6764 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6765 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6766 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6767 const auto *ThreadLimitClause = 6768 Dir->getSingleClause<OMPThreadLimitClause>(); 6769 CodeGenFunction::LexicalScope Scope( 6770 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6771 if (const auto *PreInit = 6772 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6773 for (const auto *I : PreInit->decls()) { 6774 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6775 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6776 } else { 6777 CodeGenFunction::AutoVarEmission Emission = 6778 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6779 CGF.EmitAutoVarCleanups(Emission); 6780 } 6781 } 6782 } 6783 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6784 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6785 ThreadLimitVal = 6786 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6787 } 6788 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6789 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6790 CS = Dir->getInnermostCapturedStmt(); 6791 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6792 CGF.getContext(), CS->getCapturedStmt()); 6793 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6794 } 6795 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6796 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6797 CS = Dir->getInnermostCapturedStmt(); 6798 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6799 return NumThreads; 6800 } 6801 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6802 return Bld.getInt32(1); 6803 } 6804 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6805 } 6806 case OMPD_target_teams: { 6807 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6808 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6809 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6810 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6811 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6812 ThreadLimitVal = 6813 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6814 } 6815 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6816 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6817 return NumThreads; 6818 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6819 CGF.getContext(), CS->getCapturedStmt()); 6820 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6821 if (Dir->getDirectiveKind() == OMPD_distribute) { 6822 CS = Dir->getInnermostCapturedStmt(); 6823 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6824 return NumThreads; 6825 } 6826 } 6827 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6828 } 6829 case OMPD_target_teams_distribute: 6830 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6831 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6832 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6833 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6834 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6835 ThreadLimitVal = 6836 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6837 } 6838 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6839 case OMPD_target_parallel: 6840 case OMPD_target_parallel_for: 6841 case OMPD_target_parallel_for_simd: 6842 case OMPD_target_teams_distribute_parallel_for: 6843 case OMPD_target_teams_distribute_parallel_for_simd: { 6844 llvm::Value *CondVal = nullptr; 6845 // Handle if clause. If if clause present, the number of threads is 6846 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6847 if (D.hasClausesOfKind<OMPIfClause>()) { 6848 const OMPIfClause *IfClause = nullptr; 6849 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6850 if (C->getNameModifier() == OMPD_unknown || 6851 C->getNameModifier() == OMPD_parallel) { 6852 IfClause = C; 6853 break; 6854 } 6855 } 6856 if (IfClause) { 6857 const Expr *Cond = IfClause->getCondition(); 6858 bool Result; 6859 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6860 if (!Result) 6861 return Bld.getInt32(1); 6862 } else { 6863 CodeGenFunction::RunCleanupsScope Scope(CGF); 6864 CondVal = CGF.EvaluateExprAsBool(Cond); 6865 } 6866 } 6867 } 6868 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6869 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6870 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6871 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6872 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6873 ThreadLimitVal = 6874 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6875 } 6876 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6877 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6878 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6879 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6880 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6881 NumThreadsVal = 6882 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6883 ThreadLimitVal = ThreadLimitVal 6884 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6885 ThreadLimitVal), 6886 NumThreadsVal, ThreadLimitVal) 6887 : NumThreadsVal; 6888 } 6889 if (!ThreadLimitVal) 6890 ThreadLimitVal = Bld.getInt32(0); 6891 if (CondVal) 6892 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6893 return ThreadLimitVal; 6894 } 6895 case OMPD_target_teams_distribute_simd: 6896 case OMPD_target_simd: 6897 return Bld.getInt32(1); 6898 case OMPD_parallel: 6899 case OMPD_for: 6900 case OMPD_parallel_for: 6901 case OMPD_parallel_master: 6902 case OMPD_parallel_sections: 6903 case OMPD_for_simd: 6904 case OMPD_parallel_for_simd: 6905 case OMPD_cancel: 6906 case OMPD_cancellation_point: 6907 case OMPD_ordered: 6908 case OMPD_threadprivate: 6909 case OMPD_allocate: 6910 case OMPD_task: 6911 case OMPD_simd: 6912 case OMPD_sections: 6913 case OMPD_section: 6914 case OMPD_single: 6915 case OMPD_master: 6916 case OMPD_critical: 6917 case OMPD_taskyield: 6918 case OMPD_barrier: 6919 case OMPD_taskwait: 6920 case OMPD_taskgroup: 6921 case OMPD_atomic: 6922 case OMPD_flush: 6923 case OMPD_depobj: 6924 case OMPD_scan: 6925 case OMPD_teams: 6926 case OMPD_target_data: 6927 case OMPD_target_exit_data: 6928 case OMPD_target_enter_data: 6929 case OMPD_distribute: 6930 case OMPD_distribute_simd: 6931 case OMPD_distribute_parallel_for: 6932 case OMPD_distribute_parallel_for_simd: 6933 case OMPD_teams_distribute: 6934 case OMPD_teams_distribute_simd: 6935 case OMPD_teams_distribute_parallel_for: 6936 case OMPD_teams_distribute_parallel_for_simd: 6937 case OMPD_target_update: 6938 case OMPD_declare_simd: 6939 case OMPD_declare_variant: 6940 case OMPD_begin_declare_variant: 6941 case OMPD_end_declare_variant: 6942 case OMPD_declare_target: 6943 case OMPD_end_declare_target: 6944 case OMPD_declare_reduction: 6945 case OMPD_declare_mapper: 6946 case OMPD_taskloop: 6947 case OMPD_taskloop_simd: 6948 case OMPD_master_taskloop: 6949 case OMPD_master_taskloop_simd: 6950 case OMPD_parallel_master_taskloop: 6951 case OMPD_parallel_master_taskloop_simd: 6952 case OMPD_requires: 6953 case OMPD_unknown: 6954 break; 6955 default: 6956 break; 6957 } 6958 llvm_unreachable("Unsupported directive kind."); 6959 } 6960 6961 namespace { 6962 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 6963 6964 // Utility to handle information from clauses associated with a given 6965 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 6966 // It provides a convenient interface to obtain the information and generate 6967 // code for that information. 6968 class MappableExprsHandler { 6969 public: 6970 /// Values for bit flags used to specify the mapping type for 6971 /// offloading. 6972 enum OpenMPOffloadMappingFlags : uint64_t { 6973 /// No flags 6974 OMP_MAP_NONE = 0x0, 6975 /// Allocate memory on the device and move data from host to device. 6976 OMP_MAP_TO = 0x01, 6977 /// Allocate memory on the device and move data from device to host. 6978 OMP_MAP_FROM = 0x02, 6979 /// Always perform the requested mapping action on the element, even 6980 /// if it was already mapped before. 6981 OMP_MAP_ALWAYS = 0x04, 6982 /// Delete the element from the device environment, ignoring the 6983 /// current reference count associated with the element. 6984 OMP_MAP_DELETE = 0x08, 6985 /// The element being mapped is a pointer-pointee pair; both the 6986 /// pointer and the pointee should be mapped. 6987 OMP_MAP_PTR_AND_OBJ = 0x10, 6988 /// This flags signals that the base address of an entry should be 6989 /// passed to the target kernel as an argument. 6990 OMP_MAP_TARGET_PARAM = 0x20, 6991 /// Signal that the runtime library has to return the device pointer 6992 /// in the current position for the data being mapped. Used when we have the 6993 /// use_device_ptr or use_device_addr clause. 6994 OMP_MAP_RETURN_PARAM = 0x40, 6995 /// This flag signals that the reference being passed is a pointer to 6996 /// private data. 6997 OMP_MAP_PRIVATE = 0x80, 6998 /// Pass the element to the device by value. 6999 OMP_MAP_LITERAL = 0x100, 7000 /// Implicit map 7001 OMP_MAP_IMPLICIT = 0x200, 7002 /// Close is a hint to the runtime to allocate memory close to 7003 /// the target device. 7004 OMP_MAP_CLOSE = 0x400, 7005 /// 0x800 is reserved for compatibility with XLC. 7006 /// Produce a runtime error if the data is not already allocated. 7007 OMP_MAP_PRESENT = 0x1000, 7008 /// The 16 MSBs of the flags indicate whether the entry is member of some 7009 /// struct/class. 7010 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7011 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7012 }; 7013 7014 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7015 static unsigned getFlagMemberOffset() { 7016 unsigned Offset = 0; 7017 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7018 Remain = Remain >> 1) 7019 Offset++; 7020 return Offset; 7021 } 7022 7023 /// Class that associates information with a base pointer to be passed to the 7024 /// runtime library. 7025 class BasePointerInfo { 7026 /// The base pointer. 7027 llvm::Value *Ptr = nullptr; 7028 /// The base declaration that refers to this device pointer, or null if 7029 /// there is none. 7030 const ValueDecl *DevPtrDecl = nullptr; 7031 7032 public: 7033 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7034 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7035 llvm::Value *operator*() const { return Ptr; } 7036 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7037 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7038 }; 7039 7040 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7041 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7042 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7043 using MapMappersArrayTy = SmallVector<const ValueDecl *, 4>; 7044 7045 /// This structure contains combined information generated for mappable 7046 /// clauses, including base pointers, pointers, sizes, map types, and 7047 /// user-defined mappers. 7048 struct MapCombinedInfoTy { 7049 MapBaseValuesArrayTy BasePointers; 7050 MapValuesArrayTy Pointers; 7051 MapValuesArrayTy Sizes; 7052 MapFlagsArrayTy Types; 7053 MapMappersArrayTy Mappers; 7054 7055 /// Append arrays in \a CurInfo. 7056 void append(MapCombinedInfoTy &CurInfo) { 7057 BasePointers.append(CurInfo.BasePointers.begin(), 7058 CurInfo.BasePointers.end()); 7059 Pointers.append(CurInfo.Pointers.begin(), CurInfo.Pointers.end()); 7060 Sizes.append(CurInfo.Sizes.begin(), CurInfo.Sizes.end()); 7061 Types.append(CurInfo.Types.begin(), CurInfo.Types.end()); 7062 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end()); 7063 } 7064 }; 7065 7066 /// Map between a struct and the its lowest & highest elements which have been 7067 /// mapped. 7068 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7069 /// HE(FieldIndex, Pointer)} 7070 struct StructRangeInfoTy { 7071 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7072 0, Address::invalid()}; 7073 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7074 0, Address::invalid()}; 7075 Address Base = Address::invalid(); 7076 }; 7077 7078 private: 7079 /// Kind that defines how a device pointer has to be returned. 7080 struct MapInfo { 7081 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7082 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7083 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7084 ArrayRef<OpenMPMotionModifierKind> MotionModifiers; 7085 bool ReturnDevicePointer = false; 7086 bool IsImplicit = false; 7087 const ValueDecl *Mapper = nullptr; 7088 bool ForDeviceAddr = false; 7089 7090 MapInfo() = default; 7091 MapInfo( 7092 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7093 OpenMPMapClauseKind MapType, 7094 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7095 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7096 bool ReturnDevicePointer, bool IsImplicit, 7097 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false) 7098 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7099 MotionModifiers(MotionModifiers), 7100 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit), 7101 Mapper(Mapper), ForDeviceAddr(ForDeviceAddr) {} 7102 }; 7103 7104 /// If use_device_ptr or use_device_addr is used on a decl which is a struct 7105 /// member and there is no map information about it, then emission of that 7106 /// entry is deferred until the whole struct has been processed. 7107 struct DeferredDevicePtrEntryTy { 7108 const Expr *IE = nullptr; 7109 const ValueDecl *VD = nullptr; 7110 bool ForDeviceAddr = false; 7111 7112 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD, 7113 bool ForDeviceAddr) 7114 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {} 7115 }; 7116 7117 /// The target directive from where the mappable clauses were extracted. It 7118 /// is either a executable directive or a user-defined mapper directive. 7119 llvm::PointerUnion<const OMPExecutableDirective *, 7120 const OMPDeclareMapperDecl *> 7121 CurDir; 7122 7123 /// Function the directive is being generated for. 7124 CodeGenFunction &CGF; 7125 7126 /// Set of all first private variables in the current directive. 7127 /// bool data is set to true if the variable is implicitly marked as 7128 /// firstprivate, false otherwise. 7129 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7130 7131 /// Map between device pointer declarations and their expression components. 7132 /// The key value for declarations in 'this' is null. 7133 llvm::DenseMap< 7134 const ValueDecl *, 7135 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7136 DevPointersMap; 7137 7138 llvm::Value *getExprTypeSize(const Expr *E) const { 7139 QualType ExprTy = E->getType().getCanonicalType(); 7140 7141 // Calculate the size for array shaping expression. 7142 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) { 7143 llvm::Value *Size = 7144 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType()); 7145 for (const Expr *SE : OAE->getDimensions()) { 7146 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 7147 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 7148 CGF.getContext().getSizeType(), 7149 SE->getExprLoc()); 7150 Size = CGF.Builder.CreateNUWMul(Size, Sz); 7151 } 7152 return Size; 7153 } 7154 7155 // Reference types are ignored for mapping purposes. 7156 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7157 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7158 7159 // Given that an array section is considered a built-in type, we need to 7160 // do the calculation based on the length of the section instead of relying 7161 // on CGF.getTypeSize(E->getType()). 7162 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7163 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7164 OAE->getBase()->IgnoreParenImpCasts()) 7165 .getCanonicalType(); 7166 7167 // If there is no length associated with the expression and lower bound is 7168 // not specified too, that means we are using the whole length of the 7169 // base. 7170 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7171 !OAE->getLowerBound()) 7172 return CGF.getTypeSize(BaseTy); 7173 7174 llvm::Value *ElemSize; 7175 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7176 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7177 } else { 7178 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7179 assert(ATy && "Expecting array type if not a pointer type."); 7180 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7181 } 7182 7183 // If we don't have a length at this point, that is because we have an 7184 // array section with a single element. 7185 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid()) 7186 return ElemSize; 7187 7188 if (const Expr *LenExpr = OAE->getLength()) { 7189 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7190 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7191 CGF.getContext().getSizeType(), 7192 LenExpr->getExprLoc()); 7193 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7194 } 7195 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7196 OAE->getLowerBound() && "expected array_section[lb:]."); 7197 // Size = sizetype - lb * elemtype; 7198 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7199 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7200 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7201 CGF.getContext().getSizeType(), 7202 OAE->getLowerBound()->getExprLoc()); 7203 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7204 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7205 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7206 LengthVal = CGF.Builder.CreateSelect( 7207 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7208 return LengthVal; 7209 } 7210 return CGF.getTypeSize(ExprTy); 7211 } 7212 7213 /// Return the corresponding bits for a given map clause modifier. Add 7214 /// a flag marking the map as a pointer if requested. Add a flag marking the 7215 /// map as the first one of a series of maps that relate to the same map 7216 /// expression. 7217 OpenMPOffloadMappingFlags getMapTypeBits( 7218 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7219 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit, 7220 bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7221 OpenMPOffloadMappingFlags Bits = 7222 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7223 switch (MapType) { 7224 case OMPC_MAP_alloc: 7225 case OMPC_MAP_release: 7226 // alloc and release is the default behavior in the runtime library, i.e. 7227 // if we don't pass any bits alloc/release that is what the runtime is 7228 // going to do. Therefore, we don't need to signal anything for these two 7229 // type modifiers. 7230 break; 7231 case OMPC_MAP_to: 7232 Bits |= OMP_MAP_TO; 7233 break; 7234 case OMPC_MAP_from: 7235 Bits |= OMP_MAP_FROM; 7236 break; 7237 case OMPC_MAP_tofrom: 7238 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7239 break; 7240 case OMPC_MAP_delete: 7241 Bits |= OMP_MAP_DELETE; 7242 break; 7243 case OMPC_MAP_unknown: 7244 llvm_unreachable("Unexpected map type!"); 7245 } 7246 if (AddPtrFlag) 7247 Bits |= OMP_MAP_PTR_AND_OBJ; 7248 if (AddIsTargetParamFlag) 7249 Bits |= OMP_MAP_TARGET_PARAM; 7250 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7251 != MapModifiers.end()) 7252 Bits |= OMP_MAP_ALWAYS; 7253 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7254 != MapModifiers.end()) 7255 Bits |= OMP_MAP_CLOSE; 7256 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_present) 7257 != MapModifiers.end()) 7258 Bits |= OMP_MAP_PRESENT; 7259 if (llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present) 7260 != MotionModifiers.end()) 7261 Bits |= OMP_MAP_PRESENT; 7262 return Bits; 7263 } 7264 7265 /// Return true if the provided expression is a final array section. A 7266 /// final array section, is one whose length can't be proved to be one. 7267 bool isFinalArraySectionExpression(const Expr *E) const { 7268 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7269 7270 // It is not an array section and therefore not a unity-size one. 7271 if (!OASE) 7272 return false; 7273 7274 // An array section with no colon always refer to a single element. 7275 if (OASE->getColonLocFirst().isInvalid()) 7276 return false; 7277 7278 const Expr *Length = OASE->getLength(); 7279 7280 // If we don't have a length we have to check if the array has size 1 7281 // for this dimension. Also, we should always expect a length if the 7282 // base type is pointer. 7283 if (!Length) { 7284 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7285 OASE->getBase()->IgnoreParenImpCasts()) 7286 .getCanonicalType(); 7287 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7288 return ATy->getSize().getSExtValue() != 1; 7289 // If we don't have a constant dimension length, we have to consider 7290 // the current section as having any size, so it is not necessarily 7291 // unitary. If it happen to be unity size, that's user fault. 7292 return true; 7293 } 7294 7295 // Check if the length evaluates to 1. 7296 Expr::EvalResult Result; 7297 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7298 return true; // Can have more that size 1. 7299 7300 llvm::APSInt ConstLength = Result.Val.getInt(); 7301 return ConstLength.getSExtValue() != 1; 7302 } 7303 7304 /// Generate the base pointers, section pointers, sizes, map type bits, and 7305 /// user-defined mappers (all included in \a CombinedInfo) for the provided 7306 /// map type, map or motion modifiers, and expression components. 7307 /// \a IsFirstComponent should be set to true if the provided set of 7308 /// components is the first associated with a capture. 7309 void generateInfoForComponentList( 7310 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7311 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7312 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7313 MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct, 7314 bool IsFirstComponentList, bool IsImplicit, 7315 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false, 7316 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7317 OverlappedElements = llvm::None) const { 7318 // The following summarizes what has to be generated for each map and the 7319 // types below. The generated information is expressed in this order: 7320 // base pointer, section pointer, size, flags 7321 // (to add to the ones that come from the map type and modifier). 7322 // 7323 // double d; 7324 // int i[100]; 7325 // float *p; 7326 // 7327 // struct S1 { 7328 // int i; 7329 // float f[50]; 7330 // } 7331 // struct S2 { 7332 // int i; 7333 // float f[50]; 7334 // S1 s; 7335 // double *p; 7336 // struct S2 *ps; 7337 // } 7338 // S2 s; 7339 // S2 *ps; 7340 // 7341 // map(d) 7342 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7343 // 7344 // map(i) 7345 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7346 // 7347 // map(i[1:23]) 7348 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7349 // 7350 // map(p) 7351 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7352 // 7353 // map(p[1:24]) 7354 // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ 7355 // in unified shared memory mode or for local pointers 7356 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7357 // 7358 // map(s) 7359 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7360 // 7361 // map(s.i) 7362 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7363 // 7364 // map(s.s.f) 7365 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7366 // 7367 // map(s.p) 7368 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7369 // 7370 // map(to: s.p[:22]) 7371 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7372 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7373 // &(s.p), &(s.p[0]), 22*sizeof(double), 7374 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7375 // (*) alloc space for struct members, only this is a target parameter 7376 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7377 // optimizes this entry out, same in the examples below) 7378 // (***) map the pointee (map: to) 7379 // 7380 // map(s.ps) 7381 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7382 // 7383 // map(from: s.ps->s.i) 7384 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7385 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7386 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7387 // 7388 // map(to: s.ps->ps) 7389 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7390 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7391 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7392 // 7393 // map(s.ps->ps->ps) 7394 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7395 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7396 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7397 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7398 // 7399 // map(to: s.ps->ps->s.f[:22]) 7400 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7401 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7402 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7403 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7404 // 7405 // map(ps) 7406 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7407 // 7408 // map(ps->i) 7409 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7410 // 7411 // map(ps->s.f) 7412 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7413 // 7414 // map(from: ps->p) 7415 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7416 // 7417 // map(to: ps->p[:22]) 7418 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7419 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7420 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7421 // 7422 // map(ps->ps) 7423 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7424 // 7425 // map(from: ps->ps->s.i) 7426 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7427 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7428 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7429 // 7430 // map(from: ps->ps->ps) 7431 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7432 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7433 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7434 // 7435 // map(ps->ps->ps->ps) 7436 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7437 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7438 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7439 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7440 // 7441 // map(to: ps->ps->ps->s.f[:22]) 7442 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7443 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7444 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7445 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7446 // 7447 // map(to: s.f[:22]) map(from: s.p[:33]) 7448 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7449 // sizeof(double*) (**), TARGET_PARAM 7450 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7451 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7452 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7453 // (*) allocate contiguous space needed to fit all mapped members even if 7454 // we allocate space for members not mapped (in this example, 7455 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7456 // them as well because they fall between &s.f[0] and &s.p) 7457 // 7458 // map(from: s.f[:22]) map(to: ps->p[:33]) 7459 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7460 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7461 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7462 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7463 // (*) the struct this entry pertains to is the 2nd element in the list of 7464 // arguments, hence MEMBER_OF(2) 7465 // 7466 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7467 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7468 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7469 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7470 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7471 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7472 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7473 // (*) the struct this entry pertains to is the 4th element in the list 7474 // of arguments, hence MEMBER_OF(4) 7475 7476 // Track if the map information being generated is the first for a capture. 7477 bool IsCaptureFirstInfo = IsFirstComponentList; 7478 // When the variable is on a declare target link or in a to clause with 7479 // unified memory, a reference is needed to hold the host/device address 7480 // of the variable. 7481 bool RequiresReference = false; 7482 7483 // Scan the components from the base to the complete expression. 7484 auto CI = Components.rbegin(); 7485 auto CE = Components.rend(); 7486 auto I = CI; 7487 7488 // Track if the map information being generated is the first for a list of 7489 // components. 7490 bool IsExpressionFirstInfo = true; 7491 bool FirstPointerInComplexData = false; 7492 Address BP = Address::invalid(); 7493 const Expr *AssocExpr = I->getAssociatedExpression(); 7494 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7495 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7496 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr); 7497 7498 if (isa<MemberExpr>(AssocExpr)) { 7499 // The base is the 'this' pointer. The content of the pointer is going 7500 // to be the base of the field being mapped. 7501 BP = CGF.LoadCXXThisAddress(); 7502 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7503 (OASE && 7504 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7505 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7506 } else if (OAShE && 7507 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) { 7508 BP = Address( 7509 CGF.EmitScalarExpr(OAShE->getBase()), 7510 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType())); 7511 } else { 7512 // The base is the reference to the variable. 7513 // BP = &Var. 7514 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7515 if (const auto *VD = 7516 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7517 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7518 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7519 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7520 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7521 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7522 RequiresReference = true; 7523 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7524 } 7525 } 7526 } 7527 7528 // If the variable is a pointer and is being dereferenced (i.e. is not 7529 // the last component), the base has to be the pointer itself, not its 7530 // reference. References are ignored for mapping purposes. 7531 QualType Ty = 7532 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7533 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7534 // No need to generate individual map information for the pointer, it 7535 // can be associated with the combined storage if shared memory mode is 7536 // active or the base declaration is not global variable. 7537 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration()); 7538 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 7539 !VD || VD->hasLocalStorage()) 7540 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7541 else 7542 FirstPointerInComplexData = true; 7543 ++I; 7544 } 7545 } 7546 7547 // Track whether a component of the list should be marked as MEMBER_OF some 7548 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7549 // in a component list should be marked as MEMBER_OF, all subsequent entries 7550 // do not belong to the base struct. E.g. 7551 // struct S2 s; 7552 // s.ps->ps->ps->f[:] 7553 // (1) (2) (3) (4) 7554 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7555 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7556 // is the pointee of ps(2) which is not member of struct s, so it should not 7557 // be marked as such (it is still PTR_AND_OBJ). 7558 // The variable is initialized to false so that PTR_AND_OBJ entries which 7559 // are not struct members are not considered (e.g. array of pointers to 7560 // data). 7561 bool ShouldBeMemberOf = false; 7562 7563 // Variable keeping track of whether or not we have encountered a component 7564 // in the component list which is a member expression. Useful when we have a 7565 // pointer or a final array section, in which case it is the previous 7566 // component in the list which tells us whether we have a member expression. 7567 // E.g. X.f[:] 7568 // While processing the final array section "[:]" it is "f" which tells us 7569 // whether we are dealing with a member of a declared struct. 7570 const MemberExpr *EncounteredME = nullptr; 7571 7572 for (; I != CE; ++I) { 7573 // If the current component is member of a struct (parent struct) mark it. 7574 if (!EncounteredME) { 7575 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7576 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7577 // as MEMBER_OF the parent struct. 7578 if (EncounteredME) { 7579 ShouldBeMemberOf = true; 7580 // Do not emit as complex pointer if this is actually not array-like 7581 // expression. 7582 if (FirstPointerInComplexData) { 7583 QualType Ty = std::prev(I) 7584 ->getAssociatedDeclaration() 7585 ->getType() 7586 .getNonReferenceType(); 7587 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7588 FirstPointerInComplexData = false; 7589 } 7590 } 7591 } 7592 7593 auto Next = std::next(I); 7594 7595 // We need to generate the addresses and sizes if this is the last 7596 // component, if the component is a pointer or if it is an array section 7597 // whose length can't be proved to be one. If this is a pointer, it 7598 // becomes the base address for the following components. 7599 7600 // A final array section, is one whose length can't be proved to be one. 7601 bool IsFinalArraySection = 7602 isFinalArraySectionExpression(I->getAssociatedExpression()); 7603 7604 // Get information on whether the element is a pointer. Have to do a 7605 // special treatment for array sections given that they are built-in 7606 // types. 7607 const auto *OASE = 7608 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7609 const auto *OAShE = 7610 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression()); 7611 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 7612 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 7613 bool IsPointer = 7614 OAShE || 7615 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7616 .getCanonicalType() 7617 ->isAnyPointerType()) || 7618 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7619 bool IsNonDerefPointer = IsPointer && !UO && !BO; 7620 7621 if (Next == CE || IsNonDerefPointer || IsFinalArraySection) { 7622 // If this is not the last component, we expect the pointer to be 7623 // associated with an array expression or member expression. 7624 assert((Next == CE || 7625 isa<MemberExpr>(Next->getAssociatedExpression()) || 7626 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7627 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 7628 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || 7629 isa<UnaryOperator>(Next->getAssociatedExpression()) || 7630 isa<BinaryOperator>(Next->getAssociatedExpression())) && 7631 "Unexpected expression"); 7632 7633 Address LB = Address::invalid(); 7634 if (OAShE) { 7635 LB = Address(CGF.EmitScalarExpr(OAShE->getBase()), 7636 CGF.getContext().getTypeAlignInChars( 7637 OAShE->getBase()->getType())); 7638 } else { 7639 LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7640 .getAddress(CGF); 7641 } 7642 7643 // If this component is a pointer inside the base struct then we don't 7644 // need to create any entry for it - it will be combined with the object 7645 // it is pointing to into a single PTR_AND_OBJ entry. 7646 bool IsMemberPointerOrAddr = 7647 (IsPointer || ForDeviceAddr) && EncounteredME && 7648 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7649 EncounteredME); 7650 if (!OverlappedElements.empty()) { 7651 // Handle base element with the info for overlapped elements. 7652 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7653 assert(Next == CE && 7654 "Expected last element for the overlapped elements."); 7655 assert(!IsPointer && 7656 "Unexpected base element with the pointer type."); 7657 // Mark the whole struct as the struct that requires allocation on the 7658 // device. 7659 PartialStruct.LowestElem = {0, LB}; 7660 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7661 I->getAssociatedExpression()->getType()); 7662 Address HB = CGF.Builder.CreateConstGEP( 7663 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7664 CGF.VoidPtrTy), 7665 TypeSize.getQuantity() - 1); 7666 PartialStruct.HighestElem = { 7667 std::numeric_limits<decltype( 7668 PartialStruct.HighestElem.first)>::max(), 7669 HB}; 7670 PartialStruct.Base = BP; 7671 // Emit data for non-overlapped data. 7672 OpenMPOffloadMappingFlags Flags = 7673 OMP_MAP_MEMBER_OF | 7674 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, 7675 /*AddPtrFlag=*/false, 7676 /*AddIsTargetParamFlag=*/false); 7677 LB = BP; 7678 llvm::Value *Size = nullptr; 7679 // Do bitcopy of all non-overlapped structure elements. 7680 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7681 Component : OverlappedElements) { 7682 Address ComponentLB = Address::invalid(); 7683 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7684 Component) { 7685 if (MC.getAssociatedDeclaration()) { 7686 ComponentLB = 7687 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7688 .getAddress(CGF); 7689 Size = CGF.Builder.CreatePtrDiff( 7690 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7691 CGF.EmitCastToVoidPtr(LB.getPointer())); 7692 break; 7693 } 7694 } 7695 assert(Size && "Failed to determine structure size"); 7696 CombinedInfo.BasePointers.push_back(BP.getPointer()); 7697 CombinedInfo.Pointers.push_back(LB.getPointer()); 7698 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 7699 Size, CGF.Int64Ty, /*isSigned=*/true)); 7700 CombinedInfo.Types.push_back(Flags); 7701 CombinedInfo.Mappers.push_back(nullptr); 7702 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7703 } 7704 CombinedInfo.BasePointers.push_back(BP.getPointer()); 7705 CombinedInfo.Pointers.push_back(LB.getPointer()); 7706 Size = CGF.Builder.CreatePtrDiff( 7707 CGF.EmitCastToVoidPtr( 7708 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7709 CGF.EmitCastToVoidPtr(LB.getPointer())); 7710 CombinedInfo.Sizes.push_back( 7711 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7712 CombinedInfo.Types.push_back(Flags); 7713 CombinedInfo.Mappers.push_back(nullptr); 7714 break; 7715 } 7716 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7717 if (!IsMemberPointerOrAddr) { 7718 CombinedInfo.BasePointers.push_back(BP.getPointer()); 7719 CombinedInfo.Pointers.push_back(LB.getPointer()); 7720 CombinedInfo.Sizes.push_back( 7721 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7722 7723 // If Mapper is valid, the last component inherits the mapper. 7724 bool HasMapper = Mapper && Next == CE; 7725 CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr); 7726 7727 // We need to add a pointer flag for each map that comes from the 7728 // same expression except for the first one. We also need to signal 7729 // this map is the first one that relates with the current capture 7730 // (there is a set of entries for each capture). 7731 OpenMPOffloadMappingFlags Flags = 7732 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, 7733 !IsExpressionFirstInfo || RequiresReference || 7734 FirstPointerInComplexData, 7735 IsCaptureFirstInfo && !RequiresReference); 7736 7737 if (!IsExpressionFirstInfo) { 7738 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7739 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7740 if (IsPointer) 7741 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7742 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7743 7744 if (ShouldBeMemberOf) { 7745 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7746 // should be later updated with the correct value of MEMBER_OF. 7747 Flags |= OMP_MAP_MEMBER_OF; 7748 // From now on, all subsequent PTR_AND_OBJ entries should not be 7749 // marked as MEMBER_OF. 7750 ShouldBeMemberOf = false; 7751 } 7752 } 7753 7754 CombinedInfo.Types.push_back(Flags); 7755 } 7756 7757 // If we have encountered a member expression so far, keep track of the 7758 // mapped member. If the parent is "*this", then the value declaration 7759 // is nullptr. 7760 if (EncounteredME) { 7761 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 7762 unsigned FieldIndex = FD->getFieldIndex(); 7763 7764 // Update info about the lowest and highest elements for this struct 7765 if (!PartialStruct.Base.isValid()) { 7766 PartialStruct.LowestElem = {FieldIndex, LB}; 7767 if (IsFinalArraySection) { 7768 Address HB = 7769 CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false) 7770 .getAddress(CGF); 7771 PartialStruct.HighestElem = {FieldIndex, HB}; 7772 } else { 7773 PartialStruct.HighestElem = {FieldIndex, LB}; 7774 } 7775 PartialStruct.Base = BP; 7776 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7777 PartialStruct.LowestElem = {FieldIndex, LB}; 7778 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7779 PartialStruct.HighestElem = {FieldIndex, LB}; 7780 } 7781 } 7782 7783 // If we have a final array section, we are done with this expression. 7784 if (IsFinalArraySection) 7785 break; 7786 7787 // The pointer becomes the base for the next element. 7788 if (Next != CE) 7789 BP = LB; 7790 7791 IsExpressionFirstInfo = false; 7792 IsCaptureFirstInfo = false; 7793 FirstPointerInComplexData = false; 7794 } 7795 } 7796 } 7797 7798 /// Return the adjusted map modifiers if the declaration a capture refers to 7799 /// appears in a first-private clause. This is expected to be used only with 7800 /// directives that start with 'target'. 7801 MappableExprsHandler::OpenMPOffloadMappingFlags 7802 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7803 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7804 7805 // A first private variable captured by reference will use only the 7806 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7807 // declaration is known as first-private in this handler. 7808 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7809 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7810 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7811 return MappableExprsHandler::OMP_MAP_ALWAYS | 7812 MappableExprsHandler::OMP_MAP_TO; 7813 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7814 return MappableExprsHandler::OMP_MAP_TO | 7815 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7816 return MappableExprsHandler::OMP_MAP_PRIVATE | 7817 MappableExprsHandler::OMP_MAP_TO; 7818 } 7819 return MappableExprsHandler::OMP_MAP_TO | 7820 MappableExprsHandler::OMP_MAP_FROM; 7821 } 7822 7823 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7824 // Rotate by getFlagMemberOffset() bits. 7825 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7826 << getFlagMemberOffset()); 7827 } 7828 7829 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7830 OpenMPOffloadMappingFlags MemberOfFlag) { 7831 // If the entry is PTR_AND_OBJ but has not been marked with the special 7832 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7833 // marked as MEMBER_OF. 7834 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7835 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7836 return; 7837 7838 // Reset the placeholder value to prepare the flag for the assignment of the 7839 // proper MEMBER_OF value. 7840 Flags &= ~OMP_MAP_MEMBER_OF; 7841 Flags |= MemberOfFlag; 7842 } 7843 7844 void getPlainLayout(const CXXRecordDecl *RD, 7845 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7846 bool AsBase) const { 7847 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7848 7849 llvm::StructType *St = 7850 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7851 7852 unsigned NumElements = St->getNumElements(); 7853 llvm::SmallVector< 7854 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7855 RecordLayout(NumElements); 7856 7857 // Fill bases. 7858 for (const auto &I : RD->bases()) { 7859 if (I.isVirtual()) 7860 continue; 7861 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7862 // Ignore empty bases. 7863 if (Base->isEmpty() || CGF.getContext() 7864 .getASTRecordLayout(Base) 7865 .getNonVirtualSize() 7866 .isZero()) 7867 continue; 7868 7869 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7870 RecordLayout[FieldIndex] = Base; 7871 } 7872 // Fill in virtual bases. 7873 for (const auto &I : RD->vbases()) { 7874 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7875 // Ignore empty bases. 7876 if (Base->isEmpty()) 7877 continue; 7878 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7879 if (RecordLayout[FieldIndex]) 7880 continue; 7881 RecordLayout[FieldIndex] = Base; 7882 } 7883 // Fill in all the fields. 7884 assert(!RD->isUnion() && "Unexpected union."); 7885 for (const auto *Field : RD->fields()) { 7886 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7887 // will fill in later.) 7888 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7889 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7890 RecordLayout[FieldIndex] = Field; 7891 } 7892 } 7893 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7894 &Data : RecordLayout) { 7895 if (Data.isNull()) 7896 continue; 7897 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7898 getPlainLayout(Base, Layout, /*AsBase=*/true); 7899 else 7900 Layout.push_back(Data.get<const FieldDecl *>()); 7901 } 7902 } 7903 7904 public: 7905 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7906 : CurDir(&Dir), CGF(CGF) { 7907 // Extract firstprivate clause information. 7908 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7909 for (const auto *D : C->varlists()) 7910 FirstPrivateDecls.try_emplace( 7911 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 7912 // Extract implicit firstprivates from uses_allocators clauses. 7913 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) { 7914 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 7915 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 7916 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits)) 7917 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()), 7918 /*Implicit=*/true); 7919 else if (const auto *VD = dyn_cast<VarDecl>( 7920 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts()) 7921 ->getDecl())) 7922 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true); 7923 } 7924 } 7925 // Extract device pointer clause information. 7926 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7927 for (auto L : C->component_lists()) 7928 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L)); 7929 } 7930 7931 /// Constructor for the declare mapper directive. 7932 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 7933 : CurDir(&Dir), CGF(CGF) {} 7934 7935 /// Generate code for the combined entry if we have a partially mapped struct 7936 /// and take care of the mapping flags of the arguments corresponding to 7937 /// individual struct members. 7938 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo, 7939 MapFlagsArrayTy &CurTypes, 7940 const StructRangeInfoTy &PartialStruct, 7941 bool NotTargetParams = false) const { 7942 // Base is the base of the struct 7943 CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); 7944 // Pointer is the address of the lowest element 7945 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7946 CombinedInfo.Pointers.push_back(LB); 7947 // There should not be a mapper for a combined entry. 7948 CombinedInfo.Mappers.push_back(nullptr); 7949 // Size is (addr of {highest+1} element) - (addr of lowest element) 7950 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7951 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7952 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7953 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7954 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7955 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 7956 /*isSigned=*/false); 7957 CombinedInfo.Sizes.push_back(Size); 7958 // Map type is always TARGET_PARAM, if generate info for captures. 7959 CombinedInfo.Types.push_back(NotTargetParams ? OMP_MAP_NONE 7960 : OMP_MAP_TARGET_PARAM); 7961 // If any element has the present modifier, then make sure the runtime 7962 // doesn't attempt to allocate the struct. 7963 if (CurTypes.end() != 7964 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) { 7965 return Type & OMP_MAP_PRESENT; 7966 })) 7967 CombinedInfo.Types.back() |= OMP_MAP_PRESENT; 7968 // Remove TARGET_PARAM flag from the first element 7969 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7970 7971 // All other current entries will be MEMBER_OF the combined entry 7972 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7973 // 0xFFFF in the MEMBER_OF field). 7974 OpenMPOffloadMappingFlags MemberOfFlag = 7975 getMemberOfFlag(CombinedInfo.BasePointers.size() - 1); 7976 for (auto &M : CurTypes) 7977 setCorrectMemberOfFlag(M, MemberOfFlag); 7978 } 7979 7980 /// Generate all the base pointers, section pointers, sizes, map types, and 7981 /// mappers for the extracted mappable expressions (all included in \a 7982 /// CombinedInfo). Also, for each item that relates with a device pointer, a 7983 /// pair of the relevant declaration and index where it occurs is appended to 7984 /// the device pointers info array. 7985 void generateAllInfo( 7986 MapCombinedInfoTy &CombinedInfo, bool NotTargetParams = false, 7987 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 7988 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 7989 // We have to process the component lists that relate with the same 7990 // declaration in a single chunk so that we can generate the map flags 7991 // correctly. Therefore, we organize all lists in a map. 7992 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7993 7994 // Helper function to fill the information map for the different supported 7995 // clauses. 7996 auto &&InfoGen = 7997 [&Info, &SkipVarSet]( 7998 const ValueDecl *D, 7999 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8000 OpenMPMapClauseKind MapType, 8001 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8002 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 8003 bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper, 8004 bool ForDeviceAddr = false) { 8005 const ValueDecl *VD = 8006 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8007 if (SkipVarSet.count(VD)) 8008 return; 8009 Info[VD].emplace_back(L, MapType, MapModifiers, MotionModifiers, 8010 ReturnDevicePointer, IsImplicit, Mapper, 8011 ForDeviceAddr); 8012 }; 8013 8014 assert(CurDir.is<const OMPExecutableDirective *>() && 8015 "Expect a executable directive"); 8016 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8017 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 8018 for (const auto L : C->component_lists()) { 8019 InfoGen(std::get<0>(L), std::get<1>(L), C->getMapType(), 8020 C->getMapTypeModifiers(), llvm::None, 8021 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L)); 8022 } 8023 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 8024 for (const auto L : C->component_lists()) { 8025 InfoGen(std::get<0>(L), std::get<1>(L), OMPC_MAP_to, llvm::None, 8026 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8027 C->isImplicit(), std::get<2>(L)); 8028 } 8029 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 8030 for (const auto L : C->component_lists()) { 8031 InfoGen(std::get<0>(L), std::get<1>(L), OMPC_MAP_from, llvm::None, 8032 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8033 C->isImplicit(), std::get<2>(L)); 8034 } 8035 8036 // Look at the use_device_ptr clause information and mark the existing map 8037 // entries as such. If there is no map information for an entry in the 8038 // use_device_ptr list, we create one with map type 'alloc' and zero size 8039 // section. It is the user fault if that was not mapped before. If there is 8040 // no map information and the pointer is a struct member, then we defer the 8041 // emission of that entry until the whole struct has been processed. 8042 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 8043 DeferredInfo; 8044 MapCombinedInfoTy UseDevicePtrCombinedInfo; 8045 8046 for (const auto *C : 8047 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 8048 for (const auto L : C->component_lists()) { 8049 OMPClauseMappableExprCommon::MappableExprComponentListRef Components = 8050 std::get<1>(L); 8051 assert(!Components.empty() && 8052 "Not expecting empty list of components!"); 8053 const ValueDecl *VD = Components.back().getAssociatedDeclaration(); 8054 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8055 const Expr *IE = Components.back().getAssociatedExpression(); 8056 // If the first component is a member expression, we have to look into 8057 // 'this', which maps to null in the map of map information. Otherwise 8058 // look directly for the information. 8059 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8060 8061 // We potentially have map information for this declaration already. 8062 // Look for the first set of components that refer to it. 8063 if (It != Info.end()) { 8064 auto *CI = llvm::find_if(It->second, [VD](const MapInfo &MI) { 8065 return MI.Components.back().getAssociatedDeclaration() == VD; 8066 }); 8067 // If we found a map entry, signal that the pointer has to be returned 8068 // and move on to the next declaration. 8069 // Exclude cases where the base pointer is mapped as array subscript, 8070 // array section or array shaping. The base address is passed as a 8071 // pointer to base in this case and cannot be used as a base for 8072 // use_device_ptr list item. 8073 if (CI != It->second.end()) { 8074 auto PrevCI = std::next(CI->Components.rbegin()); 8075 const auto *VarD = dyn_cast<VarDecl>(VD); 8076 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8077 isa<MemberExpr>(IE) || 8078 !VD->getType().getNonReferenceType()->isPointerType() || 8079 PrevCI == CI->Components.rend() || 8080 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD || 8081 VarD->hasLocalStorage()) { 8082 CI->ReturnDevicePointer = true; 8083 continue; 8084 } 8085 } 8086 } 8087 8088 // We didn't find any match in our map information - generate a zero 8089 // size array section - if the pointer is a struct member we defer this 8090 // action until the whole struct has been processed. 8091 if (isa<MemberExpr>(IE)) { 8092 // Insert the pointer into Info to be processed by 8093 // generateInfoForComponentList. Because it is a member pointer 8094 // without a pointee, no entry will be generated for it, therefore 8095 // we need to generate one after the whole struct has been processed. 8096 // Nonetheless, generateInfoForComponentList must be called to take 8097 // the pointer into account for the calculation of the range of the 8098 // partial struct. 8099 InfoGen(nullptr, Components, OMPC_MAP_unknown, llvm::None, llvm::None, 8100 /*ReturnDevicePointer=*/false, C->isImplicit(), nullptr); 8101 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false); 8102 } else { 8103 llvm::Value *Ptr = 8104 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8105 UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD); 8106 UseDevicePtrCombinedInfo.Pointers.push_back(Ptr); 8107 UseDevicePtrCombinedInfo.Sizes.push_back( 8108 llvm::Constant::getNullValue(CGF.Int64Ty)); 8109 UseDevicePtrCombinedInfo.Types.push_back( 8110 OMP_MAP_RETURN_PARAM | 8111 (NotTargetParams ? OMP_MAP_NONE : OMP_MAP_TARGET_PARAM)); 8112 UseDevicePtrCombinedInfo.Mappers.push_back(nullptr); 8113 } 8114 } 8115 } 8116 8117 // Look at the use_device_addr clause information and mark the existing map 8118 // entries as such. If there is no map information for an entry in the 8119 // use_device_addr list, we create one with map type 'alloc' and zero size 8120 // section. It is the user fault if that was not mapped before. If there is 8121 // no map information and the pointer is a struct member, then we defer the 8122 // emission of that entry until the whole struct has been processed. 8123 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed; 8124 for (const auto *C : 8125 CurExecDir->getClausesOfKind<OMPUseDeviceAddrClause>()) { 8126 for (const auto L : C->component_lists()) { 8127 assert(!std::get<1>(L).empty() && 8128 "Not expecting empty list of components!"); 8129 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration(); 8130 if (!Processed.insert(VD).second) 8131 continue; 8132 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8133 const Expr *IE = std::get<1>(L).back().getAssociatedExpression(); 8134 // If the first component is a member expression, we have to look into 8135 // 'this', which maps to null in the map of map information. Otherwise 8136 // look directly for the information. 8137 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8138 8139 // We potentially have map information for this declaration already. 8140 // Look for the first set of components that refer to it. 8141 if (It != Info.end()) { 8142 auto *CI = llvm::find_if(It->second, [VD](const MapInfo &MI) { 8143 return MI.Components.back().getAssociatedDeclaration() == VD; 8144 }); 8145 // If we found a map entry, signal that the pointer has to be returned 8146 // and move on to the next declaration. 8147 if (CI != It->second.end()) { 8148 CI->ReturnDevicePointer = true; 8149 continue; 8150 } 8151 } 8152 8153 // We didn't find any match in our map information - generate a zero 8154 // size array section - if the pointer is a struct member we defer this 8155 // action until the whole struct has been processed. 8156 if (isa<MemberExpr>(IE)) { 8157 // Insert the pointer into Info to be processed by 8158 // generateInfoForComponentList. Because it is a member pointer 8159 // without a pointee, no entry will be generated for it, therefore 8160 // we need to generate one after the whole struct has been processed. 8161 // Nonetheless, generateInfoForComponentList must be called to take 8162 // the pointer into account for the calculation of the range of the 8163 // partial struct. 8164 InfoGen(nullptr, std::get<1>(L), OMPC_MAP_unknown, llvm::None, 8165 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8166 nullptr, /*ForDeviceAddr=*/true); 8167 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true); 8168 } else { 8169 llvm::Value *Ptr; 8170 if (IE->isGLValue()) 8171 Ptr = CGF.EmitLValue(IE).getPointer(CGF); 8172 else 8173 Ptr = CGF.EmitScalarExpr(IE); 8174 CombinedInfo.BasePointers.emplace_back(Ptr, VD); 8175 CombinedInfo.Pointers.push_back(Ptr); 8176 CombinedInfo.Sizes.push_back( 8177 llvm::Constant::getNullValue(CGF.Int64Ty)); 8178 CombinedInfo.Types.push_back( 8179 OMP_MAP_RETURN_PARAM | 8180 (NotTargetParams ? OMP_MAP_NONE : OMP_MAP_TARGET_PARAM)); 8181 CombinedInfo.Mappers.push_back(nullptr); 8182 } 8183 } 8184 } 8185 8186 for (const auto &M : Info) { 8187 // We need to know when we generate information for the first component 8188 // associated with a capture, because the mapping flags depend on it. 8189 bool IsFirstComponentList = !NotTargetParams; 8190 8191 // Temporary generated information. 8192 MapCombinedInfoTy CurInfo; 8193 StructRangeInfoTy PartialStruct; 8194 8195 for (const MapInfo &L : M.second) { 8196 assert(!L.Components.empty() && 8197 "Not expecting declaration with no component lists."); 8198 8199 // Remember the current base pointer index. 8200 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size(); 8201 generateInfoForComponentList(L.MapType, L.MapModifiers, 8202 L.MotionModifiers, L.Components, CurInfo, 8203 PartialStruct, IsFirstComponentList, 8204 L.IsImplicit, L.Mapper, L.ForDeviceAddr); 8205 8206 // If this entry relates with a device pointer, set the relevant 8207 // declaration and add the 'return pointer' flag. 8208 if (L.ReturnDevicePointer) { 8209 assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx && 8210 "Unexpected number of mapped base pointers."); 8211 8212 const ValueDecl *RelevantVD = 8213 L.Components.back().getAssociatedDeclaration(); 8214 assert(RelevantVD && 8215 "No relevant declaration related with device pointer??"); 8216 8217 CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl( 8218 RelevantVD); 8219 CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8220 } 8221 IsFirstComponentList = false; 8222 } 8223 8224 // Append any pending zero-length pointers which are struct members and 8225 // used with use_device_ptr or use_device_addr. 8226 auto CI = DeferredInfo.find(M.first); 8227 if (CI != DeferredInfo.end()) { 8228 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8229 llvm::Value *BasePtr; 8230 llvm::Value *Ptr; 8231 if (L.ForDeviceAddr) { 8232 if (L.IE->isGLValue()) 8233 Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8234 else 8235 Ptr = this->CGF.EmitScalarExpr(L.IE); 8236 BasePtr = Ptr; 8237 // Entry is RETURN_PARAM. Also, set the placeholder value 8238 // MEMBER_OF=FFFF so that the entry is later updated with the 8239 // correct value of MEMBER_OF. 8240 CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF); 8241 } else { 8242 BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8243 Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE), 8244 L.IE->getExprLoc()); 8245 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8246 // value MEMBER_OF=FFFF so that the entry is later updated with the 8247 // correct value of MEMBER_OF. 8248 CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8249 OMP_MAP_MEMBER_OF); 8250 } 8251 CurInfo.BasePointers.emplace_back(BasePtr, L.VD); 8252 CurInfo.Pointers.push_back(Ptr); 8253 CurInfo.Sizes.push_back( 8254 llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8255 CurInfo.Mappers.push_back(nullptr); 8256 } 8257 } 8258 8259 // If there is an entry in PartialStruct it means we have a struct with 8260 // individual members mapped. Emit an extra combined entry. 8261 if (PartialStruct.Base.isValid()) 8262 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, 8263 NotTargetParams); 8264 8265 // We need to append the results of this capture to what we already have. 8266 CombinedInfo.append(CurInfo); 8267 } 8268 // Append data for use_device_ptr clauses. 8269 CombinedInfo.append(UseDevicePtrCombinedInfo); 8270 } 8271 8272 /// Generate all the base pointers, section pointers, sizes, map types, and 8273 /// mappers for the extracted map clauses of user-defined mapper (all included 8274 /// in \a CombinedInfo). 8275 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const { 8276 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8277 "Expect a declare mapper directive"); 8278 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8279 // We have to process the component lists that relate with the same 8280 // declaration in a single chunk so that we can generate the map flags 8281 // correctly. Therefore, we organize all lists in a map. 8282 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8283 8284 // Fill the information map for map clauses. 8285 for (const auto *C : CurMapperDir->clauselists()) { 8286 const auto *MC = cast<OMPMapClause>(C); 8287 for (const auto L : MC->component_lists()) { 8288 const ValueDecl *VD = 8289 std::get<0>(L) ? cast<ValueDecl>(std::get<0>(L)->getCanonicalDecl()) 8290 : nullptr; 8291 // Get the corresponding user-defined mapper. 8292 Info[VD].emplace_back(std::get<1>(L), MC->getMapType(), 8293 MC->getMapTypeModifiers(), llvm::None, 8294 /*ReturnDevicePointer=*/false, MC->isImplicit(), 8295 std::get<2>(L)); 8296 } 8297 } 8298 8299 for (const auto &M : Info) { 8300 // We need to know when we generate information for the first component 8301 // associated with a capture, because the mapping flags depend on it. 8302 bool IsFirstComponentList = true; 8303 8304 // Temporary generated information. 8305 MapCombinedInfoTy CurInfo; 8306 StructRangeInfoTy PartialStruct; 8307 8308 for (const MapInfo &L : M.second) { 8309 assert(!L.Components.empty() && 8310 "Not expecting declaration with no component lists."); 8311 generateInfoForComponentList(L.MapType, L.MapModifiers, 8312 L.MotionModifiers, L.Components, CurInfo, 8313 PartialStruct, IsFirstComponentList, 8314 L.IsImplicit, L.Mapper, L.ForDeviceAddr); 8315 IsFirstComponentList = false; 8316 } 8317 8318 // If there is an entry in PartialStruct it means we have a struct with 8319 // individual members mapped. Emit an extra combined entry. 8320 if (PartialStruct.Base.isValid()) 8321 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct); 8322 8323 // We need to append the results of this capture to what we already have. 8324 CombinedInfo.append(CurInfo); 8325 } 8326 } 8327 8328 /// Emit capture info for lambdas for variables captured by reference. 8329 void generateInfoForLambdaCaptures( 8330 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 8331 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8332 const auto *RD = VD->getType() 8333 .getCanonicalType() 8334 .getNonReferenceType() 8335 ->getAsCXXRecordDecl(); 8336 if (!RD || !RD->isLambda()) 8337 return; 8338 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8339 LValue VDLVal = CGF.MakeAddrLValue( 8340 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8341 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8342 FieldDecl *ThisCapture = nullptr; 8343 RD->getCaptureFields(Captures, ThisCapture); 8344 if (ThisCapture) { 8345 LValue ThisLVal = 8346 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8347 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8348 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8349 VDLVal.getPointer(CGF)); 8350 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF)); 8351 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF)); 8352 CombinedInfo.Sizes.push_back( 8353 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8354 CGF.Int64Ty, /*isSigned=*/true)); 8355 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8356 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8357 CombinedInfo.Mappers.push_back(nullptr); 8358 } 8359 for (const LambdaCapture &LC : RD->captures()) { 8360 if (!LC.capturesVariable()) 8361 continue; 8362 const VarDecl *VD = LC.getCapturedVar(); 8363 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8364 continue; 8365 auto It = Captures.find(VD); 8366 assert(It != Captures.end() && "Found lambda capture without field."); 8367 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8368 if (LC.getCaptureKind() == LCK_ByRef) { 8369 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8370 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8371 VDLVal.getPointer(CGF)); 8372 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 8373 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF)); 8374 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8375 CGF.getTypeSize( 8376 VD->getType().getCanonicalType().getNonReferenceType()), 8377 CGF.Int64Ty, /*isSigned=*/true)); 8378 } else { 8379 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8380 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8381 VDLVal.getPointer(CGF)); 8382 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 8383 CombinedInfo.Pointers.push_back(VarRVal.getScalarVal()); 8384 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8385 } 8386 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8387 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8388 CombinedInfo.Mappers.push_back(nullptr); 8389 } 8390 } 8391 8392 /// Set correct indices for lambdas captures. 8393 void adjustMemberOfForLambdaCaptures( 8394 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8395 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8396 MapFlagsArrayTy &Types) const { 8397 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8398 // Set correct member_of idx for all implicit lambda captures. 8399 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8400 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8401 continue; 8402 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8403 assert(BasePtr && "Unable to find base lambda address."); 8404 int TgtIdx = -1; 8405 for (unsigned J = I; J > 0; --J) { 8406 unsigned Idx = J - 1; 8407 if (Pointers[Idx] != BasePtr) 8408 continue; 8409 TgtIdx = Idx; 8410 break; 8411 } 8412 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8413 // All other current entries will be MEMBER_OF the combined entry 8414 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8415 // 0xFFFF in the MEMBER_OF field). 8416 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8417 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8418 } 8419 } 8420 8421 /// Generate the base pointers, section pointers, sizes, map types, and 8422 /// mappers associated to a given capture (all included in \a CombinedInfo). 8423 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8424 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 8425 StructRangeInfoTy &PartialStruct) const { 8426 assert(!Cap->capturesVariableArrayType() && 8427 "Not expecting to generate map info for a variable array type!"); 8428 8429 // We need to know when we generating information for the first component 8430 const ValueDecl *VD = Cap->capturesThis() 8431 ? nullptr 8432 : Cap->getCapturedVar()->getCanonicalDecl(); 8433 8434 // If this declaration appears in a is_device_ptr clause we just have to 8435 // pass the pointer by value. If it is a reference to a declaration, we just 8436 // pass its value. 8437 if (DevPointersMap.count(VD)) { 8438 CombinedInfo.BasePointers.emplace_back(Arg, VD); 8439 CombinedInfo.Pointers.push_back(Arg); 8440 CombinedInfo.Sizes.push_back( 8441 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8442 CGF.Int64Ty, /*isSigned=*/true)); 8443 CombinedInfo.Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8444 CombinedInfo.Mappers.push_back(nullptr); 8445 return; 8446 } 8447 8448 using MapData = 8449 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8450 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool, 8451 const ValueDecl *>; 8452 SmallVector<MapData, 4> DeclComponentLists; 8453 assert(CurDir.is<const OMPExecutableDirective *>() && 8454 "Expect a executable directive"); 8455 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8456 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8457 for (const auto L : C->decl_component_lists(VD)) { 8458 const ValueDecl *VDecl, *Mapper; 8459 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8460 std::tie(VDecl, Components, Mapper) = L; 8461 assert(VDecl == VD && "We got information for the wrong declaration??"); 8462 assert(!Components.empty() && 8463 "Not expecting declaration with no component lists."); 8464 DeclComponentLists.emplace_back(Components, C->getMapType(), 8465 C->getMapTypeModifiers(), 8466 C->isImplicit(), Mapper); 8467 } 8468 } 8469 8470 // Find overlapping elements (including the offset from the base element). 8471 llvm::SmallDenseMap< 8472 const MapData *, 8473 llvm::SmallVector< 8474 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8475 4> 8476 OverlappedData; 8477 size_t Count = 0; 8478 for (const MapData &L : DeclComponentLists) { 8479 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8480 OpenMPMapClauseKind MapType; 8481 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8482 bool IsImplicit; 8483 const ValueDecl *Mapper; 8484 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper) = L; 8485 ++Count; 8486 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8487 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8488 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper) = L1; 8489 auto CI = Components.rbegin(); 8490 auto CE = Components.rend(); 8491 auto SI = Components1.rbegin(); 8492 auto SE = Components1.rend(); 8493 for (; CI != CE && SI != SE; ++CI, ++SI) { 8494 if (CI->getAssociatedExpression()->getStmtClass() != 8495 SI->getAssociatedExpression()->getStmtClass()) 8496 break; 8497 // Are we dealing with different variables/fields? 8498 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8499 break; 8500 } 8501 // Found overlapping if, at least for one component, reached the head of 8502 // the components list. 8503 if (CI == CE || SI == SE) { 8504 assert((CI != CE || SI != SE) && 8505 "Unexpected full match of the mapping components."); 8506 const MapData &BaseData = CI == CE ? L : L1; 8507 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8508 SI == SE ? Components : Components1; 8509 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8510 OverlappedElements.getSecond().push_back(SubData); 8511 } 8512 } 8513 } 8514 // Sort the overlapped elements for each item. 8515 llvm::SmallVector<const FieldDecl *, 4> Layout; 8516 if (!OverlappedData.empty()) { 8517 if (const auto *CRD = 8518 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8519 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8520 else { 8521 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8522 Layout.append(RD->field_begin(), RD->field_end()); 8523 } 8524 } 8525 for (auto &Pair : OverlappedData) { 8526 llvm::sort( 8527 Pair.getSecond(), 8528 [&Layout]( 8529 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8530 OMPClauseMappableExprCommon::MappableExprComponentListRef 8531 Second) { 8532 auto CI = First.rbegin(); 8533 auto CE = First.rend(); 8534 auto SI = Second.rbegin(); 8535 auto SE = Second.rend(); 8536 for (; CI != CE && SI != SE; ++CI, ++SI) { 8537 if (CI->getAssociatedExpression()->getStmtClass() != 8538 SI->getAssociatedExpression()->getStmtClass()) 8539 break; 8540 // Are we dealing with different variables/fields? 8541 if (CI->getAssociatedDeclaration() != 8542 SI->getAssociatedDeclaration()) 8543 break; 8544 } 8545 8546 // Lists contain the same elements. 8547 if (CI == CE && SI == SE) 8548 return false; 8549 8550 // List with less elements is less than list with more elements. 8551 if (CI == CE || SI == SE) 8552 return CI == CE; 8553 8554 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8555 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8556 if (FD1->getParent() == FD2->getParent()) 8557 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8558 const auto It = 8559 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8560 return FD == FD1 || FD == FD2; 8561 }); 8562 return *It == FD1; 8563 }); 8564 } 8565 8566 // Associated with a capture, because the mapping flags depend on it. 8567 // Go through all of the elements with the overlapped elements. 8568 for (const auto &Pair : OverlappedData) { 8569 const MapData &L = *Pair.getFirst(); 8570 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8571 OpenMPMapClauseKind MapType; 8572 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8573 bool IsImplicit; 8574 const ValueDecl *Mapper; 8575 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper) = L; 8576 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8577 OverlappedComponents = Pair.getSecond(); 8578 bool IsFirstComponentList = true; 8579 generateInfoForComponentList( 8580 MapType, MapModifiers, llvm::None, Components, CombinedInfo, 8581 PartialStruct, IsFirstComponentList, IsImplicit, Mapper, 8582 /*ForDeviceAddr=*/false, OverlappedComponents); 8583 } 8584 // Go through other elements without overlapped elements. 8585 bool IsFirstComponentList = OverlappedData.empty(); 8586 for (const MapData &L : DeclComponentLists) { 8587 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8588 OpenMPMapClauseKind MapType; 8589 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8590 bool IsImplicit; 8591 const ValueDecl *Mapper; 8592 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper) = L; 8593 auto It = OverlappedData.find(&L); 8594 if (It == OverlappedData.end()) 8595 generateInfoForComponentList(MapType, MapModifiers, llvm::None, 8596 Components, CombinedInfo, PartialStruct, 8597 IsFirstComponentList, IsImplicit, Mapper); 8598 IsFirstComponentList = false; 8599 } 8600 } 8601 8602 /// Generate the default map information for a given capture \a CI, 8603 /// record field declaration \a RI and captured value \a CV. 8604 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8605 const FieldDecl &RI, llvm::Value *CV, 8606 MapCombinedInfoTy &CombinedInfo) const { 8607 bool IsImplicit = true; 8608 // Do the default mapping. 8609 if (CI.capturesThis()) { 8610 CombinedInfo.BasePointers.push_back(CV); 8611 CombinedInfo.Pointers.push_back(CV); 8612 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8613 CombinedInfo.Sizes.push_back( 8614 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8615 CGF.Int64Ty, /*isSigned=*/true)); 8616 // Default map type. 8617 CombinedInfo.Types.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8618 } else if (CI.capturesVariableByCopy()) { 8619 CombinedInfo.BasePointers.push_back(CV); 8620 CombinedInfo.Pointers.push_back(CV); 8621 if (!RI.getType()->isAnyPointerType()) { 8622 // We have to signal to the runtime captures passed by value that are 8623 // not pointers. 8624 CombinedInfo.Types.push_back(OMP_MAP_LITERAL); 8625 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8626 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8627 } else { 8628 // Pointers are implicitly mapped with a zero size and no flags 8629 // (other than first map that is added for all implicit maps). 8630 CombinedInfo.Types.push_back(OMP_MAP_NONE); 8631 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8632 } 8633 const VarDecl *VD = CI.getCapturedVar(); 8634 auto I = FirstPrivateDecls.find(VD); 8635 if (I != FirstPrivateDecls.end()) 8636 IsImplicit = I->getSecond(); 8637 } else { 8638 assert(CI.capturesVariable() && "Expected captured reference."); 8639 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8640 QualType ElementType = PtrTy->getPointeeType(); 8641 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8642 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8643 // The default map type for a scalar/complex type is 'to' because by 8644 // default the value doesn't have to be retrieved. For an aggregate 8645 // type, the default is 'tofrom'. 8646 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI)); 8647 const VarDecl *VD = CI.getCapturedVar(); 8648 auto I = FirstPrivateDecls.find(VD); 8649 if (I != FirstPrivateDecls.end() && 8650 VD->getType().isConstant(CGF.getContext())) { 8651 llvm::Constant *Addr = 8652 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8653 // Copy the value of the original variable to the new global copy. 8654 CGF.Builder.CreateMemCpy( 8655 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 8656 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8657 CombinedInfo.Sizes.back(), /*IsVolatile=*/false); 8658 // Use new global variable as the base pointers. 8659 CombinedInfo.BasePointers.push_back(Addr); 8660 CombinedInfo.Pointers.push_back(Addr); 8661 } else { 8662 CombinedInfo.BasePointers.push_back(CV); 8663 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8664 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8665 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8666 AlignmentSource::Decl)); 8667 CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); 8668 } else { 8669 CombinedInfo.Pointers.push_back(CV); 8670 } 8671 } 8672 if (I != FirstPrivateDecls.end()) 8673 IsImplicit = I->getSecond(); 8674 } 8675 // Every default map produces a single argument which is a target parameter. 8676 CombinedInfo.Types.back() |= OMP_MAP_TARGET_PARAM; 8677 8678 // Add flag stating this is an implicit map. 8679 if (IsImplicit) 8680 CombinedInfo.Types.back() |= OMP_MAP_IMPLICIT; 8681 8682 // No user-defined mapper for default mapping. 8683 CombinedInfo.Mappers.push_back(nullptr); 8684 } 8685 }; 8686 } // anonymous namespace 8687 8688 /// Emit the arrays used to pass the captures and map information to the 8689 /// offloading runtime library. If there is no map or capture information, 8690 /// return nullptr by reference. 8691 static void 8692 emitOffloadingArrays(CodeGenFunction &CGF, 8693 MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 8694 CGOpenMPRuntime::TargetDataInfo &Info) { 8695 CodeGenModule &CGM = CGF.CGM; 8696 ASTContext &Ctx = CGF.getContext(); 8697 8698 // Reset the array information. 8699 Info.clearArrayInfo(); 8700 Info.NumberOfPtrs = CombinedInfo.BasePointers.size(); 8701 8702 if (Info.NumberOfPtrs) { 8703 // Detect if we have any capture size requiring runtime evaluation of the 8704 // size so that a constant array could be eventually used. 8705 bool hasRuntimeEvaluationCaptureSize = false; 8706 for (llvm::Value *S : CombinedInfo.Sizes) 8707 if (!isa<llvm::Constant>(S)) { 8708 hasRuntimeEvaluationCaptureSize = true; 8709 break; 8710 } 8711 8712 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8713 QualType PointerArrayType = Ctx.getConstantArrayType( 8714 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8715 /*IndexTypeQuals=*/0); 8716 8717 Info.BasePointersArray = 8718 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8719 Info.PointersArray = 8720 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8721 Address MappersArray = 8722 CGF.CreateMemTemp(PointerArrayType, ".offload_mappers"); 8723 Info.MappersArray = MappersArray.getPointer(); 8724 8725 // If we don't have any VLA types or other types that require runtime 8726 // evaluation, we can use a constant array for the map sizes, otherwise we 8727 // need to fill up the arrays as we do for the pointers. 8728 QualType Int64Ty = 8729 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8730 if (hasRuntimeEvaluationCaptureSize) { 8731 QualType SizeArrayType = Ctx.getConstantArrayType( 8732 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8733 /*IndexTypeQuals=*/0); 8734 Info.SizesArray = 8735 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8736 } else { 8737 // We expect all the sizes to be constant, so we collect them to create 8738 // a constant array. 8739 SmallVector<llvm::Constant *, 16> ConstSizes; 8740 for (llvm::Value *S : CombinedInfo.Sizes) 8741 ConstSizes.push_back(cast<llvm::Constant>(S)); 8742 8743 auto *SizesArrayInit = llvm::ConstantArray::get( 8744 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8745 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8746 auto *SizesArrayGbl = new llvm::GlobalVariable( 8747 CGM.getModule(), SizesArrayInit->getType(), 8748 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8749 SizesArrayInit, Name); 8750 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8751 Info.SizesArray = SizesArrayGbl; 8752 } 8753 8754 // The map types are always constant so we don't need to generate code to 8755 // fill arrays. Instead, we create an array constant. 8756 SmallVector<uint64_t, 4> Mapping(CombinedInfo.Types.size(), 0); 8757 llvm::copy(CombinedInfo.Types, Mapping.begin()); 8758 llvm::Constant *MapTypesArrayInit = 8759 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8760 std::string MaptypesName = 8761 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8762 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8763 CGM.getModule(), MapTypesArrayInit->getType(), 8764 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8765 MapTypesArrayInit, MaptypesName); 8766 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8767 Info.MapTypesArray = MapTypesArrayGbl; 8768 8769 // If there's a present map type modifier, it must not be applied to the end 8770 // of a region, so generate a separate map type array in that case. 8771 if (Info.separateBeginEndCalls()) { 8772 bool EndMapTypesDiffer = false; 8773 for (uint64_t &Type : Mapping) { 8774 if (Type & MappableExprsHandler::OMP_MAP_PRESENT) { 8775 Type &= ~MappableExprsHandler::OMP_MAP_PRESENT; 8776 EndMapTypesDiffer = true; 8777 } 8778 } 8779 if (EndMapTypesDiffer) { 8780 MapTypesArrayInit = 8781 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8782 MaptypesName = CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8783 MapTypesArrayGbl = new llvm::GlobalVariable( 8784 CGM.getModule(), MapTypesArrayInit->getType(), 8785 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8786 MapTypesArrayInit, MaptypesName); 8787 MapTypesArrayGbl->setUnnamedAddr( 8788 llvm::GlobalValue::UnnamedAddr::Global); 8789 Info.MapTypesArrayEnd = MapTypesArrayGbl; 8790 } 8791 } 8792 8793 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8794 llvm::Value *BPVal = *CombinedInfo.BasePointers[I]; 8795 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8796 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8797 Info.BasePointersArray, 0, I); 8798 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8799 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8800 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8801 CGF.Builder.CreateStore(BPVal, BPAddr); 8802 8803 if (Info.requiresDevicePointerInfo()) 8804 if (const ValueDecl *DevVD = 8805 CombinedInfo.BasePointers[I].getDevicePtrDecl()) 8806 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8807 8808 llvm::Value *PVal = CombinedInfo.Pointers[I]; 8809 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8810 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8811 Info.PointersArray, 0, I); 8812 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8813 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8814 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8815 CGF.Builder.CreateStore(PVal, PAddr); 8816 8817 if (hasRuntimeEvaluationCaptureSize) { 8818 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8819 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8820 Info.SizesArray, 8821 /*Idx0=*/0, 8822 /*Idx1=*/I); 8823 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8824 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(CombinedInfo.Sizes[I], 8825 CGM.Int64Ty, 8826 /*isSigned=*/true), 8827 SAddr); 8828 } 8829 8830 // Fill up the mapper array. 8831 llvm::Value *MFunc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 8832 if (CombinedInfo.Mappers[I]) { 8833 MFunc = CGM.getOpenMPRuntime().getOrCreateUserDefinedMapperFunc( 8834 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I])); 8835 MFunc = CGF.Builder.CreatePointerCast(MFunc, CGM.VoidPtrTy); 8836 Info.HasMapper = true; 8837 } 8838 Address MAddr = CGF.Builder.CreateConstArrayGEP(MappersArray, I); 8839 CGF.Builder.CreateStore(MFunc, MAddr); 8840 } 8841 } 8842 } 8843 8844 /// Emit the arguments to be passed to the runtime library based on the 8845 /// arrays of base pointers, pointers, sizes, map types, and mappers. If 8846 /// ForEndCall, emit map types to be passed for the end of the region instead of 8847 /// the beginning. 8848 static void emitOffloadingArraysArgument( 8849 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8850 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8851 llvm::Value *&MapTypesArrayArg, llvm::Value *&MappersArrayArg, 8852 CGOpenMPRuntime::TargetDataInfo &Info, bool ForEndCall = false) { 8853 assert((!ForEndCall || Info.separateBeginEndCalls()) && 8854 "expected region end call to runtime only when end call is separate"); 8855 CodeGenModule &CGM = CGF.CGM; 8856 if (Info.NumberOfPtrs) { 8857 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8858 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8859 Info.BasePointersArray, 8860 /*Idx0=*/0, /*Idx1=*/0); 8861 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8862 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8863 Info.PointersArray, 8864 /*Idx0=*/0, 8865 /*Idx1=*/0); 8866 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8867 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8868 /*Idx0=*/0, /*Idx1=*/0); 8869 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8870 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8871 ForEndCall && Info.MapTypesArrayEnd ? Info.MapTypesArrayEnd 8872 : Info.MapTypesArray, 8873 /*Idx0=*/0, 8874 /*Idx1=*/0); 8875 MappersArrayArg = 8876 Info.HasMapper 8877 ? CGF.Builder.CreatePointerCast(Info.MappersArray, CGM.VoidPtrPtrTy) 8878 : llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8879 } else { 8880 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8881 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8882 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8883 MapTypesArrayArg = 8884 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8885 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8886 } 8887 } 8888 8889 /// Check for inner distribute directive. 8890 static const OMPExecutableDirective * 8891 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8892 const auto *CS = D.getInnermostCapturedStmt(); 8893 const auto *Body = 8894 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8895 const Stmt *ChildStmt = 8896 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8897 8898 if (const auto *NestedDir = 8899 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8900 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8901 switch (D.getDirectiveKind()) { 8902 case OMPD_target: 8903 if (isOpenMPDistributeDirective(DKind)) 8904 return NestedDir; 8905 if (DKind == OMPD_teams) { 8906 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8907 /*IgnoreCaptured=*/true); 8908 if (!Body) 8909 return nullptr; 8910 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8911 if (const auto *NND = 8912 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8913 DKind = NND->getDirectiveKind(); 8914 if (isOpenMPDistributeDirective(DKind)) 8915 return NND; 8916 } 8917 } 8918 return nullptr; 8919 case OMPD_target_teams: 8920 if (isOpenMPDistributeDirective(DKind)) 8921 return NestedDir; 8922 return nullptr; 8923 case OMPD_target_parallel: 8924 case OMPD_target_simd: 8925 case OMPD_target_parallel_for: 8926 case OMPD_target_parallel_for_simd: 8927 return nullptr; 8928 case OMPD_target_teams_distribute: 8929 case OMPD_target_teams_distribute_simd: 8930 case OMPD_target_teams_distribute_parallel_for: 8931 case OMPD_target_teams_distribute_parallel_for_simd: 8932 case OMPD_parallel: 8933 case OMPD_for: 8934 case OMPD_parallel_for: 8935 case OMPD_parallel_master: 8936 case OMPD_parallel_sections: 8937 case OMPD_for_simd: 8938 case OMPD_parallel_for_simd: 8939 case OMPD_cancel: 8940 case OMPD_cancellation_point: 8941 case OMPD_ordered: 8942 case OMPD_threadprivate: 8943 case OMPD_allocate: 8944 case OMPD_task: 8945 case OMPD_simd: 8946 case OMPD_sections: 8947 case OMPD_section: 8948 case OMPD_single: 8949 case OMPD_master: 8950 case OMPD_critical: 8951 case OMPD_taskyield: 8952 case OMPD_barrier: 8953 case OMPD_taskwait: 8954 case OMPD_taskgroup: 8955 case OMPD_atomic: 8956 case OMPD_flush: 8957 case OMPD_depobj: 8958 case OMPD_scan: 8959 case OMPD_teams: 8960 case OMPD_target_data: 8961 case OMPD_target_exit_data: 8962 case OMPD_target_enter_data: 8963 case OMPD_distribute: 8964 case OMPD_distribute_simd: 8965 case OMPD_distribute_parallel_for: 8966 case OMPD_distribute_parallel_for_simd: 8967 case OMPD_teams_distribute: 8968 case OMPD_teams_distribute_simd: 8969 case OMPD_teams_distribute_parallel_for: 8970 case OMPD_teams_distribute_parallel_for_simd: 8971 case OMPD_target_update: 8972 case OMPD_declare_simd: 8973 case OMPD_declare_variant: 8974 case OMPD_begin_declare_variant: 8975 case OMPD_end_declare_variant: 8976 case OMPD_declare_target: 8977 case OMPD_end_declare_target: 8978 case OMPD_declare_reduction: 8979 case OMPD_declare_mapper: 8980 case OMPD_taskloop: 8981 case OMPD_taskloop_simd: 8982 case OMPD_master_taskloop: 8983 case OMPD_master_taskloop_simd: 8984 case OMPD_parallel_master_taskloop: 8985 case OMPD_parallel_master_taskloop_simd: 8986 case OMPD_requires: 8987 case OMPD_unknown: 8988 default: 8989 llvm_unreachable("Unexpected directive."); 8990 } 8991 } 8992 8993 return nullptr; 8994 } 8995 8996 /// Emit the user-defined mapper function. The code generation follows the 8997 /// pattern in the example below. 8998 /// \code 8999 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 9000 /// void *base, void *begin, 9001 /// int64_t size, int64_t type) { 9002 /// // Allocate space for an array section first. 9003 /// if (size > 1 && !maptype.IsDelete) 9004 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9005 /// size*sizeof(Ty), clearToFrom(type)); 9006 /// // Map members. 9007 /// for (unsigned i = 0; i < size; i++) { 9008 /// // For each component specified by this mapper: 9009 /// for (auto c : all_components) { 9010 /// if (c.hasMapper()) 9011 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 9012 /// c.arg_type); 9013 /// else 9014 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 9015 /// c.arg_begin, c.arg_size, c.arg_type); 9016 /// } 9017 /// } 9018 /// // Delete the array section. 9019 /// if (size > 1 && maptype.IsDelete) 9020 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9021 /// size*sizeof(Ty), clearToFrom(type)); 9022 /// } 9023 /// \endcode 9024 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 9025 CodeGenFunction *CGF) { 9026 if (UDMMap.count(D) > 0) 9027 return; 9028 ASTContext &C = CGM.getContext(); 9029 QualType Ty = D->getType(); 9030 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 9031 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 9032 auto *MapperVarDecl = 9033 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 9034 SourceLocation Loc = D->getLocation(); 9035 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 9036 9037 // Prepare mapper function arguments and attributes. 9038 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9039 C.VoidPtrTy, ImplicitParamDecl::Other); 9040 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9041 ImplicitParamDecl::Other); 9042 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9043 C.VoidPtrTy, ImplicitParamDecl::Other); 9044 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9045 ImplicitParamDecl::Other); 9046 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9047 ImplicitParamDecl::Other); 9048 FunctionArgList Args; 9049 Args.push_back(&HandleArg); 9050 Args.push_back(&BaseArg); 9051 Args.push_back(&BeginArg); 9052 Args.push_back(&SizeArg); 9053 Args.push_back(&TypeArg); 9054 const CGFunctionInfo &FnInfo = 9055 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 9056 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 9057 SmallString<64> TyStr; 9058 llvm::raw_svector_ostream Out(TyStr); 9059 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 9060 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 9061 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 9062 Name, &CGM.getModule()); 9063 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 9064 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 9065 // Start the mapper function code generation. 9066 CodeGenFunction MapperCGF(CGM); 9067 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 9068 // Compute the starting and end addreses of array elements. 9069 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 9070 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 9071 C.getPointerType(Int64Ty), Loc); 9072 // Convert the size in bytes into the number of array elements. 9073 Size = MapperCGF.Builder.CreateExactUDiv( 9074 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9075 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 9076 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 9077 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 9078 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 9079 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 9080 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 9081 C.getPointerType(Int64Ty), Loc); 9082 // Prepare common arguments for array initiation and deletion. 9083 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 9084 MapperCGF.GetAddrOfLocalVar(&HandleArg), 9085 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9086 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 9087 MapperCGF.GetAddrOfLocalVar(&BaseArg), 9088 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9089 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 9090 MapperCGF.GetAddrOfLocalVar(&BeginArg), 9091 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9092 9093 // Emit array initiation if this is an array section and \p MapType indicates 9094 // that memory allocation is required. 9095 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 9096 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9097 ElementSize, HeadBB, /*IsInit=*/true); 9098 9099 // Emit a for loop to iterate through SizeArg of elements and map all of them. 9100 9101 // Emit the loop header block. 9102 MapperCGF.EmitBlock(HeadBB); 9103 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 9104 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 9105 // Evaluate whether the initial condition is satisfied. 9106 llvm::Value *IsEmpty = 9107 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 9108 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 9109 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 9110 9111 // Emit the loop body block. 9112 MapperCGF.EmitBlock(BodyBB); 9113 llvm::BasicBlock *LastBB = BodyBB; 9114 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 9115 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 9116 PtrPHI->addIncoming(PtrBegin, EntryBB); 9117 Address PtrCurrent = 9118 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 9119 .getAlignment() 9120 .alignmentOfArrayElement(ElementSize)); 9121 // Privatize the declared variable of mapper to be the current array element. 9122 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 9123 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 9124 return MapperCGF 9125 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 9126 .getAddress(MapperCGF); 9127 }); 9128 (void)Scope.Privatize(); 9129 9130 // Get map clause information. Fill up the arrays with all mapped variables. 9131 MappableExprsHandler::MapCombinedInfoTy Info; 9132 MappableExprsHandler MEHandler(*D, MapperCGF); 9133 MEHandler.generateAllInfoForMapper(Info); 9134 9135 // Call the runtime API __tgt_mapper_num_components to get the number of 9136 // pre-existing components. 9137 llvm::Value *OffloadingArgs[] = {Handle}; 9138 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 9139 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 9140 OMPRTL___tgt_mapper_num_components), 9141 OffloadingArgs); 9142 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 9143 PreviousSize, 9144 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 9145 9146 // Fill up the runtime mapper handle for all components. 9147 for (unsigned I = 0; I < Info.BasePointers.size(); ++I) { 9148 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 9149 *Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9150 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9151 Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9152 llvm::Value *CurSizeArg = Info.Sizes[I]; 9153 9154 // Extract the MEMBER_OF field from the map type. 9155 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 9156 MapperCGF.EmitBlock(MemberBB); 9157 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(Info.Types[I]); 9158 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 9159 OriMapType, 9160 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 9161 llvm::BasicBlock *MemberCombineBB = 9162 MapperCGF.createBasicBlock("omp.member.combine"); 9163 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 9164 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 9165 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 9166 // Add the number of pre-existing components to the MEMBER_OF field if it 9167 // is valid. 9168 MapperCGF.EmitBlock(MemberCombineBB); 9169 llvm::Value *CombinedMember = 9170 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9171 // Do nothing if it is not a member of previous components. 9172 MapperCGF.EmitBlock(TypeBB); 9173 llvm::PHINode *MemberMapType = 9174 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 9175 MemberMapType->addIncoming(OriMapType, MemberBB); 9176 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 9177 9178 // Combine the map type inherited from user-defined mapper with that 9179 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9180 // bits of the \a MapType, which is the input argument of the mapper 9181 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9182 // bits of MemberMapType. 9183 // [OpenMP 5.0], 1.2.6. map-type decay. 9184 // | alloc | to | from | tofrom | release | delete 9185 // ---------------------------------------------------------- 9186 // alloc | alloc | alloc | alloc | alloc | release | delete 9187 // to | alloc | to | alloc | to | release | delete 9188 // from | alloc | alloc | from | from | release | delete 9189 // tofrom | alloc | to | from | tofrom | release | delete 9190 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9191 MapType, 9192 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9193 MappableExprsHandler::OMP_MAP_FROM)); 9194 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9195 llvm::BasicBlock *AllocElseBB = 9196 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9197 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9198 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9199 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9200 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9201 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9202 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9203 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9204 MapperCGF.EmitBlock(AllocBB); 9205 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9206 MemberMapType, 9207 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9208 MappableExprsHandler::OMP_MAP_FROM))); 9209 MapperCGF.Builder.CreateBr(EndBB); 9210 MapperCGF.EmitBlock(AllocElseBB); 9211 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9212 LeftToFrom, 9213 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9214 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9215 // In case of to, clear OMP_MAP_FROM. 9216 MapperCGF.EmitBlock(ToBB); 9217 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9218 MemberMapType, 9219 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9220 MapperCGF.Builder.CreateBr(EndBB); 9221 MapperCGF.EmitBlock(ToElseBB); 9222 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9223 LeftToFrom, 9224 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9225 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9226 // In case of from, clear OMP_MAP_TO. 9227 MapperCGF.EmitBlock(FromBB); 9228 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9229 MemberMapType, 9230 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9231 // In case of tofrom, do nothing. 9232 MapperCGF.EmitBlock(EndBB); 9233 LastBB = EndBB; 9234 llvm::PHINode *CurMapType = 9235 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9236 CurMapType->addIncoming(AllocMapType, AllocBB); 9237 CurMapType->addIncoming(ToMapType, ToBB); 9238 CurMapType->addIncoming(FromMapType, FromBB); 9239 CurMapType->addIncoming(MemberMapType, ToElseBB); 9240 9241 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9242 CurSizeArg, CurMapType}; 9243 if (Info.Mappers[I]) { 9244 // Call the corresponding mapper function. 9245 llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc( 9246 cast<OMPDeclareMapperDecl>(Info.Mappers[I])); 9247 assert(MapperFunc && "Expect a valid mapper function is available."); 9248 MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs); 9249 } else { 9250 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9251 // data structure. 9252 MapperCGF.EmitRuntimeCall( 9253 OMPBuilder.getOrCreateRuntimeFunction( 9254 CGM.getModule(), OMPRTL___tgt_push_mapper_component), 9255 OffloadingArgs); 9256 } 9257 } 9258 9259 // Update the pointer to point to the next element that needs to be mapped, 9260 // and check whether we have mapped all elements. 9261 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9262 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9263 PtrPHI->addIncoming(PtrNext, LastBB); 9264 llvm::Value *IsDone = 9265 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9266 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9267 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9268 9269 MapperCGF.EmitBlock(ExitBB); 9270 // Emit array deletion if this is an array section and \p MapType indicates 9271 // that deletion is required. 9272 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9273 ElementSize, DoneBB, /*IsInit=*/false); 9274 9275 // Emit the function exit block. 9276 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9277 MapperCGF.FinishFunction(); 9278 UDMMap.try_emplace(D, Fn); 9279 if (CGF) { 9280 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9281 Decls.second.push_back(D); 9282 } 9283 } 9284 9285 /// Emit the array initialization or deletion portion for user-defined mapper 9286 /// code generation. First, it evaluates whether an array section is mapped and 9287 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9288 /// true, and \a MapType indicates to not delete this array, array 9289 /// initialization code is generated. If \a IsInit is false, and \a MapType 9290 /// indicates to not this array, array deletion code is generated. 9291 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9292 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9293 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9294 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9295 StringRef Prefix = IsInit ? ".init" : ".del"; 9296 9297 // Evaluate if this is an array section. 9298 llvm::BasicBlock *IsDeleteBB = 9299 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"})); 9300 llvm::BasicBlock *BodyBB = 9301 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 9302 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9303 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9304 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9305 9306 // Evaluate if we are going to delete this section. 9307 MapperCGF.EmitBlock(IsDeleteBB); 9308 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9309 MapType, 9310 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9311 llvm::Value *DeleteCond; 9312 if (IsInit) { 9313 DeleteCond = MapperCGF.Builder.CreateIsNull( 9314 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9315 } else { 9316 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9317 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9318 } 9319 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9320 9321 MapperCGF.EmitBlock(BodyBB); 9322 // Get the array size by multiplying element size and element number (i.e., \p 9323 // Size). 9324 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9325 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9326 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9327 // memory allocation/deletion purpose only. 9328 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9329 MapType, 9330 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9331 MappableExprsHandler::OMP_MAP_FROM))); 9332 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9333 // data structure. 9334 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9335 MapperCGF.EmitRuntimeCall( 9336 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 9337 OMPRTL___tgt_push_mapper_component), 9338 OffloadingArgs); 9339 } 9340 9341 llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc( 9342 const OMPDeclareMapperDecl *D) { 9343 auto I = UDMMap.find(D); 9344 if (I != UDMMap.end()) 9345 return I->second; 9346 emitUserDefinedMapper(D); 9347 return UDMMap.lookup(D); 9348 } 9349 9350 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9351 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9352 llvm::Value *DeviceID, 9353 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9354 const OMPLoopDirective &D)> 9355 SizeEmitter) { 9356 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9357 const OMPExecutableDirective *TD = &D; 9358 // Get nested teams distribute kind directive, if any. 9359 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9360 TD = getNestedDistributeDirective(CGM.getContext(), D); 9361 if (!TD) 9362 return; 9363 const auto *LD = cast<OMPLoopDirective>(TD); 9364 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9365 PrePostActionTy &) { 9366 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9367 llvm::Value *Args[] = {DeviceID, NumIterations}; 9368 CGF.EmitRuntimeCall( 9369 OMPBuilder.getOrCreateRuntimeFunction( 9370 CGM.getModule(), OMPRTL___kmpc_push_target_tripcount), 9371 Args); 9372 } 9373 }; 9374 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9375 } 9376 9377 void CGOpenMPRuntime::emitTargetCall( 9378 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9379 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9380 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 9381 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9382 const OMPLoopDirective &D)> 9383 SizeEmitter) { 9384 if (!CGF.HaveInsertPoint()) 9385 return; 9386 9387 assert(OutlinedFn && "Invalid outlined function!"); 9388 9389 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9390 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9391 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9392 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9393 PrePostActionTy &) { 9394 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9395 }; 9396 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9397 9398 CodeGenFunction::OMPTargetDataInfo InputInfo; 9399 llvm::Value *MapTypesArray = nullptr; 9400 // Fill up the pointer arrays and transfer execution to the device. 9401 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9402 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9403 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9404 if (Device.getInt() == OMPC_DEVICE_ancestor) { 9405 // Reverse offloading is not supported, so just execute on the host. 9406 if (RequiresOuterTask) { 9407 CapturedVars.clear(); 9408 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9409 } 9410 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9411 return; 9412 } 9413 9414 // On top of the arrays that were filled up, the target offloading call 9415 // takes as arguments the device id as well as the host pointer. The host 9416 // pointer is used by the runtime library to identify the current target 9417 // region, so it only has to be unique and not necessarily point to 9418 // anything. It could be the pointer to the outlined function that 9419 // implements the target region, but we aren't using that so that the 9420 // compiler doesn't need to keep that, and could therefore inline the host 9421 // function if proven worthwhile during optimization. 9422 9423 // From this point on, we need to have an ID of the target region defined. 9424 assert(OutlinedFnID && "Invalid outlined function ID!"); 9425 9426 // Emit device ID if any. 9427 llvm::Value *DeviceID; 9428 if (Device.getPointer()) { 9429 assert((Device.getInt() == OMPC_DEVICE_unknown || 9430 Device.getInt() == OMPC_DEVICE_device_num) && 9431 "Expected device_num modifier."); 9432 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer()); 9433 DeviceID = 9434 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true); 9435 } else { 9436 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9437 } 9438 9439 // Emit the number of elements in the offloading arrays. 9440 llvm::Value *PointerNum = 9441 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9442 9443 // Return value of the runtime offloading call. 9444 llvm::Value *Return; 9445 9446 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9447 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9448 9449 // Emit tripcount for the target loop-based directive. 9450 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9451 9452 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9453 // The target region is an outlined function launched by the runtime 9454 // via calls __tgt_target() or __tgt_target_teams(). 9455 // 9456 // __tgt_target() launches a target region with one team and one thread, 9457 // executing a serial region. This master thread may in turn launch 9458 // more threads within its team upon encountering a parallel region, 9459 // however, no additional teams can be launched on the device. 9460 // 9461 // __tgt_target_teams() launches a target region with one or more teams, 9462 // each with one or more threads. This call is required for target 9463 // constructs such as: 9464 // 'target teams' 9465 // 'target' / 'teams' 9466 // 'target teams distribute parallel for' 9467 // 'target parallel' 9468 // and so on. 9469 // 9470 // Note that on the host and CPU targets, the runtime implementation of 9471 // these calls simply call the outlined function without forking threads. 9472 // The outlined functions themselves have runtime calls to 9473 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9474 // the compiler in emitTeamsCall() and emitParallelCall(). 9475 // 9476 // In contrast, on the NVPTX target, the implementation of 9477 // __tgt_target_teams() launches a GPU kernel with the requested number 9478 // of teams and threads so no additional calls to the runtime are required. 9479 if (NumTeams) { 9480 // If we have NumTeams defined this means that we have an enclosed teams 9481 // region. Therefore we also expect to have NumThreads defined. These two 9482 // values should be defined in the presence of a teams directive, 9483 // regardless of having any clauses associated. If the user is using teams 9484 // but no clauses, these two values will be the default that should be 9485 // passed to the runtime library - a 32-bit integer with the value zero. 9486 assert(NumThreads && "Thread limit expression should be available along " 9487 "with number of teams."); 9488 llvm::Value *OffloadingArgs[] = {DeviceID, 9489 OutlinedFnID, 9490 PointerNum, 9491 InputInfo.BasePointersArray.getPointer(), 9492 InputInfo.PointersArray.getPointer(), 9493 InputInfo.SizesArray.getPointer(), 9494 MapTypesArray, 9495 InputInfo.MappersArray.getPointer(), 9496 NumTeams, 9497 NumThreads}; 9498 Return = CGF.EmitRuntimeCall( 9499 OMPBuilder.getOrCreateRuntimeFunction( 9500 CGM.getModule(), HasNowait 9501 ? OMPRTL___tgt_target_teams_nowait_mapper 9502 : OMPRTL___tgt_target_teams_mapper), 9503 OffloadingArgs); 9504 } else { 9505 llvm::Value *OffloadingArgs[] = {DeviceID, 9506 OutlinedFnID, 9507 PointerNum, 9508 InputInfo.BasePointersArray.getPointer(), 9509 InputInfo.PointersArray.getPointer(), 9510 InputInfo.SizesArray.getPointer(), 9511 MapTypesArray, 9512 InputInfo.MappersArray.getPointer()}; 9513 Return = CGF.EmitRuntimeCall( 9514 OMPBuilder.getOrCreateRuntimeFunction( 9515 CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper 9516 : OMPRTL___tgt_target_mapper), 9517 OffloadingArgs); 9518 } 9519 9520 // Check the error code and execute the host version if required. 9521 llvm::BasicBlock *OffloadFailedBlock = 9522 CGF.createBasicBlock("omp_offload.failed"); 9523 llvm::BasicBlock *OffloadContBlock = 9524 CGF.createBasicBlock("omp_offload.cont"); 9525 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9526 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9527 9528 CGF.EmitBlock(OffloadFailedBlock); 9529 if (RequiresOuterTask) { 9530 CapturedVars.clear(); 9531 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9532 } 9533 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9534 CGF.EmitBranch(OffloadContBlock); 9535 9536 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9537 }; 9538 9539 // Notify that the host version must be executed. 9540 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9541 RequiresOuterTask](CodeGenFunction &CGF, 9542 PrePostActionTy &) { 9543 if (RequiresOuterTask) { 9544 CapturedVars.clear(); 9545 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9546 } 9547 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9548 }; 9549 9550 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9551 &CapturedVars, RequiresOuterTask, 9552 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9553 // Fill up the arrays with all the captured variables. 9554 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 9555 9556 // Get mappable expression information. 9557 MappableExprsHandler MEHandler(D, CGF); 9558 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9559 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet; 9560 9561 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9562 auto CV = CapturedVars.begin(); 9563 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9564 CE = CS.capture_end(); 9565 CI != CE; ++CI, ++RI, ++CV) { 9566 MappableExprsHandler::MapCombinedInfoTy CurInfo; 9567 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9568 9569 // VLA sizes are passed to the outlined region by copy and do not have map 9570 // information associated. 9571 if (CI->capturesVariableArrayType()) { 9572 CurInfo.BasePointers.push_back(*CV); 9573 CurInfo.Pointers.push_back(*CV); 9574 CurInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 9575 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9576 // Copy to the device as an argument. No need to retrieve it. 9577 CurInfo.Types.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9578 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9579 MappableExprsHandler::OMP_MAP_IMPLICIT); 9580 CurInfo.Mappers.push_back(nullptr); 9581 } else { 9582 // If we have any information in the map clause, we use it, otherwise we 9583 // just do a default mapping. 9584 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct); 9585 if (!CI->capturesThis()) 9586 MappedVarSet.insert(CI->getCapturedVar()); 9587 else 9588 MappedVarSet.insert(nullptr); 9589 if (CurInfo.BasePointers.empty()) 9590 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo); 9591 // Generate correct mapping for variables captured by reference in 9592 // lambdas. 9593 if (CI->capturesVariable()) 9594 MEHandler.generateInfoForLambdaCaptures(CI->getCapturedVar(), *CV, 9595 CurInfo, LambdaPointers); 9596 } 9597 // We expect to have at least an element of information for this capture. 9598 assert(!CurInfo.BasePointers.empty() && 9599 "Non-existing map pointer for capture!"); 9600 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() && 9601 CurInfo.BasePointers.size() == CurInfo.Sizes.size() && 9602 CurInfo.BasePointers.size() == CurInfo.Types.size() && 9603 CurInfo.BasePointers.size() == CurInfo.Mappers.size() && 9604 "Inconsistent map information sizes!"); 9605 9606 // If there is an entry in PartialStruct it means we have a struct with 9607 // individual members mapped. Emit an extra combined entry. 9608 if (PartialStruct.Base.isValid()) 9609 MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct); 9610 9611 // We need to append the results of this capture to what we already have. 9612 CombinedInfo.append(CurInfo); 9613 } 9614 // Adjust MEMBER_OF flags for the lambdas captures. 9615 MEHandler.adjustMemberOfForLambdaCaptures( 9616 LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers, 9617 CombinedInfo.Types); 9618 // Map any list items in a map clause that were not captures because they 9619 // weren't referenced within the construct. 9620 MEHandler.generateAllInfo(CombinedInfo, /*NotTargetParams=*/true, 9621 MappedVarSet); 9622 9623 TargetDataInfo Info; 9624 // Fill up the arrays and create the arguments. 9625 emitOffloadingArrays(CGF, CombinedInfo, Info); 9626 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9627 Info.PointersArray, Info.SizesArray, 9628 Info.MapTypesArray, Info.MappersArray, Info); 9629 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9630 InputInfo.BasePointersArray = 9631 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9632 InputInfo.PointersArray = 9633 Address(Info.PointersArray, CGM.getPointerAlign()); 9634 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9635 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 9636 MapTypesArray = Info.MapTypesArray; 9637 if (RequiresOuterTask) 9638 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9639 else 9640 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9641 }; 9642 9643 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9644 CodeGenFunction &CGF, PrePostActionTy &) { 9645 if (RequiresOuterTask) { 9646 CodeGenFunction::OMPTargetDataInfo InputInfo; 9647 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9648 } else { 9649 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9650 } 9651 }; 9652 9653 // If we have a target function ID it means that we need to support 9654 // offloading, otherwise, just execute on the host. We need to execute on host 9655 // regardless of the conditional in the if clause if, e.g., the user do not 9656 // specify target triples. 9657 if (OutlinedFnID) { 9658 if (IfCond) { 9659 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9660 } else { 9661 RegionCodeGenTy ThenRCG(TargetThenGen); 9662 ThenRCG(CGF); 9663 } 9664 } else { 9665 RegionCodeGenTy ElseRCG(TargetElseGen); 9666 ElseRCG(CGF); 9667 } 9668 } 9669 9670 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9671 StringRef ParentName) { 9672 if (!S) 9673 return; 9674 9675 // Codegen OMP target directives that offload compute to the device. 9676 bool RequiresDeviceCodegen = 9677 isa<OMPExecutableDirective>(S) && 9678 isOpenMPTargetExecutionDirective( 9679 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9680 9681 if (RequiresDeviceCodegen) { 9682 const auto &E = *cast<OMPExecutableDirective>(S); 9683 unsigned DeviceID; 9684 unsigned FileID; 9685 unsigned Line; 9686 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9687 FileID, Line); 9688 9689 // Is this a target region that should not be emitted as an entry point? If 9690 // so just signal we are done with this target region. 9691 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9692 ParentName, Line)) 9693 return; 9694 9695 switch (E.getDirectiveKind()) { 9696 case OMPD_target: 9697 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9698 cast<OMPTargetDirective>(E)); 9699 break; 9700 case OMPD_target_parallel: 9701 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9702 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9703 break; 9704 case OMPD_target_teams: 9705 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9706 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9707 break; 9708 case OMPD_target_teams_distribute: 9709 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9710 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9711 break; 9712 case OMPD_target_teams_distribute_simd: 9713 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9714 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9715 break; 9716 case OMPD_target_parallel_for: 9717 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9718 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9719 break; 9720 case OMPD_target_parallel_for_simd: 9721 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9722 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9723 break; 9724 case OMPD_target_simd: 9725 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9726 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9727 break; 9728 case OMPD_target_teams_distribute_parallel_for: 9729 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9730 CGM, ParentName, 9731 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9732 break; 9733 case OMPD_target_teams_distribute_parallel_for_simd: 9734 CodeGenFunction:: 9735 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9736 CGM, ParentName, 9737 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9738 break; 9739 case OMPD_parallel: 9740 case OMPD_for: 9741 case OMPD_parallel_for: 9742 case OMPD_parallel_master: 9743 case OMPD_parallel_sections: 9744 case OMPD_for_simd: 9745 case OMPD_parallel_for_simd: 9746 case OMPD_cancel: 9747 case OMPD_cancellation_point: 9748 case OMPD_ordered: 9749 case OMPD_threadprivate: 9750 case OMPD_allocate: 9751 case OMPD_task: 9752 case OMPD_simd: 9753 case OMPD_sections: 9754 case OMPD_section: 9755 case OMPD_single: 9756 case OMPD_master: 9757 case OMPD_critical: 9758 case OMPD_taskyield: 9759 case OMPD_barrier: 9760 case OMPD_taskwait: 9761 case OMPD_taskgroup: 9762 case OMPD_atomic: 9763 case OMPD_flush: 9764 case OMPD_depobj: 9765 case OMPD_scan: 9766 case OMPD_teams: 9767 case OMPD_target_data: 9768 case OMPD_target_exit_data: 9769 case OMPD_target_enter_data: 9770 case OMPD_distribute: 9771 case OMPD_distribute_simd: 9772 case OMPD_distribute_parallel_for: 9773 case OMPD_distribute_parallel_for_simd: 9774 case OMPD_teams_distribute: 9775 case OMPD_teams_distribute_simd: 9776 case OMPD_teams_distribute_parallel_for: 9777 case OMPD_teams_distribute_parallel_for_simd: 9778 case OMPD_target_update: 9779 case OMPD_declare_simd: 9780 case OMPD_declare_variant: 9781 case OMPD_begin_declare_variant: 9782 case OMPD_end_declare_variant: 9783 case OMPD_declare_target: 9784 case OMPD_end_declare_target: 9785 case OMPD_declare_reduction: 9786 case OMPD_declare_mapper: 9787 case OMPD_taskloop: 9788 case OMPD_taskloop_simd: 9789 case OMPD_master_taskloop: 9790 case OMPD_master_taskloop_simd: 9791 case OMPD_parallel_master_taskloop: 9792 case OMPD_parallel_master_taskloop_simd: 9793 case OMPD_requires: 9794 case OMPD_unknown: 9795 default: 9796 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9797 } 9798 return; 9799 } 9800 9801 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9802 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9803 return; 9804 9805 scanForTargetRegionsFunctions(E->getRawStmt(), ParentName); 9806 return; 9807 } 9808 9809 // If this is a lambda function, look into its body. 9810 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9811 S = L->getBody(); 9812 9813 // Keep looking for target regions recursively. 9814 for (const Stmt *II : S->children()) 9815 scanForTargetRegionsFunctions(II, ParentName); 9816 } 9817 9818 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9819 // If emitting code for the host, we do not process FD here. Instead we do 9820 // the normal code generation. 9821 if (!CGM.getLangOpts().OpenMPIsDevice) { 9822 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9823 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9824 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9825 // Do not emit device_type(nohost) functions for the host. 9826 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9827 return true; 9828 } 9829 return false; 9830 } 9831 9832 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9833 // Try to detect target regions in the function. 9834 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9835 StringRef Name = CGM.getMangledName(GD); 9836 scanForTargetRegionsFunctions(FD->getBody(), Name); 9837 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9838 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9839 // Do not emit device_type(nohost) functions for the host. 9840 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9841 return true; 9842 } 9843 9844 // Do not to emit function if it is not marked as declare target. 9845 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9846 AlreadyEmittedTargetDecls.count(VD) == 0; 9847 } 9848 9849 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9850 if (!CGM.getLangOpts().OpenMPIsDevice) 9851 return false; 9852 9853 // Check if there are Ctors/Dtors in this declaration and look for target 9854 // regions in it. We use the complete variant to produce the kernel name 9855 // mangling. 9856 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9857 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9858 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9859 StringRef ParentName = 9860 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9861 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9862 } 9863 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9864 StringRef ParentName = 9865 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9866 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9867 } 9868 } 9869 9870 // Do not to emit variable if it is not marked as declare target. 9871 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9872 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9873 cast<VarDecl>(GD.getDecl())); 9874 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9875 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9876 HasRequiresUnifiedSharedMemory)) { 9877 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9878 return true; 9879 } 9880 return false; 9881 } 9882 9883 llvm::Constant * 9884 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9885 const VarDecl *VD) { 9886 assert(VD->getType().isConstant(CGM.getContext()) && 9887 "Expected constant variable."); 9888 StringRef VarName; 9889 llvm::Constant *Addr; 9890 llvm::GlobalValue::LinkageTypes Linkage; 9891 QualType Ty = VD->getType(); 9892 SmallString<128> Buffer; 9893 { 9894 unsigned DeviceID; 9895 unsigned FileID; 9896 unsigned Line; 9897 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9898 FileID, Line); 9899 llvm::raw_svector_ostream OS(Buffer); 9900 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9901 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9902 VarName = OS.str(); 9903 } 9904 Linkage = llvm::GlobalValue::InternalLinkage; 9905 Addr = 9906 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9907 getDefaultFirstprivateAddressSpace()); 9908 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9909 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9910 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9911 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9912 VarName, Addr, VarSize, 9913 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9914 return Addr; 9915 } 9916 9917 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9918 llvm::Constant *Addr) { 9919 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9920 !CGM.getLangOpts().OpenMPIsDevice) 9921 return; 9922 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9923 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9924 if (!Res) { 9925 if (CGM.getLangOpts().OpenMPIsDevice) { 9926 // Register non-target variables being emitted in device code (debug info 9927 // may cause this). 9928 StringRef VarName = CGM.getMangledName(VD); 9929 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9930 } 9931 return; 9932 } 9933 // Register declare target variables. 9934 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9935 StringRef VarName; 9936 CharUnits VarSize; 9937 llvm::GlobalValue::LinkageTypes Linkage; 9938 9939 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9940 !HasRequiresUnifiedSharedMemory) { 9941 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9942 VarName = CGM.getMangledName(VD); 9943 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9944 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9945 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9946 } else { 9947 VarSize = CharUnits::Zero(); 9948 } 9949 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9950 // Temp solution to prevent optimizations of the internal variables. 9951 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9952 std::string RefName = getName({VarName, "ref"}); 9953 if (!CGM.GetGlobalValue(RefName)) { 9954 llvm::Constant *AddrRef = 9955 getOrCreateInternalVariable(Addr->getType(), RefName); 9956 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9957 GVAddrRef->setConstant(/*Val=*/true); 9958 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9959 GVAddrRef->setInitializer(Addr); 9960 CGM.addCompilerUsedGlobal(GVAddrRef); 9961 } 9962 } 9963 } else { 9964 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9965 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9966 HasRequiresUnifiedSharedMemory)) && 9967 "Declare target attribute must link or to with unified memory."); 9968 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9969 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9970 else 9971 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9972 9973 if (CGM.getLangOpts().OpenMPIsDevice) { 9974 VarName = Addr->getName(); 9975 Addr = nullptr; 9976 } else { 9977 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9978 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9979 } 9980 VarSize = CGM.getPointerSize(); 9981 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9982 } 9983 9984 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9985 VarName, Addr, VarSize, Flags, Linkage); 9986 } 9987 9988 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9989 if (isa<FunctionDecl>(GD.getDecl()) || 9990 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9991 return emitTargetFunctions(GD); 9992 9993 return emitTargetGlobalVariable(GD); 9994 } 9995 9996 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9997 for (const VarDecl *VD : DeferredGlobalVariables) { 9998 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9999 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10000 if (!Res) 10001 continue; 10002 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10003 !HasRequiresUnifiedSharedMemory) { 10004 CGM.EmitGlobal(VD); 10005 } else { 10006 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 10007 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10008 HasRequiresUnifiedSharedMemory)) && 10009 "Expected link clause or to clause with unified memory."); 10010 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 10011 } 10012 } 10013 } 10014 10015 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 10016 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 10017 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 10018 " Expected target-based directive."); 10019 } 10020 10021 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 10022 for (const OMPClause *Clause : D->clauselists()) { 10023 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 10024 HasRequiresUnifiedSharedMemory = true; 10025 } else if (const auto *AC = 10026 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 10027 switch (AC->getAtomicDefaultMemOrderKind()) { 10028 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 10029 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 10030 break; 10031 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 10032 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 10033 break; 10034 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 10035 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 10036 break; 10037 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 10038 break; 10039 } 10040 } 10041 } 10042 } 10043 10044 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 10045 return RequiresAtomicOrdering; 10046 } 10047 10048 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 10049 LangAS &AS) { 10050 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 10051 return false; 10052 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 10053 switch(A->getAllocatorType()) { 10054 case OMPAllocateDeclAttr::OMPNullMemAlloc: 10055 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 10056 // Not supported, fallback to the default mem space. 10057 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 10058 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 10059 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 10060 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 10061 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 10062 case OMPAllocateDeclAttr::OMPConstMemAlloc: 10063 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 10064 AS = LangAS::Default; 10065 return true; 10066 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 10067 llvm_unreachable("Expected predefined allocator for the variables with the " 10068 "static storage."); 10069 } 10070 return false; 10071 } 10072 10073 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 10074 return HasRequiresUnifiedSharedMemory; 10075 } 10076 10077 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 10078 CodeGenModule &CGM) 10079 : CGM(CGM) { 10080 if (CGM.getLangOpts().OpenMPIsDevice) { 10081 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 10082 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 10083 } 10084 } 10085 10086 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 10087 if (CGM.getLangOpts().OpenMPIsDevice) 10088 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 10089 } 10090 10091 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 10092 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 10093 return true; 10094 10095 const auto *D = cast<FunctionDecl>(GD.getDecl()); 10096 // Do not to emit function if it is marked as declare target as it was already 10097 // emitted. 10098 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 10099 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 10100 if (auto *F = dyn_cast_or_null<llvm::Function>( 10101 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 10102 return !F->isDeclaration(); 10103 return false; 10104 } 10105 return true; 10106 } 10107 10108 return !AlreadyEmittedTargetDecls.insert(D).second; 10109 } 10110 10111 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 10112 // If we don't have entries or if we are emitting code for the device, we 10113 // don't need to do anything. 10114 if (CGM.getLangOpts().OMPTargetTriples.empty() || 10115 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 10116 (OffloadEntriesInfoManager.empty() && 10117 !HasEmittedDeclareTargetRegion && 10118 !HasEmittedTargetRegion)) 10119 return nullptr; 10120 10121 // Create and register the function that handles the requires directives. 10122 ASTContext &C = CGM.getContext(); 10123 10124 llvm::Function *RequiresRegFn; 10125 { 10126 CodeGenFunction CGF(CGM); 10127 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 10128 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 10129 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 10130 RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI); 10131 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 10132 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 10133 // TODO: check for other requires clauses. 10134 // The requires directive takes effect only when a target region is 10135 // present in the compilation unit. Otherwise it is ignored and not 10136 // passed to the runtime. This avoids the runtime from throwing an error 10137 // for mismatching requires clauses across compilation units that don't 10138 // contain at least 1 target region. 10139 assert((HasEmittedTargetRegion || 10140 HasEmittedDeclareTargetRegion || 10141 !OffloadEntriesInfoManager.empty()) && 10142 "Target or declare target region expected."); 10143 if (HasRequiresUnifiedSharedMemory) 10144 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 10145 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 10146 CGM.getModule(), OMPRTL___tgt_register_requires), 10147 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 10148 CGF.FinishFunction(); 10149 } 10150 return RequiresRegFn; 10151 } 10152 10153 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 10154 const OMPExecutableDirective &D, 10155 SourceLocation Loc, 10156 llvm::Function *OutlinedFn, 10157 ArrayRef<llvm::Value *> CapturedVars) { 10158 if (!CGF.HaveInsertPoint()) 10159 return; 10160 10161 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10162 CodeGenFunction::RunCleanupsScope Scope(CGF); 10163 10164 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 10165 llvm::Value *Args[] = { 10166 RTLoc, 10167 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 10168 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 10169 llvm::SmallVector<llvm::Value *, 16> RealArgs; 10170 RealArgs.append(std::begin(Args), std::end(Args)); 10171 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 10172 10173 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 10174 CGM.getModule(), OMPRTL___kmpc_fork_teams); 10175 CGF.EmitRuntimeCall(RTLFn, RealArgs); 10176 } 10177 10178 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 10179 const Expr *NumTeams, 10180 const Expr *ThreadLimit, 10181 SourceLocation Loc) { 10182 if (!CGF.HaveInsertPoint()) 10183 return; 10184 10185 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10186 10187 llvm::Value *NumTeamsVal = 10188 NumTeams 10189 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 10190 CGF.CGM.Int32Ty, /* isSigned = */ true) 10191 : CGF.Builder.getInt32(0); 10192 10193 llvm::Value *ThreadLimitVal = 10194 ThreadLimit 10195 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 10196 CGF.CGM.Int32Ty, /* isSigned = */ true) 10197 : CGF.Builder.getInt32(0); 10198 10199 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 10200 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 10201 ThreadLimitVal}; 10202 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 10203 CGM.getModule(), OMPRTL___kmpc_push_num_teams), 10204 PushNumTeamsArgs); 10205 } 10206 10207 void CGOpenMPRuntime::emitTargetDataCalls( 10208 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10209 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 10210 if (!CGF.HaveInsertPoint()) 10211 return; 10212 10213 // Action used to replace the default codegen action and turn privatization 10214 // off. 10215 PrePostActionTy NoPrivAction; 10216 10217 // Generate the code for the opening of the data environment. Capture all the 10218 // arguments of the runtime call by reference because they are used in the 10219 // closing of the region. 10220 auto &&BeginThenGen = [this, &D, Device, &Info, 10221 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 10222 // Fill up the arrays with all the mapped variables. 10223 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 10224 10225 // Get map clause information. 10226 MappableExprsHandler MEHandler(D, CGF); 10227 MEHandler.generateAllInfo(CombinedInfo); 10228 10229 // Fill up the arrays and create the arguments. 10230 emitOffloadingArrays(CGF, CombinedInfo, Info); 10231 10232 llvm::Value *BasePointersArrayArg = nullptr; 10233 llvm::Value *PointersArrayArg = nullptr; 10234 llvm::Value *SizesArrayArg = nullptr; 10235 llvm::Value *MapTypesArrayArg = nullptr; 10236 llvm::Value *MappersArrayArg = nullptr; 10237 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10238 SizesArrayArg, MapTypesArrayArg, 10239 MappersArrayArg, Info, /*ForEndCall=*/false); 10240 10241 // Emit device ID if any. 10242 llvm::Value *DeviceID = nullptr; 10243 if (Device) { 10244 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10245 CGF.Int64Ty, /*isSigned=*/true); 10246 } else { 10247 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10248 } 10249 10250 // Emit the number of elements in the offloading arrays. 10251 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10252 10253 llvm::Value *OffloadingArgs[] = { 10254 DeviceID, PointerNum, BasePointersArrayArg, PointersArrayArg, 10255 SizesArrayArg, MapTypesArrayArg, MappersArrayArg}; 10256 CGF.EmitRuntimeCall( 10257 OMPBuilder.getOrCreateRuntimeFunction( 10258 CGM.getModule(), OMPRTL___tgt_target_data_begin_mapper), 10259 OffloadingArgs); 10260 10261 // If device pointer privatization is required, emit the body of the region 10262 // here. It will have to be duplicated: with and without privatization. 10263 if (!Info.CaptureDeviceAddrMap.empty()) 10264 CodeGen(CGF); 10265 }; 10266 10267 // Generate code for the closing of the data region. 10268 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10269 PrePostActionTy &) { 10270 assert(Info.isValid() && "Invalid data environment closing arguments."); 10271 10272 llvm::Value *BasePointersArrayArg = nullptr; 10273 llvm::Value *PointersArrayArg = nullptr; 10274 llvm::Value *SizesArrayArg = nullptr; 10275 llvm::Value *MapTypesArrayArg = nullptr; 10276 llvm::Value *MappersArrayArg = nullptr; 10277 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10278 SizesArrayArg, MapTypesArrayArg, 10279 MappersArrayArg, Info, /*ForEndCall=*/true); 10280 10281 // Emit device ID if any. 10282 llvm::Value *DeviceID = nullptr; 10283 if (Device) { 10284 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10285 CGF.Int64Ty, /*isSigned=*/true); 10286 } else { 10287 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10288 } 10289 10290 // Emit the number of elements in the offloading arrays. 10291 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10292 10293 llvm::Value *OffloadingArgs[] = { 10294 DeviceID, PointerNum, BasePointersArrayArg, PointersArrayArg, 10295 SizesArrayArg, MapTypesArrayArg, MappersArrayArg}; 10296 CGF.EmitRuntimeCall( 10297 OMPBuilder.getOrCreateRuntimeFunction( 10298 CGM.getModule(), OMPRTL___tgt_target_data_end_mapper), 10299 OffloadingArgs); 10300 }; 10301 10302 // If we need device pointer privatization, we need to emit the body of the 10303 // region with no privatization in the 'else' branch of the conditional. 10304 // Otherwise, we don't have to do anything. 10305 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10306 PrePostActionTy &) { 10307 if (!Info.CaptureDeviceAddrMap.empty()) { 10308 CodeGen.setAction(NoPrivAction); 10309 CodeGen(CGF); 10310 } 10311 }; 10312 10313 // We don't have to do anything to close the region if the if clause evaluates 10314 // to false. 10315 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10316 10317 if (IfCond) { 10318 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10319 } else { 10320 RegionCodeGenTy RCG(BeginThenGen); 10321 RCG(CGF); 10322 } 10323 10324 // If we don't require privatization of device pointers, we emit the body in 10325 // between the runtime calls. This avoids duplicating the body code. 10326 if (Info.CaptureDeviceAddrMap.empty()) { 10327 CodeGen.setAction(NoPrivAction); 10328 CodeGen(CGF); 10329 } 10330 10331 if (IfCond) { 10332 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10333 } else { 10334 RegionCodeGenTy RCG(EndThenGen); 10335 RCG(CGF); 10336 } 10337 } 10338 10339 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10340 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10341 const Expr *Device) { 10342 if (!CGF.HaveInsertPoint()) 10343 return; 10344 10345 assert((isa<OMPTargetEnterDataDirective>(D) || 10346 isa<OMPTargetExitDataDirective>(D) || 10347 isa<OMPTargetUpdateDirective>(D)) && 10348 "Expecting either target enter, exit data, or update directives."); 10349 10350 CodeGenFunction::OMPTargetDataInfo InputInfo; 10351 llvm::Value *MapTypesArray = nullptr; 10352 // Generate the code for the opening of the data environment. 10353 auto &&ThenGen = [this, &D, Device, &InputInfo, 10354 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10355 // Emit device ID if any. 10356 llvm::Value *DeviceID = nullptr; 10357 if (Device) { 10358 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10359 CGF.Int64Ty, /*isSigned=*/true); 10360 } else { 10361 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10362 } 10363 10364 // Emit the number of elements in the offloading arrays. 10365 llvm::Constant *PointerNum = 10366 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10367 10368 llvm::Value *OffloadingArgs[] = {DeviceID, 10369 PointerNum, 10370 InputInfo.BasePointersArray.getPointer(), 10371 InputInfo.PointersArray.getPointer(), 10372 InputInfo.SizesArray.getPointer(), 10373 MapTypesArray, 10374 InputInfo.MappersArray.getPointer()}; 10375 10376 // Select the right runtime function call for each standalone 10377 // directive. 10378 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10379 RuntimeFunction RTLFn; 10380 switch (D.getDirectiveKind()) { 10381 case OMPD_target_enter_data: 10382 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper 10383 : OMPRTL___tgt_target_data_begin_mapper; 10384 break; 10385 case OMPD_target_exit_data: 10386 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper 10387 : OMPRTL___tgt_target_data_end_mapper; 10388 break; 10389 case OMPD_target_update: 10390 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper 10391 : OMPRTL___tgt_target_data_update_mapper; 10392 break; 10393 case OMPD_parallel: 10394 case OMPD_for: 10395 case OMPD_parallel_for: 10396 case OMPD_parallel_master: 10397 case OMPD_parallel_sections: 10398 case OMPD_for_simd: 10399 case OMPD_parallel_for_simd: 10400 case OMPD_cancel: 10401 case OMPD_cancellation_point: 10402 case OMPD_ordered: 10403 case OMPD_threadprivate: 10404 case OMPD_allocate: 10405 case OMPD_task: 10406 case OMPD_simd: 10407 case OMPD_sections: 10408 case OMPD_section: 10409 case OMPD_single: 10410 case OMPD_master: 10411 case OMPD_critical: 10412 case OMPD_taskyield: 10413 case OMPD_barrier: 10414 case OMPD_taskwait: 10415 case OMPD_taskgroup: 10416 case OMPD_atomic: 10417 case OMPD_flush: 10418 case OMPD_depobj: 10419 case OMPD_scan: 10420 case OMPD_teams: 10421 case OMPD_target_data: 10422 case OMPD_distribute: 10423 case OMPD_distribute_simd: 10424 case OMPD_distribute_parallel_for: 10425 case OMPD_distribute_parallel_for_simd: 10426 case OMPD_teams_distribute: 10427 case OMPD_teams_distribute_simd: 10428 case OMPD_teams_distribute_parallel_for: 10429 case OMPD_teams_distribute_parallel_for_simd: 10430 case OMPD_declare_simd: 10431 case OMPD_declare_variant: 10432 case OMPD_begin_declare_variant: 10433 case OMPD_end_declare_variant: 10434 case OMPD_declare_target: 10435 case OMPD_end_declare_target: 10436 case OMPD_declare_reduction: 10437 case OMPD_declare_mapper: 10438 case OMPD_taskloop: 10439 case OMPD_taskloop_simd: 10440 case OMPD_master_taskloop: 10441 case OMPD_master_taskloop_simd: 10442 case OMPD_parallel_master_taskloop: 10443 case OMPD_parallel_master_taskloop_simd: 10444 case OMPD_target: 10445 case OMPD_target_simd: 10446 case OMPD_target_teams_distribute: 10447 case OMPD_target_teams_distribute_simd: 10448 case OMPD_target_teams_distribute_parallel_for: 10449 case OMPD_target_teams_distribute_parallel_for_simd: 10450 case OMPD_target_teams: 10451 case OMPD_target_parallel: 10452 case OMPD_target_parallel_for: 10453 case OMPD_target_parallel_for_simd: 10454 case OMPD_requires: 10455 case OMPD_unknown: 10456 default: 10457 llvm_unreachable("Unexpected standalone target data directive."); 10458 break; 10459 } 10460 CGF.EmitRuntimeCall( 10461 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), RTLFn), 10462 OffloadingArgs); 10463 }; 10464 10465 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10466 CodeGenFunction &CGF, PrePostActionTy &) { 10467 // Fill up the arrays with all the mapped variables. 10468 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 10469 10470 // Get map clause information. 10471 MappableExprsHandler MEHandler(D, CGF); 10472 MEHandler.generateAllInfo(CombinedInfo); 10473 10474 TargetDataInfo Info; 10475 // Fill up the arrays and create the arguments. 10476 emitOffloadingArrays(CGF, CombinedInfo, Info); 10477 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10478 Info.PointersArray, Info.SizesArray, 10479 Info.MapTypesArray, Info.MappersArray, Info); 10480 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10481 InputInfo.BasePointersArray = 10482 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10483 InputInfo.PointersArray = 10484 Address(Info.PointersArray, CGM.getPointerAlign()); 10485 InputInfo.SizesArray = 10486 Address(Info.SizesArray, CGM.getPointerAlign()); 10487 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 10488 MapTypesArray = Info.MapTypesArray; 10489 if (D.hasClausesOfKind<OMPDependClause>()) 10490 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10491 else 10492 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10493 }; 10494 10495 if (IfCond) { 10496 emitIfClause(CGF, IfCond, TargetThenGen, 10497 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10498 } else { 10499 RegionCodeGenTy ThenRCG(TargetThenGen); 10500 ThenRCG(CGF); 10501 } 10502 } 10503 10504 namespace { 10505 /// Kind of parameter in a function with 'declare simd' directive. 10506 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10507 /// Attribute set of the parameter. 10508 struct ParamAttrTy { 10509 ParamKindTy Kind = Vector; 10510 llvm::APSInt StrideOrArg; 10511 llvm::APSInt Alignment; 10512 }; 10513 } // namespace 10514 10515 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10516 ArrayRef<ParamAttrTy> ParamAttrs) { 10517 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10518 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10519 // of that clause. The VLEN value must be power of 2. 10520 // In other case the notion of the function`s "characteristic data type" (CDT) 10521 // is used to compute the vector length. 10522 // CDT is defined in the following order: 10523 // a) For non-void function, the CDT is the return type. 10524 // b) If the function has any non-uniform, non-linear parameters, then the 10525 // CDT is the type of the first such parameter. 10526 // c) If the CDT determined by a) or b) above is struct, union, or class 10527 // type which is pass-by-value (except for the type that maps to the 10528 // built-in complex data type), the characteristic data type is int. 10529 // d) If none of the above three cases is applicable, the CDT is int. 10530 // The VLEN is then determined based on the CDT and the size of vector 10531 // register of that ISA for which current vector version is generated. The 10532 // VLEN is computed using the formula below: 10533 // VLEN = sizeof(vector_register) / sizeof(CDT), 10534 // where vector register size specified in section 3.2.1 Registers and the 10535 // Stack Frame of original AMD64 ABI document. 10536 QualType RetType = FD->getReturnType(); 10537 if (RetType.isNull()) 10538 return 0; 10539 ASTContext &C = FD->getASTContext(); 10540 QualType CDT; 10541 if (!RetType.isNull() && !RetType->isVoidType()) { 10542 CDT = RetType; 10543 } else { 10544 unsigned Offset = 0; 10545 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10546 if (ParamAttrs[Offset].Kind == Vector) 10547 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10548 ++Offset; 10549 } 10550 if (CDT.isNull()) { 10551 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10552 if (ParamAttrs[I + Offset].Kind == Vector) { 10553 CDT = FD->getParamDecl(I)->getType(); 10554 break; 10555 } 10556 } 10557 } 10558 } 10559 if (CDT.isNull()) 10560 CDT = C.IntTy; 10561 CDT = CDT->getCanonicalTypeUnqualified(); 10562 if (CDT->isRecordType() || CDT->isUnionType()) 10563 CDT = C.IntTy; 10564 return C.getTypeSize(CDT); 10565 } 10566 10567 static void 10568 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10569 const llvm::APSInt &VLENVal, 10570 ArrayRef<ParamAttrTy> ParamAttrs, 10571 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10572 struct ISADataTy { 10573 char ISA; 10574 unsigned VecRegSize; 10575 }; 10576 ISADataTy ISAData[] = { 10577 { 10578 'b', 128 10579 }, // SSE 10580 { 10581 'c', 256 10582 }, // AVX 10583 { 10584 'd', 256 10585 }, // AVX2 10586 { 10587 'e', 512 10588 }, // AVX512 10589 }; 10590 llvm::SmallVector<char, 2> Masked; 10591 switch (State) { 10592 case OMPDeclareSimdDeclAttr::BS_Undefined: 10593 Masked.push_back('N'); 10594 Masked.push_back('M'); 10595 break; 10596 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10597 Masked.push_back('N'); 10598 break; 10599 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10600 Masked.push_back('M'); 10601 break; 10602 } 10603 for (char Mask : Masked) { 10604 for (const ISADataTy &Data : ISAData) { 10605 SmallString<256> Buffer; 10606 llvm::raw_svector_ostream Out(Buffer); 10607 Out << "_ZGV" << Data.ISA << Mask; 10608 if (!VLENVal) { 10609 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10610 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10611 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10612 } else { 10613 Out << VLENVal; 10614 } 10615 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10616 switch (ParamAttr.Kind){ 10617 case LinearWithVarStride: 10618 Out << 's' << ParamAttr.StrideOrArg; 10619 break; 10620 case Linear: 10621 Out << 'l'; 10622 if (ParamAttr.StrideOrArg != 1) 10623 Out << ParamAttr.StrideOrArg; 10624 break; 10625 case Uniform: 10626 Out << 'u'; 10627 break; 10628 case Vector: 10629 Out << 'v'; 10630 break; 10631 } 10632 if (!!ParamAttr.Alignment) 10633 Out << 'a' << ParamAttr.Alignment; 10634 } 10635 Out << '_' << Fn->getName(); 10636 Fn->addFnAttr(Out.str()); 10637 } 10638 } 10639 } 10640 10641 // This are the Functions that are needed to mangle the name of the 10642 // vector functions generated by the compiler, according to the rules 10643 // defined in the "Vector Function ABI specifications for AArch64", 10644 // available at 10645 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10646 10647 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10648 /// 10649 /// TODO: Need to implement the behavior for reference marked with a 10650 /// var or no linear modifiers (1.b in the section). For this, we 10651 /// need to extend ParamKindTy to support the linear modifiers. 10652 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10653 QT = QT.getCanonicalType(); 10654 10655 if (QT->isVoidType()) 10656 return false; 10657 10658 if (Kind == ParamKindTy::Uniform) 10659 return false; 10660 10661 if (Kind == ParamKindTy::Linear) 10662 return false; 10663 10664 // TODO: Handle linear references with modifiers 10665 10666 if (Kind == ParamKindTy::LinearWithVarStride) 10667 return false; 10668 10669 return true; 10670 } 10671 10672 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10673 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10674 QT = QT.getCanonicalType(); 10675 unsigned Size = C.getTypeSize(QT); 10676 10677 // Only scalars and complex within 16 bytes wide set PVB to true. 10678 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10679 return false; 10680 10681 if (QT->isFloatingType()) 10682 return true; 10683 10684 if (QT->isIntegerType()) 10685 return true; 10686 10687 if (QT->isPointerType()) 10688 return true; 10689 10690 // TODO: Add support for complex types (section 3.1.2, item 2). 10691 10692 return false; 10693 } 10694 10695 /// Computes the lane size (LS) of a return type or of an input parameter, 10696 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10697 /// TODO: Add support for references, section 3.2.1, item 1. 10698 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10699 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10700 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10701 if (getAArch64PBV(PTy, C)) 10702 return C.getTypeSize(PTy); 10703 } 10704 if (getAArch64PBV(QT, C)) 10705 return C.getTypeSize(QT); 10706 10707 return C.getTypeSize(C.getUIntPtrType()); 10708 } 10709 10710 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10711 // signature of the scalar function, as defined in 3.2.2 of the 10712 // AAVFABI. 10713 static std::tuple<unsigned, unsigned, bool> 10714 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10715 QualType RetType = FD->getReturnType().getCanonicalType(); 10716 10717 ASTContext &C = FD->getASTContext(); 10718 10719 bool OutputBecomesInput = false; 10720 10721 llvm::SmallVector<unsigned, 8> Sizes; 10722 if (!RetType->isVoidType()) { 10723 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10724 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10725 OutputBecomesInput = true; 10726 } 10727 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10728 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10729 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10730 } 10731 10732 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10733 // The LS of a function parameter / return value can only be a power 10734 // of 2, starting from 8 bits, up to 128. 10735 assert(std::all_of(Sizes.begin(), Sizes.end(), 10736 [](unsigned Size) { 10737 return Size == 8 || Size == 16 || Size == 32 || 10738 Size == 64 || Size == 128; 10739 }) && 10740 "Invalid size"); 10741 10742 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10743 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10744 OutputBecomesInput); 10745 } 10746 10747 /// Mangle the parameter part of the vector function name according to 10748 /// their OpenMP classification. The mangling function is defined in 10749 /// section 3.5 of the AAVFABI. 10750 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10751 SmallString<256> Buffer; 10752 llvm::raw_svector_ostream Out(Buffer); 10753 for (const auto &ParamAttr : ParamAttrs) { 10754 switch (ParamAttr.Kind) { 10755 case LinearWithVarStride: 10756 Out << "ls" << ParamAttr.StrideOrArg; 10757 break; 10758 case Linear: 10759 Out << 'l'; 10760 // Don't print the step value if it is not present or if it is 10761 // equal to 1. 10762 if (ParamAttr.StrideOrArg != 1) 10763 Out << ParamAttr.StrideOrArg; 10764 break; 10765 case Uniform: 10766 Out << 'u'; 10767 break; 10768 case Vector: 10769 Out << 'v'; 10770 break; 10771 } 10772 10773 if (!!ParamAttr.Alignment) 10774 Out << 'a' << ParamAttr.Alignment; 10775 } 10776 10777 return std::string(Out.str()); 10778 } 10779 10780 // Function used to add the attribute. The parameter `VLEN` is 10781 // templated to allow the use of "x" when targeting scalable functions 10782 // for SVE. 10783 template <typename T> 10784 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10785 char ISA, StringRef ParSeq, 10786 StringRef MangledName, bool OutputBecomesInput, 10787 llvm::Function *Fn) { 10788 SmallString<256> Buffer; 10789 llvm::raw_svector_ostream Out(Buffer); 10790 Out << Prefix << ISA << LMask << VLEN; 10791 if (OutputBecomesInput) 10792 Out << "v"; 10793 Out << ParSeq << "_" << MangledName; 10794 Fn->addFnAttr(Out.str()); 10795 } 10796 10797 // Helper function to generate the Advanced SIMD names depending on 10798 // the value of the NDS when simdlen is not present. 10799 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10800 StringRef Prefix, char ISA, 10801 StringRef ParSeq, StringRef MangledName, 10802 bool OutputBecomesInput, 10803 llvm::Function *Fn) { 10804 switch (NDS) { 10805 case 8: 10806 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10807 OutputBecomesInput, Fn); 10808 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10809 OutputBecomesInput, Fn); 10810 break; 10811 case 16: 10812 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10813 OutputBecomesInput, Fn); 10814 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10815 OutputBecomesInput, Fn); 10816 break; 10817 case 32: 10818 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10819 OutputBecomesInput, Fn); 10820 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10821 OutputBecomesInput, Fn); 10822 break; 10823 case 64: 10824 case 128: 10825 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10826 OutputBecomesInput, Fn); 10827 break; 10828 default: 10829 llvm_unreachable("Scalar type is too wide."); 10830 } 10831 } 10832 10833 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10834 static void emitAArch64DeclareSimdFunction( 10835 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10836 ArrayRef<ParamAttrTy> ParamAttrs, 10837 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10838 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10839 10840 // Get basic data for building the vector signature. 10841 const auto Data = getNDSWDS(FD, ParamAttrs); 10842 const unsigned NDS = std::get<0>(Data); 10843 const unsigned WDS = std::get<1>(Data); 10844 const bool OutputBecomesInput = std::get<2>(Data); 10845 10846 // Check the values provided via `simdlen` by the user. 10847 // 1. A `simdlen(1)` doesn't produce vector signatures, 10848 if (UserVLEN == 1) { 10849 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10850 DiagnosticsEngine::Warning, 10851 "The clause simdlen(1) has no effect when targeting aarch64."); 10852 CGM.getDiags().Report(SLoc, DiagID); 10853 return; 10854 } 10855 10856 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10857 // Advanced SIMD output. 10858 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10859 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10860 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10861 "power of 2 when targeting Advanced SIMD."); 10862 CGM.getDiags().Report(SLoc, DiagID); 10863 return; 10864 } 10865 10866 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10867 // limits. 10868 if (ISA == 's' && UserVLEN != 0) { 10869 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10870 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10871 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10872 "lanes in the architectural constraints " 10873 "for SVE (min is 128-bit, max is " 10874 "2048-bit, by steps of 128-bit)"); 10875 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10876 return; 10877 } 10878 } 10879 10880 // Sort out parameter sequence. 10881 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10882 StringRef Prefix = "_ZGV"; 10883 // Generate simdlen from user input (if any). 10884 if (UserVLEN) { 10885 if (ISA == 's') { 10886 // SVE generates only a masked function. 10887 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10888 OutputBecomesInput, Fn); 10889 } else { 10890 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10891 // Advanced SIMD generates one or two functions, depending on 10892 // the `[not]inbranch` clause. 10893 switch (State) { 10894 case OMPDeclareSimdDeclAttr::BS_Undefined: 10895 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10896 OutputBecomesInput, Fn); 10897 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10898 OutputBecomesInput, Fn); 10899 break; 10900 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10901 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10902 OutputBecomesInput, Fn); 10903 break; 10904 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10905 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10906 OutputBecomesInput, Fn); 10907 break; 10908 } 10909 } 10910 } else { 10911 // If no user simdlen is provided, follow the AAVFABI rules for 10912 // generating the vector length. 10913 if (ISA == 's') { 10914 // SVE, section 3.4.1, item 1. 10915 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10916 OutputBecomesInput, Fn); 10917 } else { 10918 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10919 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10920 // two vector names depending on the use of the clause 10921 // `[not]inbranch`. 10922 switch (State) { 10923 case OMPDeclareSimdDeclAttr::BS_Undefined: 10924 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10925 OutputBecomesInput, Fn); 10926 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10927 OutputBecomesInput, Fn); 10928 break; 10929 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10930 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10931 OutputBecomesInput, Fn); 10932 break; 10933 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10934 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10935 OutputBecomesInput, Fn); 10936 break; 10937 } 10938 } 10939 } 10940 } 10941 10942 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10943 llvm::Function *Fn) { 10944 ASTContext &C = CGM.getContext(); 10945 FD = FD->getMostRecentDecl(); 10946 // Map params to their positions in function decl. 10947 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10948 if (isa<CXXMethodDecl>(FD)) 10949 ParamPositions.try_emplace(FD, 0); 10950 unsigned ParamPos = ParamPositions.size(); 10951 for (const ParmVarDecl *P : FD->parameters()) { 10952 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10953 ++ParamPos; 10954 } 10955 while (FD) { 10956 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10957 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10958 // Mark uniform parameters. 10959 for (const Expr *E : Attr->uniforms()) { 10960 E = E->IgnoreParenImpCasts(); 10961 unsigned Pos; 10962 if (isa<CXXThisExpr>(E)) { 10963 Pos = ParamPositions[FD]; 10964 } else { 10965 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10966 ->getCanonicalDecl(); 10967 Pos = ParamPositions[PVD]; 10968 } 10969 ParamAttrs[Pos].Kind = Uniform; 10970 } 10971 // Get alignment info. 10972 auto NI = Attr->alignments_begin(); 10973 for (const Expr *E : Attr->aligneds()) { 10974 E = E->IgnoreParenImpCasts(); 10975 unsigned Pos; 10976 QualType ParmTy; 10977 if (isa<CXXThisExpr>(E)) { 10978 Pos = ParamPositions[FD]; 10979 ParmTy = E->getType(); 10980 } else { 10981 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10982 ->getCanonicalDecl(); 10983 Pos = ParamPositions[PVD]; 10984 ParmTy = PVD->getType(); 10985 } 10986 ParamAttrs[Pos].Alignment = 10987 (*NI) 10988 ? (*NI)->EvaluateKnownConstInt(C) 10989 : llvm::APSInt::getUnsigned( 10990 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10991 .getQuantity()); 10992 ++NI; 10993 } 10994 // Mark linear parameters. 10995 auto SI = Attr->steps_begin(); 10996 auto MI = Attr->modifiers_begin(); 10997 for (const Expr *E : Attr->linears()) { 10998 E = E->IgnoreParenImpCasts(); 10999 unsigned Pos; 11000 // Rescaling factor needed to compute the linear parameter 11001 // value in the mangled name. 11002 unsigned PtrRescalingFactor = 1; 11003 if (isa<CXXThisExpr>(E)) { 11004 Pos = ParamPositions[FD]; 11005 } else { 11006 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11007 ->getCanonicalDecl(); 11008 Pos = ParamPositions[PVD]; 11009 if (auto *P = dyn_cast<PointerType>(PVD->getType())) 11010 PtrRescalingFactor = CGM.getContext() 11011 .getTypeSizeInChars(P->getPointeeType()) 11012 .getQuantity(); 11013 } 11014 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 11015 ParamAttr.Kind = Linear; 11016 // Assuming a stride of 1, for `linear` without modifiers. 11017 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1); 11018 if (*SI) { 11019 Expr::EvalResult Result; 11020 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 11021 if (const auto *DRE = 11022 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 11023 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 11024 ParamAttr.Kind = LinearWithVarStride; 11025 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 11026 ParamPositions[StridePVD->getCanonicalDecl()]); 11027 } 11028 } 11029 } else { 11030 ParamAttr.StrideOrArg = Result.Val.getInt(); 11031 } 11032 } 11033 // If we are using a linear clause on a pointer, we need to 11034 // rescale the value of linear_step with the byte size of the 11035 // pointee type. 11036 if (Linear == ParamAttr.Kind) 11037 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor; 11038 ++SI; 11039 ++MI; 11040 } 11041 llvm::APSInt VLENVal; 11042 SourceLocation ExprLoc; 11043 const Expr *VLENExpr = Attr->getSimdlen(); 11044 if (VLENExpr) { 11045 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 11046 ExprLoc = VLENExpr->getExprLoc(); 11047 } 11048 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 11049 if (CGM.getTriple().isX86()) { 11050 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 11051 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 11052 unsigned VLEN = VLENVal.getExtValue(); 11053 StringRef MangledName = Fn->getName(); 11054 if (CGM.getTarget().hasFeature("sve")) 11055 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11056 MangledName, 's', 128, Fn, ExprLoc); 11057 if (CGM.getTarget().hasFeature("neon")) 11058 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11059 MangledName, 'n', 128, Fn, ExprLoc); 11060 } 11061 } 11062 FD = FD->getPreviousDecl(); 11063 } 11064 } 11065 11066 namespace { 11067 /// Cleanup action for doacross support. 11068 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 11069 public: 11070 static const int DoacrossFinArgs = 2; 11071 11072 private: 11073 llvm::FunctionCallee RTLFn; 11074 llvm::Value *Args[DoacrossFinArgs]; 11075 11076 public: 11077 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 11078 ArrayRef<llvm::Value *> CallArgs) 11079 : RTLFn(RTLFn) { 11080 assert(CallArgs.size() == DoacrossFinArgs); 11081 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11082 } 11083 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11084 if (!CGF.HaveInsertPoint()) 11085 return; 11086 CGF.EmitRuntimeCall(RTLFn, Args); 11087 } 11088 }; 11089 } // namespace 11090 11091 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11092 const OMPLoopDirective &D, 11093 ArrayRef<Expr *> NumIterations) { 11094 if (!CGF.HaveInsertPoint()) 11095 return; 11096 11097 ASTContext &C = CGM.getContext(); 11098 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 11099 RecordDecl *RD; 11100 if (KmpDimTy.isNull()) { 11101 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 11102 // kmp_int64 lo; // lower 11103 // kmp_int64 up; // upper 11104 // kmp_int64 st; // stride 11105 // }; 11106 RD = C.buildImplicitRecord("kmp_dim"); 11107 RD->startDefinition(); 11108 addFieldToRecordDecl(C, RD, Int64Ty); 11109 addFieldToRecordDecl(C, RD, Int64Ty); 11110 addFieldToRecordDecl(C, RD, Int64Ty); 11111 RD->completeDefinition(); 11112 KmpDimTy = C.getRecordType(RD); 11113 } else { 11114 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 11115 } 11116 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 11117 QualType ArrayTy = 11118 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 11119 11120 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 11121 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 11122 enum { LowerFD = 0, UpperFD, StrideFD }; 11123 // Fill dims with data. 11124 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 11125 LValue DimsLVal = CGF.MakeAddrLValue( 11126 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 11127 // dims.upper = num_iterations; 11128 LValue UpperLVal = CGF.EmitLValueForField( 11129 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 11130 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 11131 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(), 11132 Int64Ty, NumIterations[I]->getExprLoc()); 11133 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 11134 // dims.stride = 1; 11135 LValue StrideLVal = CGF.EmitLValueForField( 11136 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 11137 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 11138 StrideLVal); 11139 } 11140 11141 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 11142 // kmp_int32 num_dims, struct kmp_dim * dims); 11143 llvm::Value *Args[] = { 11144 emitUpdateLocation(CGF, D.getBeginLoc()), 11145 getThreadID(CGF, D.getBeginLoc()), 11146 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 11147 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11148 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 11149 CGM.VoidPtrTy)}; 11150 11151 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11152 CGM.getModule(), OMPRTL___kmpc_doacross_init); 11153 CGF.EmitRuntimeCall(RTLFn, Args); 11154 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 11155 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 11156 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11157 CGM.getModule(), OMPRTL___kmpc_doacross_fini); 11158 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11159 llvm::makeArrayRef(FiniArgs)); 11160 } 11161 11162 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11163 const OMPDependClause *C) { 11164 QualType Int64Ty = 11165 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 11166 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 11167 QualType ArrayTy = CGM.getContext().getConstantArrayType( 11168 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 11169 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 11170 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 11171 const Expr *CounterVal = C->getLoopData(I); 11172 assert(CounterVal); 11173 llvm::Value *CntVal = CGF.EmitScalarConversion( 11174 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 11175 CounterVal->getExprLoc()); 11176 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 11177 /*Volatile=*/false, Int64Ty); 11178 } 11179 llvm::Value *Args[] = { 11180 emitUpdateLocation(CGF, C->getBeginLoc()), 11181 getThreadID(CGF, C->getBeginLoc()), 11182 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 11183 llvm::FunctionCallee RTLFn; 11184 if (C->getDependencyKind() == OMPC_DEPEND_source) { 11185 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 11186 OMPRTL___kmpc_doacross_post); 11187 } else { 11188 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 11189 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 11190 OMPRTL___kmpc_doacross_wait); 11191 } 11192 CGF.EmitRuntimeCall(RTLFn, Args); 11193 } 11194 11195 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 11196 llvm::FunctionCallee Callee, 11197 ArrayRef<llvm::Value *> Args) const { 11198 assert(Loc.isValid() && "Outlined function call location must be valid."); 11199 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 11200 11201 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 11202 if (Fn->doesNotThrow()) { 11203 CGF.EmitNounwindRuntimeCall(Fn, Args); 11204 return; 11205 } 11206 } 11207 CGF.EmitRuntimeCall(Callee, Args); 11208 } 11209 11210 void CGOpenMPRuntime::emitOutlinedFunctionCall( 11211 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 11212 ArrayRef<llvm::Value *> Args) const { 11213 emitCall(CGF, Loc, OutlinedFn, Args); 11214 } 11215 11216 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 11217 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 11218 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 11219 HasEmittedDeclareTargetRegion = true; 11220 } 11221 11222 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 11223 const VarDecl *NativeParam, 11224 const VarDecl *TargetParam) const { 11225 return CGF.GetAddrOfLocalVar(NativeParam); 11226 } 11227 11228 namespace { 11229 /// Cleanup action for allocate support. 11230 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 11231 public: 11232 static const int CleanupArgs = 3; 11233 11234 private: 11235 llvm::FunctionCallee RTLFn; 11236 llvm::Value *Args[CleanupArgs]; 11237 11238 public: 11239 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 11240 ArrayRef<llvm::Value *> CallArgs) 11241 : RTLFn(RTLFn) { 11242 assert(CallArgs.size() == CleanupArgs && 11243 "Size of arguments does not match."); 11244 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11245 } 11246 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11247 if (!CGF.HaveInsertPoint()) 11248 return; 11249 CGF.EmitRuntimeCall(RTLFn, Args); 11250 } 11251 }; 11252 } // namespace 11253 11254 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11255 const VarDecl *VD) { 11256 if (!VD) 11257 return Address::invalid(); 11258 const VarDecl *CVD = VD->getCanonicalDecl(); 11259 if (CVD->hasAttr<OMPAllocateDeclAttr>()) { 11260 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 11261 // Use the default allocation. 11262 if ((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc || 11263 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) && 11264 !AA->getAllocator()) 11265 return Address::invalid(); 11266 llvm::Value *Size; 11267 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11268 if (CVD->getType()->isVariablyModifiedType()) { 11269 Size = CGF.getTypeSize(CVD->getType()); 11270 // Align the size: ((size + align - 1) / align) * align 11271 Size = CGF.Builder.CreateNUWAdd( 11272 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11273 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11274 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11275 } else { 11276 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11277 Size = CGM.getSize(Sz.alignTo(Align)); 11278 } 11279 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11280 assert(AA->getAllocator() && 11281 "Expected allocator expression for non-default allocator."); 11282 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11283 // According to the standard, the original allocator type is a enum 11284 // (integer). Convert to pointer type, if required. 11285 if (Allocator->getType()->isIntegerTy()) 11286 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11287 else if (Allocator->getType()->isPointerTy()) 11288 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11289 Allocator, CGM.VoidPtrTy); 11290 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11291 11292 llvm::Value *Addr = 11293 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 11294 CGM.getModule(), OMPRTL___kmpc_alloc), 11295 Args, getName({CVD->getName(), ".void.addr"})); 11296 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11297 Allocator}; 11298 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11299 CGM.getModule(), OMPRTL___kmpc_free); 11300 11301 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11302 llvm::makeArrayRef(FiniArgs)); 11303 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11304 Addr, 11305 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11306 getName({CVD->getName(), ".addr"})); 11307 return Address(Addr, Align); 11308 } 11309 if (UntiedLocalVarsStack.empty()) 11310 return Address::invalid(); 11311 const UntiedLocalVarsAddressesMap &UntiedData = UntiedLocalVarsStack.back(); 11312 auto It = UntiedData.find(VD); 11313 if (It == UntiedData.end()) 11314 return Address::invalid(); 11315 11316 return It->second; 11317 } 11318 11319 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 11320 CodeGenModule &CGM, const OMPLoopDirective &S) 11321 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 11322 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11323 if (!NeedToPush) 11324 return; 11325 NontemporalDeclsSet &DS = 11326 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 11327 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 11328 for (const Stmt *Ref : C->private_refs()) { 11329 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 11330 const ValueDecl *VD; 11331 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 11332 VD = DRE->getDecl(); 11333 } else { 11334 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 11335 assert((ME->isImplicitCXXThis() || 11336 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 11337 "Expected member of current class."); 11338 VD = ME->getMemberDecl(); 11339 } 11340 DS.insert(VD); 11341 } 11342 } 11343 } 11344 11345 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 11346 if (!NeedToPush) 11347 return; 11348 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 11349 } 11350 11351 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII( 11352 CodeGenModule &CGM, 11353 const llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, Address> &LocalVars) 11354 : CGM(CGM), NeedToPush(!LocalVars.empty()) { 11355 if (!NeedToPush) 11356 return; 11357 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars); 11358 } 11359 11360 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::~UntiedTaskLocalDeclsRAII() { 11361 if (!NeedToPush) 11362 return; 11363 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back(); 11364 } 11365 11366 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 11367 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11368 11369 return llvm::any_of( 11370 CGM.getOpenMPRuntime().NontemporalDeclsStack, 11371 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 11372 } 11373 11374 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 11375 const OMPExecutableDirective &S, 11376 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 11377 const { 11378 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 11379 // Vars in target/task regions must be excluded completely. 11380 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 11381 isOpenMPTaskingDirective(S.getDirectiveKind())) { 11382 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11383 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 11384 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 11385 for (const CapturedStmt::Capture &Cap : CS->captures()) { 11386 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 11387 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 11388 } 11389 } 11390 // Exclude vars in private clauses. 11391 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 11392 for (const Expr *Ref : C->varlists()) { 11393 if (!Ref->getType()->isScalarType()) 11394 continue; 11395 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11396 if (!DRE) 11397 continue; 11398 NeedToCheckForLPCs.insert(DRE->getDecl()); 11399 } 11400 } 11401 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 11402 for (const Expr *Ref : C->varlists()) { 11403 if (!Ref->getType()->isScalarType()) 11404 continue; 11405 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11406 if (!DRE) 11407 continue; 11408 NeedToCheckForLPCs.insert(DRE->getDecl()); 11409 } 11410 } 11411 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11412 for (const Expr *Ref : C->varlists()) { 11413 if (!Ref->getType()->isScalarType()) 11414 continue; 11415 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11416 if (!DRE) 11417 continue; 11418 NeedToCheckForLPCs.insert(DRE->getDecl()); 11419 } 11420 } 11421 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 11422 for (const Expr *Ref : C->varlists()) { 11423 if (!Ref->getType()->isScalarType()) 11424 continue; 11425 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11426 if (!DRE) 11427 continue; 11428 NeedToCheckForLPCs.insert(DRE->getDecl()); 11429 } 11430 } 11431 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 11432 for (const Expr *Ref : C->varlists()) { 11433 if (!Ref->getType()->isScalarType()) 11434 continue; 11435 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11436 if (!DRE) 11437 continue; 11438 NeedToCheckForLPCs.insert(DRE->getDecl()); 11439 } 11440 } 11441 for (const Decl *VD : NeedToCheckForLPCs) { 11442 for (const LastprivateConditionalData &Data : 11443 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 11444 if (Data.DeclToUniqueName.count(VD) > 0) { 11445 if (!Data.Disabled) 11446 NeedToAddForLPCsAsDisabled.insert(VD); 11447 break; 11448 } 11449 } 11450 } 11451 } 11452 11453 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11454 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 11455 : CGM(CGF.CGM), 11456 Action((CGM.getLangOpts().OpenMP >= 50 && 11457 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 11458 [](const OMPLastprivateClause *C) { 11459 return C->getKind() == 11460 OMPC_LASTPRIVATE_conditional; 11461 })) 11462 ? ActionToDo::PushAsLastprivateConditional 11463 : ActionToDo::DoNotPush) { 11464 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11465 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 11466 return; 11467 assert(Action == ActionToDo::PushAsLastprivateConditional && 11468 "Expected a push action."); 11469 LastprivateConditionalData &Data = 11470 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11471 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11472 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 11473 continue; 11474 11475 for (const Expr *Ref : C->varlists()) { 11476 Data.DeclToUniqueName.insert(std::make_pair( 11477 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 11478 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 11479 } 11480 } 11481 Data.IVLVal = IVLVal; 11482 Data.Fn = CGF.CurFn; 11483 } 11484 11485 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11486 CodeGenFunction &CGF, const OMPExecutableDirective &S) 11487 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 11488 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11489 if (CGM.getLangOpts().OpenMP < 50) 11490 return; 11491 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 11492 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 11493 if (!NeedToAddForLPCsAsDisabled.empty()) { 11494 Action = ActionToDo::DisableLastprivateConditional; 11495 LastprivateConditionalData &Data = 11496 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11497 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 11498 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 11499 Data.Fn = CGF.CurFn; 11500 Data.Disabled = true; 11501 } 11502 } 11503 11504 CGOpenMPRuntime::LastprivateConditionalRAII 11505 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 11506 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 11507 return LastprivateConditionalRAII(CGF, S); 11508 } 11509 11510 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 11511 if (CGM.getLangOpts().OpenMP < 50) 11512 return; 11513 if (Action == ActionToDo::DisableLastprivateConditional) { 11514 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11515 "Expected list of disabled private vars."); 11516 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11517 } 11518 if (Action == ActionToDo::PushAsLastprivateConditional) { 11519 assert( 11520 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11521 "Expected list of lastprivate conditional vars."); 11522 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11523 } 11524 } 11525 11526 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 11527 const VarDecl *VD) { 11528 ASTContext &C = CGM.getContext(); 11529 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 11530 if (I == LastprivateConditionalToTypes.end()) 11531 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 11532 QualType NewType; 11533 const FieldDecl *VDField; 11534 const FieldDecl *FiredField; 11535 LValue BaseLVal; 11536 auto VI = I->getSecond().find(VD); 11537 if (VI == I->getSecond().end()) { 11538 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 11539 RD->startDefinition(); 11540 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 11541 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 11542 RD->completeDefinition(); 11543 NewType = C.getRecordType(RD); 11544 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 11545 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 11546 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 11547 } else { 11548 NewType = std::get<0>(VI->getSecond()); 11549 VDField = std::get<1>(VI->getSecond()); 11550 FiredField = std::get<2>(VI->getSecond()); 11551 BaseLVal = std::get<3>(VI->getSecond()); 11552 } 11553 LValue FiredLVal = 11554 CGF.EmitLValueForField(BaseLVal, FiredField); 11555 CGF.EmitStoreOfScalar( 11556 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 11557 FiredLVal); 11558 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 11559 } 11560 11561 namespace { 11562 /// Checks if the lastprivate conditional variable is referenced in LHS. 11563 class LastprivateConditionalRefChecker final 11564 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 11565 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 11566 const Expr *FoundE = nullptr; 11567 const Decl *FoundD = nullptr; 11568 StringRef UniqueDeclName; 11569 LValue IVLVal; 11570 llvm::Function *FoundFn = nullptr; 11571 SourceLocation Loc; 11572 11573 public: 11574 bool VisitDeclRefExpr(const DeclRefExpr *E) { 11575 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11576 llvm::reverse(LPM)) { 11577 auto It = D.DeclToUniqueName.find(E->getDecl()); 11578 if (It == D.DeclToUniqueName.end()) 11579 continue; 11580 if (D.Disabled) 11581 return false; 11582 FoundE = E; 11583 FoundD = E->getDecl()->getCanonicalDecl(); 11584 UniqueDeclName = It->second; 11585 IVLVal = D.IVLVal; 11586 FoundFn = D.Fn; 11587 break; 11588 } 11589 return FoundE == E; 11590 } 11591 bool VisitMemberExpr(const MemberExpr *E) { 11592 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 11593 return false; 11594 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11595 llvm::reverse(LPM)) { 11596 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 11597 if (It == D.DeclToUniqueName.end()) 11598 continue; 11599 if (D.Disabled) 11600 return false; 11601 FoundE = E; 11602 FoundD = E->getMemberDecl()->getCanonicalDecl(); 11603 UniqueDeclName = It->second; 11604 IVLVal = D.IVLVal; 11605 FoundFn = D.Fn; 11606 break; 11607 } 11608 return FoundE == E; 11609 } 11610 bool VisitStmt(const Stmt *S) { 11611 for (const Stmt *Child : S->children()) { 11612 if (!Child) 11613 continue; 11614 if (const auto *E = dyn_cast<Expr>(Child)) 11615 if (!E->isGLValue()) 11616 continue; 11617 if (Visit(Child)) 11618 return true; 11619 } 11620 return false; 11621 } 11622 explicit LastprivateConditionalRefChecker( 11623 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 11624 : LPM(LPM) {} 11625 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 11626 getFoundData() const { 11627 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 11628 } 11629 }; 11630 } // namespace 11631 11632 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 11633 LValue IVLVal, 11634 StringRef UniqueDeclName, 11635 LValue LVal, 11636 SourceLocation Loc) { 11637 // Last updated loop counter for the lastprivate conditional var. 11638 // int<xx> last_iv = 0; 11639 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 11640 llvm::Constant *LastIV = 11641 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 11642 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 11643 IVLVal.getAlignment().getAsAlign()); 11644 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 11645 11646 // Last value of the lastprivate conditional. 11647 // decltype(priv_a) last_a; 11648 llvm::Constant *Last = getOrCreateInternalVariable( 11649 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 11650 cast<llvm::GlobalVariable>(Last)->setAlignment( 11651 LVal.getAlignment().getAsAlign()); 11652 LValue LastLVal = 11653 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 11654 11655 // Global loop counter. Required to handle inner parallel-for regions. 11656 // iv 11657 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 11658 11659 // #pragma omp critical(a) 11660 // if (last_iv <= iv) { 11661 // last_iv = iv; 11662 // last_a = priv_a; 11663 // } 11664 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 11665 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 11666 Action.Enter(CGF); 11667 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 11668 // (last_iv <= iv) ? Check if the variable is updated and store new 11669 // value in global var. 11670 llvm::Value *CmpRes; 11671 if (IVLVal.getType()->isSignedIntegerType()) { 11672 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 11673 } else { 11674 assert(IVLVal.getType()->isUnsignedIntegerType() && 11675 "Loop iteration variable must be integer."); 11676 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 11677 } 11678 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 11679 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 11680 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 11681 // { 11682 CGF.EmitBlock(ThenBB); 11683 11684 // last_iv = iv; 11685 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 11686 11687 // last_a = priv_a; 11688 switch (CGF.getEvaluationKind(LVal.getType())) { 11689 case TEK_Scalar: { 11690 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 11691 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 11692 break; 11693 } 11694 case TEK_Complex: { 11695 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 11696 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 11697 break; 11698 } 11699 case TEK_Aggregate: 11700 llvm_unreachable( 11701 "Aggregates are not supported in lastprivate conditional."); 11702 } 11703 // } 11704 CGF.EmitBranch(ExitBB); 11705 // There is no need to emit line number for unconditional branch. 11706 (void)ApplyDebugLocation::CreateEmpty(CGF); 11707 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 11708 }; 11709 11710 if (CGM.getLangOpts().OpenMPSimd) { 11711 // Do not emit as a critical region as no parallel region could be emitted. 11712 RegionCodeGenTy ThenRCG(CodeGen); 11713 ThenRCG(CGF); 11714 } else { 11715 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 11716 } 11717 } 11718 11719 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 11720 const Expr *LHS) { 11721 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11722 return; 11723 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 11724 if (!Checker.Visit(LHS)) 11725 return; 11726 const Expr *FoundE; 11727 const Decl *FoundD; 11728 StringRef UniqueDeclName; 11729 LValue IVLVal; 11730 llvm::Function *FoundFn; 11731 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 11732 Checker.getFoundData(); 11733 if (FoundFn != CGF.CurFn) { 11734 // Special codegen for inner parallel regions. 11735 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 11736 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 11737 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 11738 "Lastprivate conditional is not found in outer region."); 11739 QualType StructTy = std::get<0>(It->getSecond()); 11740 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 11741 LValue PrivLVal = CGF.EmitLValue(FoundE); 11742 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11743 PrivLVal.getAddress(CGF), 11744 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 11745 LValue BaseLVal = 11746 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 11747 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 11748 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 11749 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 11750 FiredLVal, llvm::AtomicOrdering::Unordered, 11751 /*IsVolatile=*/true, /*isInit=*/false); 11752 return; 11753 } 11754 11755 // Private address of the lastprivate conditional in the current context. 11756 // priv_a 11757 LValue LVal = CGF.EmitLValue(FoundE); 11758 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 11759 FoundE->getExprLoc()); 11760 } 11761 11762 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 11763 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11764 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 11765 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11766 return; 11767 auto Range = llvm::reverse(LastprivateConditionalStack); 11768 auto It = llvm::find_if( 11769 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 11770 if (It == Range.end() || It->Fn != CGF.CurFn) 11771 return; 11772 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 11773 assert(LPCI != LastprivateConditionalToTypes.end() && 11774 "Lastprivates must be registered already."); 11775 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11776 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 11777 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 11778 for (const auto &Pair : It->DeclToUniqueName) { 11779 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 11780 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 11781 continue; 11782 auto I = LPCI->getSecond().find(Pair.first); 11783 assert(I != LPCI->getSecond().end() && 11784 "Lastprivate must be rehistered already."); 11785 // bool Cmp = priv_a.Fired != 0; 11786 LValue BaseLVal = std::get<3>(I->getSecond()); 11787 LValue FiredLVal = 11788 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 11789 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 11790 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 11791 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 11792 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 11793 // if (Cmp) { 11794 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 11795 CGF.EmitBlock(ThenBB); 11796 Address Addr = CGF.GetAddrOfLocalVar(VD); 11797 LValue LVal; 11798 if (VD->getType()->isReferenceType()) 11799 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 11800 AlignmentSource::Decl); 11801 else 11802 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 11803 AlignmentSource::Decl); 11804 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 11805 D.getBeginLoc()); 11806 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 11807 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 11808 // } 11809 } 11810 } 11811 11812 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 11813 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 11814 SourceLocation Loc) { 11815 if (CGF.getLangOpts().OpenMP < 50) 11816 return; 11817 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 11818 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 11819 "Unknown lastprivate conditional variable."); 11820 StringRef UniqueName = It->second; 11821 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 11822 // The variable was not updated in the region - exit. 11823 if (!GV) 11824 return; 11825 LValue LPLVal = CGF.MakeAddrLValue( 11826 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 11827 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 11828 CGF.EmitStoreOfScalar(Res, PrivLVal); 11829 } 11830 11831 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11832 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11833 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11834 llvm_unreachable("Not supported in SIMD-only mode"); 11835 } 11836 11837 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11838 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11839 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11840 llvm_unreachable("Not supported in SIMD-only mode"); 11841 } 11842 11843 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11844 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11845 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11846 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11847 bool Tied, unsigned &NumberOfParts) { 11848 llvm_unreachable("Not supported in SIMD-only mode"); 11849 } 11850 11851 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11852 SourceLocation Loc, 11853 llvm::Function *OutlinedFn, 11854 ArrayRef<llvm::Value *> CapturedVars, 11855 const Expr *IfCond) { 11856 llvm_unreachable("Not supported in SIMD-only mode"); 11857 } 11858 11859 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11860 CodeGenFunction &CGF, StringRef CriticalName, 11861 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11862 const Expr *Hint) { 11863 llvm_unreachable("Not supported in SIMD-only mode"); 11864 } 11865 11866 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11867 const RegionCodeGenTy &MasterOpGen, 11868 SourceLocation Loc) { 11869 llvm_unreachable("Not supported in SIMD-only mode"); 11870 } 11871 11872 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11873 SourceLocation Loc) { 11874 llvm_unreachable("Not supported in SIMD-only mode"); 11875 } 11876 11877 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11878 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11879 SourceLocation Loc) { 11880 llvm_unreachable("Not supported in SIMD-only mode"); 11881 } 11882 11883 void CGOpenMPSIMDRuntime::emitSingleRegion( 11884 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11885 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11886 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11887 ArrayRef<const Expr *> AssignmentOps) { 11888 llvm_unreachable("Not supported in SIMD-only mode"); 11889 } 11890 11891 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11892 const RegionCodeGenTy &OrderedOpGen, 11893 SourceLocation Loc, 11894 bool IsThreads) { 11895 llvm_unreachable("Not supported in SIMD-only mode"); 11896 } 11897 11898 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11899 SourceLocation Loc, 11900 OpenMPDirectiveKind Kind, 11901 bool EmitChecks, 11902 bool ForceSimpleCall) { 11903 llvm_unreachable("Not supported in SIMD-only mode"); 11904 } 11905 11906 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11907 CodeGenFunction &CGF, SourceLocation Loc, 11908 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11909 bool Ordered, const DispatchRTInput &DispatchValues) { 11910 llvm_unreachable("Not supported in SIMD-only mode"); 11911 } 11912 11913 void CGOpenMPSIMDRuntime::emitForStaticInit( 11914 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11915 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11916 llvm_unreachable("Not supported in SIMD-only mode"); 11917 } 11918 11919 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11920 CodeGenFunction &CGF, SourceLocation Loc, 11921 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11922 llvm_unreachable("Not supported in SIMD-only mode"); 11923 } 11924 11925 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11926 SourceLocation Loc, 11927 unsigned IVSize, 11928 bool IVSigned) { 11929 llvm_unreachable("Not supported in SIMD-only mode"); 11930 } 11931 11932 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11933 SourceLocation Loc, 11934 OpenMPDirectiveKind DKind) { 11935 llvm_unreachable("Not supported in SIMD-only mode"); 11936 } 11937 11938 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11939 SourceLocation Loc, 11940 unsigned IVSize, bool IVSigned, 11941 Address IL, Address LB, 11942 Address UB, Address ST) { 11943 llvm_unreachable("Not supported in SIMD-only mode"); 11944 } 11945 11946 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11947 llvm::Value *NumThreads, 11948 SourceLocation Loc) { 11949 llvm_unreachable("Not supported in SIMD-only mode"); 11950 } 11951 11952 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11953 ProcBindKind ProcBind, 11954 SourceLocation Loc) { 11955 llvm_unreachable("Not supported in SIMD-only mode"); 11956 } 11957 11958 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11959 const VarDecl *VD, 11960 Address VDAddr, 11961 SourceLocation Loc) { 11962 llvm_unreachable("Not supported in SIMD-only mode"); 11963 } 11964 11965 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11966 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11967 CodeGenFunction *CGF) { 11968 llvm_unreachable("Not supported in SIMD-only mode"); 11969 } 11970 11971 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11972 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11973 llvm_unreachable("Not supported in SIMD-only mode"); 11974 } 11975 11976 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11977 ArrayRef<const Expr *> Vars, 11978 SourceLocation Loc, 11979 llvm::AtomicOrdering AO) { 11980 llvm_unreachable("Not supported in SIMD-only mode"); 11981 } 11982 11983 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11984 const OMPExecutableDirective &D, 11985 llvm::Function *TaskFunction, 11986 QualType SharedsTy, Address Shareds, 11987 const Expr *IfCond, 11988 const OMPTaskDataTy &Data) { 11989 llvm_unreachable("Not supported in SIMD-only mode"); 11990 } 11991 11992 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11993 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11994 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11995 const Expr *IfCond, const OMPTaskDataTy &Data) { 11996 llvm_unreachable("Not supported in SIMD-only mode"); 11997 } 11998 11999 void CGOpenMPSIMDRuntime::emitReduction( 12000 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 12001 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 12002 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 12003 assert(Options.SimpleReduction && "Only simple reduction is expected."); 12004 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 12005 ReductionOps, Options); 12006 } 12007 12008 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 12009 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 12010 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 12011 llvm_unreachable("Not supported in SIMD-only mode"); 12012 } 12013 12014 void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 12015 SourceLocation Loc, 12016 bool IsWorksharingReduction) { 12017 llvm_unreachable("Not supported in SIMD-only mode"); 12018 } 12019 12020 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 12021 SourceLocation Loc, 12022 ReductionCodeGen &RCG, 12023 unsigned N) { 12024 llvm_unreachable("Not supported in SIMD-only mode"); 12025 } 12026 12027 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 12028 SourceLocation Loc, 12029 llvm::Value *ReductionsPtr, 12030 LValue SharedLVal) { 12031 llvm_unreachable("Not supported in SIMD-only mode"); 12032 } 12033 12034 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 12035 SourceLocation Loc) { 12036 llvm_unreachable("Not supported in SIMD-only mode"); 12037 } 12038 12039 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 12040 CodeGenFunction &CGF, SourceLocation Loc, 12041 OpenMPDirectiveKind CancelRegion) { 12042 llvm_unreachable("Not supported in SIMD-only mode"); 12043 } 12044 12045 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 12046 SourceLocation Loc, const Expr *IfCond, 12047 OpenMPDirectiveKind CancelRegion) { 12048 llvm_unreachable("Not supported in SIMD-only mode"); 12049 } 12050 12051 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 12052 const OMPExecutableDirective &D, StringRef ParentName, 12053 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 12054 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 12055 llvm_unreachable("Not supported in SIMD-only mode"); 12056 } 12057 12058 void CGOpenMPSIMDRuntime::emitTargetCall( 12059 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12060 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 12061 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 12062 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 12063 const OMPLoopDirective &D)> 12064 SizeEmitter) { 12065 llvm_unreachable("Not supported in SIMD-only mode"); 12066 } 12067 12068 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 12069 llvm_unreachable("Not supported in SIMD-only mode"); 12070 } 12071 12072 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 12073 llvm_unreachable("Not supported in SIMD-only mode"); 12074 } 12075 12076 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 12077 return false; 12078 } 12079 12080 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 12081 const OMPExecutableDirective &D, 12082 SourceLocation Loc, 12083 llvm::Function *OutlinedFn, 12084 ArrayRef<llvm::Value *> CapturedVars) { 12085 llvm_unreachable("Not supported in SIMD-only mode"); 12086 } 12087 12088 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 12089 const Expr *NumTeams, 12090 const Expr *ThreadLimit, 12091 SourceLocation Loc) { 12092 llvm_unreachable("Not supported in SIMD-only mode"); 12093 } 12094 12095 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 12096 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12097 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 12098 llvm_unreachable("Not supported in SIMD-only mode"); 12099 } 12100 12101 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 12102 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12103 const Expr *Device) { 12104 llvm_unreachable("Not supported in SIMD-only mode"); 12105 } 12106 12107 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12108 const OMPLoopDirective &D, 12109 ArrayRef<Expr *> NumIterations) { 12110 llvm_unreachable("Not supported in SIMD-only mode"); 12111 } 12112 12113 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12114 const OMPDependClause *C) { 12115 llvm_unreachable("Not supported in SIMD-only mode"); 12116 } 12117 12118 const VarDecl * 12119 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 12120 const VarDecl *NativeParam) const { 12121 llvm_unreachable("Not supported in SIMD-only mode"); 12122 } 12123 12124 Address 12125 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 12126 const VarDecl *NativeParam, 12127 const VarDecl *TargetParam) const { 12128 llvm_unreachable("Not supported in SIMD-only mode"); 12129 } 12130