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/Frontend/OpenMP/OMPIRBuilder.h" 33 #include "llvm/IR/Constants.h" 34 #include "llvm/IR/DerivedTypes.h" 35 #include "llvm/IR/GlobalValue.h" 36 #include "llvm/IR/Value.h" 37 #include "llvm/Support/AtomicOrdering.h" 38 #include "llvm/Support/Format.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include <cassert> 41 #include <numeric> 42 43 using namespace clang; 44 using namespace CodeGen; 45 using namespace llvm::omp; 46 47 namespace { 48 /// Base class for handling code generation inside OpenMP regions. 49 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 50 public: 51 /// Kinds of OpenMP regions used in codegen. 52 enum CGOpenMPRegionKind { 53 /// Region with outlined function for standalone 'parallel' 54 /// directive. 55 ParallelOutlinedRegion, 56 /// Region with outlined function for standalone 'task' directive. 57 TaskOutlinedRegion, 58 /// Region for constructs that do not require function outlining, 59 /// like 'for', 'sections', 'atomic' etc. directives. 60 InlinedRegion, 61 /// Region with outlined function for standalone 'target' directive. 62 TargetRegion, 63 }; 64 65 CGOpenMPRegionInfo(const CapturedStmt &CS, 66 const CGOpenMPRegionKind RegionKind, 67 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 68 bool HasCancel) 69 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 70 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 71 72 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 73 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 74 bool HasCancel) 75 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 76 Kind(Kind), HasCancel(HasCancel) {} 77 78 /// Get a variable or parameter for storing global thread id 79 /// inside OpenMP construct. 80 virtual const VarDecl *getThreadIDVariable() const = 0; 81 82 /// Emit the captured statement body. 83 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 84 85 /// Get an LValue for the current ThreadID variable. 86 /// \return LValue for thread id variable. This LValue always has type int32*. 87 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 88 89 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 90 91 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 92 93 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 94 95 bool hasCancel() const { return HasCancel; } 96 97 static bool classof(const CGCapturedStmtInfo *Info) { 98 return Info->getKind() == CR_OpenMP; 99 } 100 101 ~CGOpenMPRegionInfo() override = default; 102 103 protected: 104 CGOpenMPRegionKind RegionKind; 105 RegionCodeGenTy CodeGen; 106 OpenMPDirectiveKind Kind; 107 bool HasCancel; 108 }; 109 110 /// API for captured statement code generation in OpenMP constructs. 111 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 112 public: 113 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 114 const RegionCodeGenTy &CodeGen, 115 OpenMPDirectiveKind Kind, bool HasCancel, 116 StringRef HelperName) 117 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 118 HasCancel), 119 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 120 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 121 } 122 123 /// Get a variable or parameter for storing global thread id 124 /// inside OpenMP construct. 125 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 126 127 /// Get the name of the capture helper. 128 StringRef getHelperName() const override { return HelperName; } 129 130 static bool classof(const CGCapturedStmtInfo *Info) { 131 return CGOpenMPRegionInfo::classof(Info) && 132 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 133 ParallelOutlinedRegion; 134 } 135 136 private: 137 /// A variable or parameter storing global thread id for OpenMP 138 /// constructs. 139 const VarDecl *ThreadIDVar; 140 StringRef HelperName; 141 }; 142 143 /// API for captured statement code generation in OpenMP constructs. 144 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 145 public: 146 class UntiedTaskActionTy final : public PrePostActionTy { 147 bool Untied; 148 const VarDecl *PartIDVar; 149 const RegionCodeGenTy UntiedCodeGen; 150 llvm::SwitchInst *UntiedSwitch = nullptr; 151 152 public: 153 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 154 const RegionCodeGenTy &UntiedCodeGen) 155 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 156 void Enter(CodeGenFunction &CGF) override { 157 if (Untied) { 158 // Emit task switching point. 159 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 160 CGF.GetAddrOfLocalVar(PartIDVar), 161 PartIDVar->getType()->castAs<PointerType>()); 162 llvm::Value *Res = 163 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 164 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 165 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 166 CGF.EmitBlock(DoneBB); 167 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 168 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 169 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 170 CGF.Builder.GetInsertBlock()); 171 emitUntiedSwitch(CGF); 172 } 173 } 174 void emitUntiedSwitch(CodeGenFunction &CGF) const { 175 if (Untied) { 176 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 177 CGF.GetAddrOfLocalVar(PartIDVar), 178 PartIDVar->getType()->castAs<PointerType>()); 179 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 180 PartIdLVal); 181 UntiedCodeGen(CGF); 182 CodeGenFunction::JumpDest CurPoint = 183 CGF.getJumpDestInCurrentScope(".untied.next."); 184 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 185 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 186 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 187 CGF.Builder.GetInsertBlock()); 188 CGF.EmitBranchThroughCleanup(CurPoint); 189 CGF.EmitBlock(CurPoint.getBlock()); 190 } 191 } 192 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 193 }; 194 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 195 const VarDecl *ThreadIDVar, 196 const RegionCodeGenTy &CodeGen, 197 OpenMPDirectiveKind Kind, bool HasCancel, 198 const UntiedTaskActionTy &Action) 199 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 200 ThreadIDVar(ThreadIDVar), Action(Action) { 201 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 202 } 203 204 /// Get a variable or parameter for storing global thread id 205 /// inside OpenMP construct. 206 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 207 208 /// Get an LValue for the current ThreadID variable. 209 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 210 211 /// Get the name of the capture helper. 212 StringRef getHelperName() const override { return ".omp_outlined."; } 213 214 void emitUntiedSwitch(CodeGenFunction &CGF) override { 215 Action.emitUntiedSwitch(CGF); 216 } 217 218 static bool classof(const CGCapturedStmtInfo *Info) { 219 return CGOpenMPRegionInfo::classof(Info) && 220 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 221 TaskOutlinedRegion; 222 } 223 224 private: 225 /// A variable or parameter storing global thread id for OpenMP 226 /// constructs. 227 const VarDecl *ThreadIDVar; 228 /// Action for emitting code for untied tasks. 229 const UntiedTaskActionTy &Action; 230 }; 231 232 /// API for inlined captured statement code generation in OpenMP 233 /// constructs. 234 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 235 public: 236 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 237 const RegionCodeGenTy &CodeGen, 238 OpenMPDirectiveKind Kind, bool HasCancel) 239 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 240 OldCSI(OldCSI), 241 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 242 243 // Retrieve the value of the context parameter. 244 llvm::Value *getContextValue() const override { 245 if (OuterRegionInfo) 246 return OuterRegionInfo->getContextValue(); 247 llvm_unreachable("No context value for inlined OpenMP region"); 248 } 249 250 void setContextValue(llvm::Value *V) override { 251 if (OuterRegionInfo) { 252 OuterRegionInfo->setContextValue(V); 253 return; 254 } 255 llvm_unreachable("No context value for inlined OpenMP region"); 256 } 257 258 /// Lookup the captured field decl for a variable. 259 const FieldDecl *lookup(const VarDecl *VD) const override { 260 if (OuterRegionInfo) 261 return OuterRegionInfo->lookup(VD); 262 // If there is no outer outlined region,no need to lookup in a list of 263 // captured variables, we can use the original one. 264 return nullptr; 265 } 266 267 FieldDecl *getThisFieldDecl() const override { 268 if (OuterRegionInfo) 269 return OuterRegionInfo->getThisFieldDecl(); 270 return nullptr; 271 } 272 273 /// Get a variable or parameter for storing global thread id 274 /// inside OpenMP construct. 275 const VarDecl *getThreadIDVariable() const override { 276 if (OuterRegionInfo) 277 return OuterRegionInfo->getThreadIDVariable(); 278 return nullptr; 279 } 280 281 /// Get an LValue for the current ThreadID variable. 282 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 283 if (OuterRegionInfo) 284 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 285 llvm_unreachable("No LValue for inlined OpenMP construct"); 286 } 287 288 /// Get the name of the capture helper. 289 StringRef getHelperName() const override { 290 if (auto *OuterRegionInfo = getOldCSI()) 291 return OuterRegionInfo->getHelperName(); 292 llvm_unreachable("No helper name for inlined OpenMP construct"); 293 } 294 295 void emitUntiedSwitch(CodeGenFunction &CGF) override { 296 if (OuterRegionInfo) 297 OuterRegionInfo->emitUntiedSwitch(CGF); 298 } 299 300 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 301 302 static bool classof(const CGCapturedStmtInfo *Info) { 303 return CGOpenMPRegionInfo::classof(Info) && 304 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 305 } 306 307 ~CGOpenMPInlinedRegionInfo() override = default; 308 309 private: 310 /// CodeGen info about outer OpenMP region. 311 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 312 CGOpenMPRegionInfo *OuterRegionInfo; 313 }; 314 315 /// API for captured statement code generation in OpenMP target 316 /// constructs. For this captures, implicit parameters are used instead of the 317 /// captured fields. The name of the target region has to be unique in a given 318 /// application so it is provided by the client, because only the client has 319 /// the information to generate that. 320 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 321 public: 322 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 323 const RegionCodeGenTy &CodeGen, StringRef HelperName) 324 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 325 /*HasCancel=*/false), 326 HelperName(HelperName) {} 327 328 /// This is unused for target regions because each starts executing 329 /// with a single thread. 330 const VarDecl *getThreadIDVariable() const override { return nullptr; } 331 332 /// Get the name of the capture helper. 333 StringRef getHelperName() const override { return HelperName; } 334 335 static bool classof(const CGCapturedStmtInfo *Info) { 336 return CGOpenMPRegionInfo::classof(Info) && 337 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 338 } 339 340 private: 341 StringRef HelperName; 342 }; 343 344 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 345 llvm_unreachable("No codegen for expressions"); 346 } 347 /// API for generation of expressions captured in a innermost OpenMP 348 /// region. 349 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 350 public: 351 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 352 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 353 OMPD_unknown, 354 /*HasCancel=*/false), 355 PrivScope(CGF) { 356 // Make sure the globals captured in the provided statement are local by 357 // using the privatization logic. We assume the same variable is not 358 // captured more than once. 359 for (const auto &C : CS.captures()) { 360 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 361 continue; 362 363 const VarDecl *VD = C.getCapturedVar(); 364 if (VD->isLocalVarDeclOrParm()) 365 continue; 366 367 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 368 /*RefersToEnclosingVariableOrCapture=*/false, 369 VD->getType().getNonReferenceType(), VK_LValue, 370 C.getLocation()); 371 PrivScope.addPrivate( 372 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 373 } 374 (void)PrivScope.Privatize(); 375 } 376 377 /// Lookup the captured field decl for a variable. 378 const FieldDecl *lookup(const VarDecl *VD) const override { 379 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 380 return FD; 381 return nullptr; 382 } 383 384 /// Emit the captured statement body. 385 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 386 llvm_unreachable("No body for expressions"); 387 } 388 389 /// Get a variable or parameter for storing global thread id 390 /// inside OpenMP construct. 391 const VarDecl *getThreadIDVariable() const override { 392 llvm_unreachable("No thread id for expressions"); 393 } 394 395 /// Get the name of the capture helper. 396 StringRef getHelperName() const override { 397 llvm_unreachable("No helper name for expressions"); 398 } 399 400 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 401 402 private: 403 /// Private scope to capture global variables. 404 CodeGenFunction::OMPPrivateScope PrivScope; 405 }; 406 407 /// RAII for emitting code of OpenMP constructs. 408 class InlinedOpenMPRegionRAII { 409 CodeGenFunction &CGF; 410 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 411 FieldDecl *LambdaThisCaptureField = nullptr; 412 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 413 414 public: 415 /// Constructs region for combined constructs. 416 /// \param CodeGen Code generation sequence for combined directives. Includes 417 /// a list of functions used for code generation of implicitly inlined 418 /// regions. 419 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 420 OpenMPDirectiveKind Kind, bool HasCancel) 421 : CGF(CGF) { 422 // Start emission for the construct. 423 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 424 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 425 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 426 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 427 CGF.LambdaThisCaptureField = nullptr; 428 BlockInfo = CGF.BlockInfo; 429 CGF.BlockInfo = nullptr; 430 } 431 432 ~InlinedOpenMPRegionRAII() { 433 // Restore original CapturedStmtInfo only if we're done with code emission. 434 auto *OldCSI = 435 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 436 delete CGF.CapturedStmtInfo; 437 CGF.CapturedStmtInfo = OldCSI; 438 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 439 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 440 CGF.BlockInfo = BlockInfo; 441 } 442 }; 443 444 /// Values for bit flags used in the ident_t to describe the fields. 445 /// All enumeric elements are named and described in accordance with the code 446 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 447 enum OpenMPLocationFlags : unsigned { 448 /// Use trampoline for internal microtask. 449 OMP_IDENT_IMD = 0x01, 450 /// Use c-style ident structure. 451 OMP_IDENT_KMPC = 0x02, 452 /// Atomic reduction option for kmpc_reduce. 453 OMP_ATOMIC_REDUCE = 0x10, 454 /// Explicit 'barrier' directive. 455 OMP_IDENT_BARRIER_EXPL = 0x20, 456 /// Implicit barrier in code. 457 OMP_IDENT_BARRIER_IMPL = 0x40, 458 /// Implicit barrier in 'for' directive. 459 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 460 /// Implicit barrier in 'sections' directive. 461 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 462 /// Implicit barrier in 'single' directive. 463 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 464 /// Call of __kmp_for_static_init for static loop. 465 OMP_IDENT_WORK_LOOP = 0x200, 466 /// Call of __kmp_for_static_init for sections. 467 OMP_IDENT_WORK_SECTIONS = 0x400, 468 /// Call of __kmp_for_static_init for distribute. 469 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 470 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 471 }; 472 473 namespace { 474 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 475 /// Values for bit flags for marking which requires clauses have been used. 476 enum OpenMPOffloadingRequiresDirFlags : int64_t { 477 /// flag undefined. 478 OMP_REQ_UNDEFINED = 0x000, 479 /// no requires clause present. 480 OMP_REQ_NONE = 0x001, 481 /// reverse_offload clause. 482 OMP_REQ_REVERSE_OFFLOAD = 0x002, 483 /// unified_address clause. 484 OMP_REQ_UNIFIED_ADDRESS = 0x004, 485 /// unified_shared_memory clause. 486 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 487 /// dynamic_allocators clause. 488 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 489 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 490 }; 491 492 enum OpenMPOffloadingReservedDeviceIDs { 493 /// Device ID if the device was not defined, runtime should get it 494 /// from environment variables in the spec. 495 OMP_DEVICEID_UNDEF = -1, 496 }; 497 } // anonymous namespace 498 499 /// Describes ident structure that describes a source location. 500 /// All descriptions are taken from 501 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 502 /// Original structure: 503 /// typedef struct ident { 504 /// kmp_int32 reserved_1; /**< might be used in Fortran; 505 /// see above */ 506 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 507 /// KMP_IDENT_KMPC identifies this union 508 /// member */ 509 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 510 /// see above */ 511 ///#if USE_ITT_BUILD 512 /// /* but currently used for storing 513 /// region-specific ITT */ 514 /// /* contextual information. */ 515 ///#endif /* USE_ITT_BUILD */ 516 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 517 /// C++ */ 518 /// char const *psource; /**< String describing the source location. 519 /// The string is composed of semi-colon separated 520 // fields which describe the source file, 521 /// the function and a pair of line numbers that 522 /// delimit the construct. 523 /// */ 524 /// } ident_t; 525 enum IdentFieldIndex { 526 /// might be used in Fortran 527 IdentField_Reserved_1, 528 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 529 IdentField_Flags, 530 /// Not really used in Fortran any more 531 IdentField_Reserved_2, 532 /// Source[4] in Fortran, do not use for C++ 533 IdentField_Reserved_3, 534 /// String describing the source location. The string is composed of 535 /// semi-colon separated fields which describe the source file, the function 536 /// and a pair of line numbers that delimit the construct. 537 IdentField_PSource 538 }; 539 540 /// Schedule types for 'omp for' loops (these enumerators are taken from 541 /// the enum sched_type in kmp.h). 542 enum OpenMPSchedType { 543 /// Lower bound for default (unordered) versions. 544 OMP_sch_lower = 32, 545 OMP_sch_static_chunked = 33, 546 OMP_sch_static = 34, 547 OMP_sch_dynamic_chunked = 35, 548 OMP_sch_guided_chunked = 36, 549 OMP_sch_runtime = 37, 550 OMP_sch_auto = 38, 551 /// static with chunk adjustment (e.g., simd) 552 OMP_sch_static_balanced_chunked = 45, 553 /// Lower bound for 'ordered' versions. 554 OMP_ord_lower = 64, 555 OMP_ord_static_chunked = 65, 556 OMP_ord_static = 66, 557 OMP_ord_dynamic_chunked = 67, 558 OMP_ord_guided_chunked = 68, 559 OMP_ord_runtime = 69, 560 OMP_ord_auto = 70, 561 OMP_sch_default = OMP_sch_static, 562 /// dist_schedule types 563 OMP_dist_sch_static_chunked = 91, 564 OMP_dist_sch_static = 92, 565 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 566 /// Set if the monotonic schedule modifier was present. 567 OMP_sch_modifier_monotonic = (1 << 29), 568 /// Set if the nonmonotonic schedule modifier was present. 569 OMP_sch_modifier_nonmonotonic = (1 << 30), 570 }; 571 572 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 573 /// region. 574 class CleanupTy final : public EHScopeStack::Cleanup { 575 PrePostActionTy *Action; 576 577 public: 578 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 579 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 580 if (!CGF.HaveInsertPoint()) 581 return; 582 Action->Exit(CGF); 583 } 584 }; 585 586 } // anonymous namespace 587 588 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 589 CodeGenFunction::RunCleanupsScope Scope(CGF); 590 if (PrePostAction) { 591 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 592 Callback(CodeGen, CGF, *PrePostAction); 593 } else { 594 PrePostActionTy Action; 595 Callback(CodeGen, CGF, Action); 596 } 597 } 598 599 /// Check if the combiner is a call to UDR combiner and if it is so return the 600 /// UDR decl used for reduction. 601 static const OMPDeclareReductionDecl * 602 getReductionInit(const Expr *ReductionOp) { 603 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 604 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 605 if (const auto *DRE = 606 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 607 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 608 return DRD; 609 return nullptr; 610 } 611 612 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 613 const OMPDeclareReductionDecl *DRD, 614 const Expr *InitOp, 615 Address Private, Address Original, 616 QualType Ty) { 617 if (DRD->getInitializer()) { 618 std::pair<llvm::Function *, llvm::Function *> Reduction = 619 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 620 const auto *CE = cast<CallExpr>(InitOp); 621 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 622 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 623 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 624 const auto *LHSDRE = 625 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 626 const auto *RHSDRE = 627 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 628 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 629 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 630 [=]() { return Private; }); 631 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 632 [=]() { return Original; }); 633 (void)PrivateScope.Privatize(); 634 RValue Func = RValue::get(Reduction.second); 635 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 636 CGF.EmitIgnoredExpr(InitOp); 637 } else { 638 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 639 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 640 auto *GV = new llvm::GlobalVariable( 641 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 642 llvm::GlobalValue::PrivateLinkage, Init, Name); 643 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 644 RValue InitRVal; 645 switch (CGF.getEvaluationKind(Ty)) { 646 case TEK_Scalar: 647 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 648 break; 649 case TEK_Complex: 650 InitRVal = 651 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 652 break; 653 case TEK_Aggregate: 654 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 655 break; 656 } 657 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 658 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 659 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 660 /*IsInitializer=*/false); 661 } 662 } 663 664 /// Emit initialization of arrays of complex types. 665 /// \param DestAddr Address of the array. 666 /// \param Type Type of array. 667 /// \param Init Initial expression of array. 668 /// \param SrcAddr Address of the original array. 669 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 670 QualType Type, bool EmitDeclareReductionInit, 671 const Expr *Init, 672 const OMPDeclareReductionDecl *DRD, 673 Address SrcAddr = Address::invalid()) { 674 // Perform element-by-element initialization. 675 QualType ElementTy; 676 677 // Drill down to the base element type on both arrays. 678 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 679 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 680 DestAddr = 681 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 682 if (DRD) 683 SrcAddr = 684 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 685 686 llvm::Value *SrcBegin = nullptr; 687 if (DRD) 688 SrcBegin = SrcAddr.getPointer(); 689 llvm::Value *DestBegin = DestAddr.getPointer(); 690 // Cast from pointer to array type to pointer to single element. 691 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 692 // The basic structure here is a while-do loop. 693 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 694 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 695 llvm::Value *IsEmpty = 696 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 697 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 698 699 // Enter the loop body, making that address the current address. 700 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 701 CGF.EmitBlock(BodyBB); 702 703 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 704 705 llvm::PHINode *SrcElementPHI = nullptr; 706 Address SrcElementCurrent = Address::invalid(); 707 if (DRD) { 708 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 709 "omp.arraycpy.srcElementPast"); 710 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 711 SrcElementCurrent = 712 Address(SrcElementPHI, 713 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 714 } 715 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 716 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 717 DestElementPHI->addIncoming(DestBegin, EntryBB); 718 Address DestElementCurrent = 719 Address(DestElementPHI, 720 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 721 722 // Emit copy. 723 { 724 CodeGenFunction::RunCleanupsScope InitScope(CGF); 725 if (EmitDeclareReductionInit) { 726 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 727 SrcElementCurrent, ElementTy); 728 } else 729 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 730 /*IsInitializer=*/false); 731 } 732 733 if (DRD) { 734 // Shift the address forward by one element. 735 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 736 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 737 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 738 } 739 740 // Shift the address forward by one element. 741 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 742 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 743 // Check whether we've reached the end. 744 llvm::Value *Done = 745 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 746 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 747 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 748 749 // Done. 750 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 751 } 752 753 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 754 return CGF.EmitOMPSharedLValue(E); 755 } 756 757 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 758 const Expr *E) { 759 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 760 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 761 return LValue(); 762 } 763 764 void ReductionCodeGen::emitAggregateInitialization( 765 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 766 const OMPDeclareReductionDecl *DRD) { 767 // Emit VarDecl with copy init for arrays. 768 // Get the address of the original variable captured in current 769 // captured region. 770 const auto *PrivateVD = 771 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 772 bool EmitDeclareReductionInit = 773 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 774 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 775 EmitDeclareReductionInit, 776 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 777 : PrivateVD->getInit(), 778 DRD, SharedLVal.getAddress(CGF)); 779 } 780 781 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 782 ArrayRef<const Expr *> Origs, 783 ArrayRef<const Expr *> Privates, 784 ArrayRef<const Expr *> ReductionOps) { 785 ClausesData.reserve(Shareds.size()); 786 SharedAddresses.reserve(Shareds.size()); 787 Sizes.reserve(Shareds.size()); 788 BaseDecls.reserve(Shareds.size()); 789 const auto *IOrig = Origs.begin(); 790 const auto *IPriv = Privates.begin(); 791 const auto *IRed = ReductionOps.begin(); 792 for (const Expr *Ref : Shareds) { 793 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed); 794 std::advance(IOrig, 1); 795 std::advance(IPriv, 1); 796 std::advance(IRed, 1); 797 } 798 } 799 800 void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) { 801 assert(SharedAddresses.size() == N && OrigAddresses.size() == N && 802 "Number of generated lvalues must be exactly N."); 803 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared); 804 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared); 805 SharedAddresses.emplace_back(First, Second); 806 if (ClausesData[N].Shared == ClausesData[N].Ref) { 807 OrigAddresses.emplace_back(First, Second); 808 } else { 809 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 810 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 811 OrigAddresses.emplace_back(First, Second); 812 } 813 } 814 815 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 816 const auto *PrivateVD = 817 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 818 QualType PrivateType = PrivateVD->getType(); 819 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 820 if (!PrivateType->isVariablyModifiedType()) { 821 Sizes.emplace_back( 822 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()), 823 nullptr); 824 return; 825 } 826 llvm::Value *Size; 827 llvm::Value *SizeInChars; 828 auto *ElemType = 829 cast<llvm::PointerType>(OrigAddresses[N].first.getPointer(CGF)->getType()) 830 ->getElementType(); 831 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 832 if (AsArraySection) { 833 Size = CGF.Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF), 834 OrigAddresses[N].first.getPointer(CGF)); 835 Size = CGF.Builder.CreateNUWAdd( 836 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 837 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 838 } else { 839 SizeInChars = 840 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()); 841 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 842 } 843 Sizes.emplace_back(SizeInChars, Size); 844 CodeGenFunction::OpaqueValueMapping OpaqueMap( 845 CGF, 846 cast<OpaqueValueExpr>( 847 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 848 RValue::get(Size)); 849 CGF.EmitVariablyModifiedType(PrivateType); 850 } 851 852 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 853 llvm::Value *Size) { 854 const auto *PrivateVD = 855 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 856 QualType PrivateType = PrivateVD->getType(); 857 if (!PrivateType->isVariablyModifiedType()) { 858 assert(!Size && !Sizes[N].second && 859 "Size should be nullptr for non-variably modified reduction " 860 "items."); 861 return; 862 } 863 CodeGenFunction::OpaqueValueMapping OpaqueMap( 864 CGF, 865 cast<OpaqueValueExpr>( 866 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 867 RValue::get(Size)); 868 CGF.EmitVariablyModifiedType(PrivateType); 869 } 870 871 void ReductionCodeGen::emitInitialization( 872 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 873 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 874 assert(SharedAddresses.size() > N && "No variable was generated"); 875 const auto *PrivateVD = 876 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 877 const OMPDeclareReductionDecl *DRD = 878 getReductionInit(ClausesData[N].ReductionOp); 879 QualType PrivateType = PrivateVD->getType(); 880 PrivateAddr = CGF.Builder.CreateElementBitCast( 881 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 882 QualType SharedType = SharedAddresses[N].first.getType(); 883 SharedLVal = CGF.MakeAddrLValue( 884 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 885 CGF.ConvertTypeForMem(SharedType)), 886 SharedType, SharedAddresses[N].first.getBaseInfo(), 887 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 888 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 889 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 890 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 891 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 892 PrivateAddr, SharedLVal.getAddress(CGF), 893 SharedLVal.getType()); 894 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 895 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 896 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 897 PrivateVD->getType().getQualifiers(), 898 /*IsInitializer=*/false); 899 } 900 } 901 902 bool ReductionCodeGen::needCleanups(unsigned N) { 903 const auto *PrivateVD = 904 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 905 QualType PrivateType = PrivateVD->getType(); 906 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 907 return DTorKind != QualType::DK_none; 908 } 909 910 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 911 Address PrivateAddr) { 912 const auto *PrivateVD = 913 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 914 QualType PrivateType = PrivateVD->getType(); 915 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 916 if (needCleanups(N)) { 917 PrivateAddr = CGF.Builder.CreateElementBitCast( 918 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 919 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 920 } 921 } 922 923 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 924 LValue BaseLV) { 925 BaseTy = BaseTy.getNonReferenceType(); 926 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 927 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 928 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 929 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 930 } else { 931 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 932 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 933 } 934 BaseTy = BaseTy->getPointeeType(); 935 } 936 return CGF.MakeAddrLValue( 937 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 938 CGF.ConvertTypeForMem(ElTy)), 939 BaseLV.getType(), BaseLV.getBaseInfo(), 940 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 941 } 942 943 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 944 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 945 llvm::Value *Addr) { 946 Address Tmp = Address::invalid(); 947 Address TopTmp = Address::invalid(); 948 Address MostTopTmp = Address::invalid(); 949 BaseTy = BaseTy.getNonReferenceType(); 950 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 951 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 952 Tmp = CGF.CreateMemTemp(BaseTy); 953 if (TopTmp.isValid()) 954 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 955 else 956 MostTopTmp = Tmp; 957 TopTmp = Tmp; 958 BaseTy = BaseTy->getPointeeType(); 959 } 960 llvm::Type *Ty = BaseLVType; 961 if (Tmp.isValid()) 962 Ty = Tmp.getElementType(); 963 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 964 if (Tmp.isValid()) { 965 CGF.Builder.CreateStore(Addr, Tmp); 966 return MostTopTmp; 967 } 968 return Address(Addr, BaseLVAlignment); 969 } 970 971 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 972 const VarDecl *OrigVD = nullptr; 973 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 974 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 975 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 976 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 977 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 978 Base = TempASE->getBase()->IgnoreParenImpCasts(); 979 DE = cast<DeclRefExpr>(Base); 980 OrigVD = cast<VarDecl>(DE->getDecl()); 981 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 982 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 983 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 984 Base = TempASE->getBase()->IgnoreParenImpCasts(); 985 DE = cast<DeclRefExpr>(Base); 986 OrigVD = cast<VarDecl>(DE->getDecl()); 987 } 988 return OrigVD; 989 } 990 991 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 992 Address PrivateAddr) { 993 const DeclRefExpr *DE; 994 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 995 BaseDecls.emplace_back(OrigVD); 996 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 997 LValue BaseLValue = 998 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 999 OriginalBaseLValue); 1000 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1001 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1002 llvm::Value *PrivatePointer = 1003 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1004 PrivateAddr.getPointer(), 1005 SharedAddresses[N].first.getAddress(CGF).getType()); 1006 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1007 return castToBase(CGF, OrigVD->getType(), 1008 SharedAddresses[N].first.getType(), 1009 OriginalBaseLValue.getAddress(CGF).getType(), 1010 OriginalBaseLValue.getAlignment(), Ptr); 1011 } 1012 BaseDecls.emplace_back( 1013 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1014 return PrivateAddr; 1015 } 1016 1017 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1018 const OMPDeclareReductionDecl *DRD = 1019 getReductionInit(ClausesData[N].ReductionOp); 1020 return DRD && DRD->getInitializer(); 1021 } 1022 1023 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1024 return CGF.EmitLoadOfPointerLValue( 1025 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1026 getThreadIDVariable()->getType()->castAs<PointerType>()); 1027 } 1028 1029 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1030 if (!CGF.HaveInsertPoint()) 1031 return; 1032 // 1.2.2 OpenMP Language Terminology 1033 // Structured block - An executable statement with a single entry at the 1034 // top and a single exit at the bottom. 1035 // The point of exit cannot be a branch out of the structured block. 1036 // longjmp() and throw() must not violate the entry/exit criteria. 1037 CGF.EHStack.pushTerminate(); 1038 CodeGen(CGF); 1039 CGF.EHStack.popTerminate(); 1040 } 1041 1042 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1043 CodeGenFunction &CGF) { 1044 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1045 getThreadIDVariable()->getType(), 1046 AlignmentSource::Decl); 1047 } 1048 1049 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1050 QualType FieldTy) { 1051 auto *Field = FieldDecl::Create( 1052 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1053 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1054 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1055 Field->setAccess(AS_public); 1056 DC->addDecl(Field); 1057 return Field; 1058 } 1059 1060 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1061 StringRef Separator) 1062 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1063 OffloadEntriesInfoManager(CGM) { 1064 ASTContext &C = CGM.getContext(); 1065 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1066 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1067 RD->startDefinition(); 1068 // reserved_1 1069 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1070 // flags 1071 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1072 // reserved_2 1073 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1074 // reserved_3 1075 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1076 // psource 1077 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1078 RD->completeDefinition(); 1079 IdentQTy = C.getRecordType(RD); 1080 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1081 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1082 1083 // Initialize Types used in OpenMPIRBuilder from OMPKinds.def 1084 llvm::omp::types::initializeTypes(CGM.getModule()); 1085 loadOffloadInfoMetadata(); 1086 } 1087 1088 void CGOpenMPRuntime::clear() { 1089 InternalVars.clear(); 1090 // Clean non-target variable declarations possibly used only in debug info. 1091 for (const auto &Data : EmittedNonTargetVariables) { 1092 if (!Data.getValue().pointsToAliveValue()) 1093 continue; 1094 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1095 if (!GV) 1096 continue; 1097 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1098 continue; 1099 GV->eraseFromParent(); 1100 } 1101 } 1102 1103 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1104 SmallString<128> Buffer; 1105 llvm::raw_svector_ostream OS(Buffer); 1106 StringRef Sep = FirstSeparator; 1107 for (StringRef Part : Parts) { 1108 OS << Sep << Part; 1109 Sep = Separator; 1110 } 1111 return std::string(OS.str()); 1112 } 1113 1114 static llvm::Function * 1115 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1116 const Expr *CombinerInitializer, const VarDecl *In, 1117 const VarDecl *Out, bool IsCombiner) { 1118 // void .omp_combiner.(Ty *in, Ty *out); 1119 ASTContext &C = CGM.getContext(); 1120 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1121 FunctionArgList Args; 1122 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1123 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1124 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1125 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1126 Args.push_back(&OmpOutParm); 1127 Args.push_back(&OmpInParm); 1128 const CGFunctionInfo &FnInfo = 1129 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1130 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1131 std::string Name = CGM.getOpenMPRuntime().getName( 1132 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1133 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1134 Name, &CGM.getModule()); 1135 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1136 if (CGM.getLangOpts().Optimize) { 1137 Fn->removeFnAttr(llvm::Attribute::NoInline); 1138 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1139 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1140 } 1141 CodeGenFunction CGF(CGM); 1142 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1143 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1144 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1145 Out->getLocation()); 1146 CodeGenFunction::OMPPrivateScope Scope(CGF); 1147 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1148 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1149 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1150 .getAddress(CGF); 1151 }); 1152 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1153 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1154 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1155 .getAddress(CGF); 1156 }); 1157 (void)Scope.Privatize(); 1158 if (!IsCombiner && Out->hasInit() && 1159 !CGF.isTrivialInitializer(Out->getInit())) { 1160 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1161 Out->getType().getQualifiers(), 1162 /*IsInitializer=*/true); 1163 } 1164 if (CombinerInitializer) 1165 CGF.EmitIgnoredExpr(CombinerInitializer); 1166 Scope.ForceCleanup(); 1167 CGF.FinishFunction(); 1168 return Fn; 1169 } 1170 1171 void CGOpenMPRuntime::emitUserDefinedReduction( 1172 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1173 if (UDRMap.count(D) > 0) 1174 return; 1175 llvm::Function *Combiner = emitCombinerOrInitializer( 1176 CGM, D->getType(), D->getCombiner(), 1177 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1178 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1179 /*IsCombiner=*/true); 1180 llvm::Function *Initializer = nullptr; 1181 if (const Expr *Init = D->getInitializer()) { 1182 Initializer = emitCombinerOrInitializer( 1183 CGM, D->getType(), 1184 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1185 : nullptr, 1186 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1187 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1188 /*IsCombiner=*/false); 1189 } 1190 UDRMap.try_emplace(D, Combiner, Initializer); 1191 if (CGF) { 1192 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1193 Decls.second.push_back(D); 1194 } 1195 } 1196 1197 std::pair<llvm::Function *, llvm::Function *> 1198 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1199 auto I = UDRMap.find(D); 1200 if (I != UDRMap.end()) 1201 return I->second; 1202 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1203 return UDRMap.lookup(D); 1204 } 1205 1206 namespace { 1207 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1208 // Builder if one is present. 1209 struct PushAndPopStackRAII { 1210 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1211 bool HasCancel) 1212 : OMPBuilder(OMPBuilder) { 1213 if (!OMPBuilder) 1214 return; 1215 1216 // The following callback is the crucial part of clangs cleanup process. 1217 // 1218 // NOTE: 1219 // Once the OpenMPIRBuilder is used to create parallel regions (and 1220 // similar), the cancellation destination (Dest below) is determined via 1221 // IP. That means if we have variables to finalize we split the block at IP, 1222 // use the new block (=BB) as destination to build a JumpDest (via 1223 // getJumpDestInCurrentScope(BB)) which then is fed to 1224 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1225 // to push & pop an FinalizationInfo object. 1226 // The FiniCB will still be needed but at the point where the 1227 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1228 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1229 assert(IP.getBlock()->end() == IP.getPoint() && 1230 "Clang CG should cause non-terminated block!"); 1231 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1232 CGF.Builder.restoreIP(IP); 1233 CodeGenFunction::JumpDest Dest = 1234 CGF.getOMPCancelDestination(OMPD_parallel); 1235 CGF.EmitBranchThroughCleanup(Dest); 1236 }; 1237 1238 // TODO: Remove this once we emit parallel regions through the 1239 // OpenMPIRBuilder as it can do this setup internally. 1240 llvm::OpenMPIRBuilder::FinalizationInfo FI( 1241 {FiniCB, OMPD_parallel, HasCancel}); 1242 OMPBuilder->pushFinalizationCB(std::move(FI)); 1243 } 1244 ~PushAndPopStackRAII() { 1245 if (OMPBuilder) 1246 OMPBuilder->popFinalizationCB(); 1247 } 1248 llvm::OpenMPIRBuilder *OMPBuilder; 1249 }; 1250 } // namespace 1251 1252 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1253 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1254 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1255 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1256 assert(ThreadIDVar->getType()->isPointerType() && 1257 "thread id variable must be of type kmp_int32 *"); 1258 CodeGenFunction CGF(CGM, true); 1259 bool HasCancel = false; 1260 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1261 HasCancel = OPD->hasCancel(); 1262 else if (const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D)) 1263 HasCancel = OPD->hasCancel(); 1264 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1265 HasCancel = OPSD->hasCancel(); 1266 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1267 HasCancel = OPFD->hasCancel(); 1268 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1269 HasCancel = OPFD->hasCancel(); 1270 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1271 HasCancel = OPFD->hasCancel(); 1272 else if (const auto *OPFD = 1273 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1274 HasCancel = OPFD->hasCancel(); 1275 else if (const auto *OPFD = 1276 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1277 HasCancel = OPFD->hasCancel(); 1278 1279 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1280 // parallel region to make cancellation barriers work properly. 1281 llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder(); 1282 PushAndPopStackRAII PSR(OMPBuilder, CGF, HasCancel); 1283 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1284 HasCancel, OutlinedHelperName); 1285 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1286 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1287 } 1288 1289 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1290 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1291 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1292 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1293 return emitParallelOrTeamsOutlinedFunction( 1294 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1295 } 1296 1297 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1298 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1299 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1300 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1301 return emitParallelOrTeamsOutlinedFunction( 1302 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1303 } 1304 1305 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1306 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1307 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1308 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1309 bool Tied, unsigned &NumberOfParts) { 1310 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1311 PrePostActionTy &) { 1312 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1313 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1314 llvm::Value *TaskArgs[] = { 1315 UpLoc, ThreadID, 1316 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1317 TaskTVar->getType()->castAs<PointerType>()) 1318 .getPointer(CGF)}; 1319 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 1320 CGM.getModule(), OMPRTL___kmpc_omp_task), 1321 TaskArgs); 1322 }; 1323 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1324 UntiedCodeGen); 1325 CodeGen.setAction(Action); 1326 assert(!ThreadIDVar->getType()->isPointerType() && 1327 "thread id variable must be of type kmp_int32 for tasks"); 1328 const OpenMPDirectiveKind Region = 1329 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1330 : OMPD_task; 1331 const CapturedStmt *CS = D.getCapturedStmt(Region); 1332 bool HasCancel = false; 1333 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1334 HasCancel = TD->hasCancel(); 1335 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1336 HasCancel = TD->hasCancel(); 1337 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1338 HasCancel = TD->hasCancel(); 1339 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1340 HasCancel = TD->hasCancel(); 1341 1342 CodeGenFunction CGF(CGM, true); 1343 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1344 InnermostKind, HasCancel, Action); 1345 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1346 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1347 if (!Tied) 1348 NumberOfParts = Action.getNumberOfParts(); 1349 return Res; 1350 } 1351 1352 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1353 const RecordDecl *RD, const CGRecordLayout &RL, 1354 ArrayRef<llvm::Constant *> Data) { 1355 llvm::StructType *StructTy = RL.getLLVMType(); 1356 unsigned PrevIdx = 0; 1357 ConstantInitBuilder CIBuilder(CGM); 1358 auto DI = Data.begin(); 1359 for (const FieldDecl *FD : RD->fields()) { 1360 unsigned Idx = RL.getLLVMFieldNo(FD); 1361 // Fill the alignment. 1362 for (unsigned I = PrevIdx; I < Idx; ++I) 1363 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1364 PrevIdx = Idx + 1; 1365 Fields.add(*DI); 1366 ++DI; 1367 } 1368 } 1369 1370 template <class... As> 1371 static llvm::GlobalVariable * 1372 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1373 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1374 As &&... Args) { 1375 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1376 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1377 ConstantInitBuilder CIBuilder(CGM); 1378 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1379 buildStructValue(Fields, CGM, RD, RL, Data); 1380 return Fields.finishAndCreateGlobal( 1381 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1382 std::forward<As>(Args)...); 1383 } 1384 1385 template <typename T> 1386 static void 1387 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1388 ArrayRef<llvm::Constant *> Data, 1389 T &Parent) { 1390 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1391 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1392 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1393 buildStructValue(Fields, CGM, RD, RL, Data); 1394 Fields.finishAndAddTo(Parent); 1395 } 1396 1397 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1398 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1399 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1400 FlagsTy FlagsKey(Flags, Reserved2Flags); 1401 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1402 if (!Entry) { 1403 if (!DefaultOpenMPPSource) { 1404 // Initialize default location for psource field of ident_t structure of 1405 // all ident_t objects. Format is ";file;function;line;column;;". 1406 // Taken from 1407 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1408 DefaultOpenMPPSource = 1409 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1410 DefaultOpenMPPSource = 1411 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1412 } 1413 1414 llvm::Constant *Data[] = { 1415 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1416 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1417 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1418 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1419 llvm::GlobalValue *DefaultOpenMPLocation = 1420 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1421 llvm::GlobalValue::PrivateLinkage); 1422 DefaultOpenMPLocation->setUnnamedAddr( 1423 llvm::GlobalValue::UnnamedAddr::Global); 1424 1425 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1426 } 1427 return Address(Entry, Align); 1428 } 1429 1430 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1431 bool AtCurrentPoint) { 1432 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1433 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1434 1435 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1436 if (AtCurrentPoint) { 1437 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1438 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1439 } else { 1440 Elem.second.ServiceInsertPt = 1441 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1442 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1443 } 1444 } 1445 1446 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1447 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1448 if (Elem.second.ServiceInsertPt) { 1449 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1450 Elem.second.ServiceInsertPt = nullptr; 1451 Ptr->eraseFromParent(); 1452 } 1453 } 1454 1455 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1456 SourceLocation Loc, 1457 unsigned Flags) { 1458 Flags |= OMP_IDENT_KMPC; 1459 // If no debug info is generated - return global default location. 1460 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1461 Loc.isInvalid()) 1462 return getOrCreateDefaultLocation(Flags).getPointer(); 1463 1464 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1465 1466 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1467 Address LocValue = Address::invalid(); 1468 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1469 if (I != OpenMPLocThreadIDMap.end()) 1470 LocValue = Address(I->second.DebugLoc, Align); 1471 1472 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1473 // GetOpenMPThreadID was called before this routine. 1474 if (!LocValue.isValid()) { 1475 // Generate "ident_t .kmpc_loc.addr;" 1476 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1477 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1478 Elem.second.DebugLoc = AI.getPointer(); 1479 LocValue = AI; 1480 1481 if (!Elem.second.ServiceInsertPt) 1482 setLocThreadIdInsertPt(CGF); 1483 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1484 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1485 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1486 CGF.getTypeSize(IdentQTy)); 1487 } 1488 1489 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1490 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1491 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1492 LValue PSource = 1493 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1494 1495 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1496 if (OMPDebugLoc == nullptr) { 1497 SmallString<128> Buffer2; 1498 llvm::raw_svector_ostream OS2(Buffer2); 1499 // Build debug location 1500 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1501 OS2 << ";" << PLoc.getFilename() << ";"; 1502 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1503 OS2 << FD->getQualifiedNameAsString(); 1504 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1505 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1506 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1507 } 1508 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1509 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1510 1511 // Our callers always pass this to a runtime function, so for 1512 // convenience, go ahead and return a naked pointer. 1513 return LocValue.getPointer(); 1514 } 1515 1516 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1517 SourceLocation Loc) { 1518 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1519 1520 llvm::Value *ThreadID = nullptr; 1521 // Check whether we've already cached a load of the thread id in this 1522 // function. 1523 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1524 if (I != OpenMPLocThreadIDMap.end()) { 1525 ThreadID = I->second.ThreadID; 1526 if (ThreadID != nullptr) 1527 return ThreadID; 1528 } 1529 // If exceptions are enabled, do not use parameter to avoid possible crash. 1530 if (auto *OMPRegionInfo = 1531 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1532 if (OMPRegionInfo->getThreadIDVariable()) { 1533 // Check if this an outlined function with thread id passed as argument. 1534 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1535 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1536 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1537 !CGF.getLangOpts().CXXExceptions || 1538 CGF.Builder.GetInsertBlock() == TopBlock || 1539 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1540 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1541 TopBlock || 1542 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1543 CGF.Builder.GetInsertBlock()) { 1544 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1545 // If value loaded in entry block, cache it and use it everywhere in 1546 // function. 1547 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1548 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1549 Elem.second.ThreadID = ThreadID; 1550 } 1551 return ThreadID; 1552 } 1553 } 1554 } 1555 1556 // This is not an outlined function region - need to call __kmpc_int32 1557 // kmpc_global_thread_num(ident_t *loc). 1558 // Generate thread id value and cache this value for use across the 1559 // function. 1560 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1561 if (!Elem.second.ServiceInsertPt) 1562 setLocThreadIdInsertPt(CGF); 1563 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1564 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1565 llvm::CallInst *Call = CGF.Builder.CreateCall( 1566 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 1567 CGM.getModule(), OMPRTL___kmpc_global_thread_num), 1568 emitUpdateLocation(CGF, Loc)); 1569 Call->setCallingConv(CGF.getRuntimeCC()); 1570 Elem.second.ThreadID = Call; 1571 return Call; 1572 } 1573 1574 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1575 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1576 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1577 clearLocThreadIdInsertPt(CGF); 1578 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1579 } 1580 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1581 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1582 UDRMap.erase(D); 1583 FunctionUDRMap.erase(CGF.CurFn); 1584 } 1585 auto I = FunctionUDMMap.find(CGF.CurFn); 1586 if (I != FunctionUDMMap.end()) { 1587 for(const auto *D : I->second) 1588 UDMMap.erase(D); 1589 FunctionUDMMap.erase(I); 1590 } 1591 LastprivateConditionalToTypes.erase(CGF.CurFn); 1592 } 1593 1594 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1595 return IdentTy->getPointerTo(); 1596 } 1597 1598 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1599 if (!Kmpc_MicroTy) { 1600 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1601 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1602 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1603 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1604 } 1605 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1606 } 1607 1608 llvm::FunctionCallee 1609 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 1610 assert((IVSize == 32 || IVSize == 64) && 1611 "IV size is not compatible with the omp runtime"); 1612 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 1613 : "__kmpc_for_static_init_4u") 1614 : (IVSigned ? "__kmpc_for_static_init_8" 1615 : "__kmpc_for_static_init_8u"); 1616 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1617 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1618 llvm::Type *TypeParams[] = { 1619 getIdentTyPointerTy(), // loc 1620 CGM.Int32Ty, // tid 1621 CGM.Int32Ty, // schedtype 1622 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1623 PtrTy, // p_lower 1624 PtrTy, // p_upper 1625 PtrTy, // p_stride 1626 ITy, // incr 1627 ITy // chunk 1628 }; 1629 auto *FnTy = 1630 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1631 return CGM.CreateRuntimeFunction(FnTy, Name); 1632 } 1633 1634 llvm::FunctionCallee 1635 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 1636 assert((IVSize == 32 || IVSize == 64) && 1637 "IV size is not compatible with the omp runtime"); 1638 StringRef Name = 1639 IVSize == 32 1640 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 1641 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 1642 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1643 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 1644 CGM.Int32Ty, // tid 1645 CGM.Int32Ty, // schedtype 1646 ITy, // lower 1647 ITy, // upper 1648 ITy, // stride 1649 ITy // chunk 1650 }; 1651 auto *FnTy = 1652 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1653 return CGM.CreateRuntimeFunction(FnTy, Name); 1654 } 1655 1656 llvm::FunctionCallee 1657 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 1658 assert((IVSize == 32 || IVSize == 64) && 1659 "IV size is not compatible with the omp runtime"); 1660 StringRef Name = 1661 IVSize == 32 1662 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 1663 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 1664 llvm::Type *TypeParams[] = { 1665 getIdentTyPointerTy(), // loc 1666 CGM.Int32Ty, // tid 1667 }; 1668 auto *FnTy = 1669 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1670 return CGM.CreateRuntimeFunction(FnTy, Name); 1671 } 1672 1673 llvm::FunctionCallee 1674 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 1675 assert((IVSize == 32 || IVSize == 64) && 1676 "IV size is not compatible with the omp runtime"); 1677 StringRef Name = 1678 IVSize == 32 1679 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 1680 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 1681 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1682 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1683 llvm::Type *TypeParams[] = { 1684 getIdentTyPointerTy(), // loc 1685 CGM.Int32Ty, // tid 1686 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1687 PtrTy, // p_lower 1688 PtrTy, // p_upper 1689 PtrTy // p_stride 1690 }; 1691 auto *FnTy = 1692 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1693 return CGM.CreateRuntimeFunction(FnTy, Name); 1694 } 1695 1696 /// Obtain information that uniquely identifies a target entry. This 1697 /// consists of the file and device IDs as well as line number associated with 1698 /// the relevant entry source location. 1699 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 1700 unsigned &DeviceID, unsigned &FileID, 1701 unsigned &LineNum) { 1702 SourceManager &SM = C.getSourceManager(); 1703 1704 // The loc should be always valid and have a file ID (the user cannot use 1705 // #pragma directives in macros) 1706 1707 assert(Loc.isValid() && "Source location is expected to be always valid."); 1708 1709 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 1710 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1711 1712 llvm::sys::fs::UniqueID ID; 1713 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 1714 SM.getDiagnostics().Report(diag::err_cannot_open_file) 1715 << PLoc.getFilename() << EC.message(); 1716 1717 DeviceID = ID.getDevice(); 1718 FileID = ID.getFile(); 1719 LineNum = PLoc.getLine(); 1720 } 1721 1722 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 1723 if (CGM.getLangOpts().OpenMPSimd) 1724 return Address::invalid(); 1725 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1726 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1727 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 1728 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1729 HasRequiresUnifiedSharedMemory))) { 1730 SmallString<64> PtrName; 1731 { 1732 llvm::raw_svector_ostream OS(PtrName); 1733 OS << CGM.getMangledName(GlobalDecl(VD)); 1734 if (!VD->isExternallyVisible()) { 1735 unsigned DeviceID, FileID, Line; 1736 getTargetEntryUniqueInfo(CGM.getContext(), 1737 VD->getCanonicalDecl()->getBeginLoc(), 1738 DeviceID, FileID, Line); 1739 OS << llvm::format("_%x", FileID); 1740 } 1741 OS << "_decl_tgt_ref_ptr"; 1742 } 1743 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 1744 if (!Ptr) { 1745 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 1746 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 1747 PtrName); 1748 1749 auto *GV = cast<llvm::GlobalVariable>(Ptr); 1750 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 1751 1752 if (!CGM.getLangOpts().OpenMPIsDevice) 1753 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 1754 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 1755 } 1756 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 1757 } 1758 return Address::invalid(); 1759 } 1760 1761 llvm::Constant * 1762 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 1763 assert(!CGM.getLangOpts().OpenMPUseTLS || 1764 !CGM.getContext().getTargetInfo().isTLSSupported()); 1765 // Lookup the entry, lazily creating it if necessary. 1766 std::string Suffix = getName({"cache", ""}); 1767 return getOrCreateInternalVariable( 1768 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 1769 } 1770 1771 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 1772 const VarDecl *VD, 1773 Address VDAddr, 1774 SourceLocation Loc) { 1775 if (CGM.getLangOpts().OpenMPUseTLS && 1776 CGM.getContext().getTargetInfo().isTLSSupported()) 1777 return VDAddr; 1778 1779 llvm::Type *VarTy = VDAddr.getElementType(); 1780 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1781 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1782 CGM.Int8PtrTy), 1783 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 1784 getOrCreateThreadPrivateCache(VD)}; 1785 return Address(CGF.EmitRuntimeCall( 1786 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 1787 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 1788 Args), 1789 VDAddr.getAlignment()); 1790 } 1791 1792 void CGOpenMPRuntime::emitThreadPrivateVarInit( 1793 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 1794 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 1795 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 1796 // library. 1797 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 1798 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 1799 CGM.getModule(), OMPRTL___kmpc_global_thread_num), 1800 OMPLoc); 1801 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 1802 // to register constructor/destructor for variable. 1803 llvm::Value *Args[] = { 1804 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 1805 Ctor, CopyCtor, Dtor}; 1806 CGF.EmitRuntimeCall( 1807 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 1808 CGM.getModule(), OMPRTL___kmpc_threadprivate_register), 1809 Args); 1810 } 1811 1812 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 1813 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 1814 bool PerformInit, CodeGenFunction *CGF) { 1815 if (CGM.getLangOpts().OpenMPUseTLS && 1816 CGM.getContext().getTargetInfo().isTLSSupported()) 1817 return nullptr; 1818 1819 VD = VD->getDefinition(CGM.getContext()); 1820 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 1821 QualType ASTTy = VD->getType(); 1822 1823 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 1824 const Expr *Init = VD->getAnyInitializer(); 1825 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1826 // Generate function that re-emits the declaration's initializer into the 1827 // threadprivate copy of the variable VD 1828 CodeGenFunction CtorCGF(CGM); 1829 FunctionArgList Args; 1830 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1831 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1832 ImplicitParamDecl::Other); 1833 Args.push_back(&Dst); 1834 1835 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1836 CGM.getContext().VoidPtrTy, Args); 1837 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1838 std::string Name = getName({"__kmpc_global_ctor_", ""}); 1839 llvm::Function *Fn = 1840 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 1841 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 1842 Args, Loc, Loc); 1843 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 1844 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1845 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1846 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 1847 Arg = CtorCGF.Builder.CreateElementBitCast( 1848 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 1849 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1850 /*IsInitializer=*/true); 1851 ArgVal = CtorCGF.EmitLoadOfScalar( 1852 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1853 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1854 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1855 CtorCGF.FinishFunction(); 1856 Ctor = Fn; 1857 } 1858 if (VD->getType().isDestructedType() != QualType::DK_none) { 1859 // Generate function that emits destructor call for the threadprivate copy 1860 // of the variable VD 1861 CodeGenFunction DtorCGF(CGM); 1862 FunctionArgList Args; 1863 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1864 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1865 ImplicitParamDecl::Other); 1866 Args.push_back(&Dst); 1867 1868 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1869 CGM.getContext().VoidTy, Args); 1870 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1871 std::string Name = getName({"__kmpc_global_dtor_", ""}); 1872 llvm::Function *Fn = 1873 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 1874 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1875 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1876 Loc, Loc); 1877 // Create a scope with an artificial location for the body of this function. 1878 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1879 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 1880 DtorCGF.GetAddrOfLocalVar(&Dst), 1881 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 1882 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 1883 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1884 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1885 DtorCGF.FinishFunction(); 1886 Dtor = Fn; 1887 } 1888 // Do not emit init function if it is not required. 1889 if (!Ctor && !Dtor) 1890 return nullptr; 1891 1892 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1893 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1894 /*isVarArg=*/false) 1895 ->getPointerTo(); 1896 // Copying constructor for the threadprivate variable. 1897 // Must be NULL - reserved by runtime, but currently it requires that this 1898 // parameter is always NULL. Otherwise it fires assertion. 1899 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1900 if (Ctor == nullptr) { 1901 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1902 /*isVarArg=*/false) 1903 ->getPointerTo(); 1904 Ctor = llvm::Constant::getNullValue(CtorTy); 1905 } 1906 if (Dtor == nullptr) { 1907 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1908 /*isVarArg=*/false) 1909 ->getPointerTo(); 1910 Dtor = llvm::Constant::getNullValue(DtorTy); 1911 } 1912 if (!CGF) { 1913 auto *InitFunctionTy = 1914 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1915 std::string Name = getName({"__omp_threadprivate_init_", ""}); 1916 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 1917 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 1918 CodeGenFunction InitCGF(CGM); 1919 FunctionArgList ArgList; 1920 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1921 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1922 Loc, Loc); 1923 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1924 InitCGF.FinishFunction(); 1925 return InitFunction; 1926 } 1927 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1928 } 1929 return nullptr; 1930 } 1931 1932 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 1933 llvm::GlobalVariable *Addr, 1934 bool PerformInit) { 1935 if (CGM.getLangOpts().OMPTargetTriples.empty() && 1936 !CGM.getLangOpts().OpenMPIsDevice) 1937 return false; 1938 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1939 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1940 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 1941 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1942 HasRequiresUnifiedSharedMemory)) 1943 return CGM.getLangOpts().OpenMPIsDevice; 1944 VD = VD->getDefinition(CGM.getContext()); 1945 assert(VD && "Unknown VarDecl"); 1946 1947 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 1948 return CGM.getLangOpts().OpenMPIsDevice; 1949 1950 QualType ASTTy = VD->getType(); 1951 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 1952 1953 // Produce the unique prefix to identify the new target regions. We use 1954 // the source location of the variable declaration which we know to not 1955 // conflict with any target region. 1956 unsigned DeviceID; 1957 unsigned FileID; 1958 unsigned Line; 1959 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 1960 SmallString<128> Buffer, Out; 1961 { 1962 llvm::raw_svector_ostream OS(Buffer); 1963 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 1964 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 1965 } 1966 1967 const Expr *Init = VD->getAnyInitializer(); 1968 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1969 llvm::Constant *Ctor; 1970 llvm::Constant *ID; 1971 if (CGM.getLangOpts().OpenMPIsDevice) { 1972 // Generate function that re-emits the declaration's initializer into 1973 // the threadprivate copy of the variable VD 1974 CodeGenFunction CtorCGF(CGM); 1975 1976 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1977 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1978 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 1979 FTy, Twine(Buffer, "_ctor"), FI, Loc); 1980 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 1981 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1982 FunctionArgList(), Loc, Loc); 1983 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 1984 CtorCGF.EmitAnyExprToMem(Init, 1985 Address(Addr, CGM.getContext().getDeclAlign(VD)), 1986 Init->getType().getQualifiers(), 1987 /*IsInitializer=*/true); 1988 CtorCGF.FinishFunction(); 1989 Ctor = Fn; 1990 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1991 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 1992 } else { 1993 Ctor = new llvm::GlobalVariable( 1994 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1995 llvm::GlobalValue::PrivateLinkage, 1996 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 1997 ID = Ctor; 1998 } 1999 2000 // Register the information for the entry associated with the constructor. 2001 Out.clear(); 2002 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2003 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2004 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2005 } 2006 if (VD->getType().isDestructedType() != QualType::DK_none) { 2007 llvm::Constant *Dtor; 2008 llvm::Constant *ID; 2009 if (CGM.getLangOpts().OpenMPIsDevice) { 2010 // Generate function that emits destructor call for the threadprivate 2011 // copy of the variable VD 2012 CodeGenFunction DtorCGF(CGM); 2013 2014 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2015 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2016 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2017 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2018 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2019 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2020 FunctionArgList(), Loc, Loc); 2021 // Create a scope with an artificial location for the body of this 2022 // function. 2023 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2024 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 2025 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2026 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2027 DtorCGF.FinishFunction(); 2028 Dtor = Fn; 2029 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2030 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 2031 } else { 2032 Dtor = new llvm::GlobalVariable( 2033 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2034 llvm::GlobalValue::PrivateLinkage, 2035 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 2036 ID = Dtor; 2037 } 2038 // Register the information for the entry associated with the destructor. 2039 Out.clear(); 2040 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2041 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2042 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2043 } 2044 return CGM.getLangOpts().OpenMPIsDevice; 2045 } 2046 2047 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2048 QualType VarType, 2049 StringRef Name) { 2050 std::string Suffix = getName({"artificial", ""}); 2051 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2052 llvm::Value *GAddr = 2053 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2054 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 2055 CGM.getTarget().isTLSSupported()) { 2056 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 2057 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 2058 } 2059 std::string CacheSuffix = getName({"cache", ""}); 2060 llvm::Value *Args[] = { 2061 emitUpdateLocation(CGF, SourceLocation()), 2062 getThreadID(CGF, SourceLocation()), 2063 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2064 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2065 /*isSigned=*/false), 2066 getOrCreateInternalVariable( 2067 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2068 return Address( 2069 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2070 CGF.EmitRuntimeCall( 2071 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2072 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 2073 Args), 2074 VarLVType->getPointerTo(/*AddrSpace=*/0)), 2075 CGM.getContext().getTypeAlignInChars(VarType)); 2076 } 2077 2078 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 2079 const RegionCodeGenTy &ThenGen, 2080 const RegionCodeGenTy &ElseGen) { 2081 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 2082 2083 // If the condition constant folds and can be elided, try to avoid emitting 2084 // the condition and the dead arm of the if/else. 2085 bool CondConstant; 2086 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 2087 if (CondConstant) 2088 ThenGen(CGF); 2089 else 2090 ElseGen(CGF); 2091 return; 2092 } 2093 2094 // Otherwise, the condition did not fold, or we couldn't elide it. Just 2095 // emit the conditional branch. 2096 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2097 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 2098 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 2099 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 2100 2101 // Emit the 'then' code. 2102 CGF.EmitBlock(ThenBlock); 2103 ThenGen(CGF); 2104 CGF.EmitBranch(ContBlock); 2105 // Emit the 'else' code if present. 2106 // There is no need to emit line number for unconditional branch. 2107 (void)ApplyDebugLocation::CreateEmpty(CGF); 2108 CGF.EmitBlock(ElseBlock); 2109 ElseGen(CGF); 2110 // There is no need to emit line number for unconditional branch. 2111 (void)ApplyDebugLocation::CreateEmpty(CGF); 2112 CGF.EmitBranch(ContBlock); 2113 // Emit the continuation block for code after the if. 2114 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 2115 } 2116 2117 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 2118 llvm::Function *OutlinedFn, 2119 ArrayRef<llvm::Value *> CapturedVars, 2120 const Expr *IfCond) { 2121 if (!CGF.HaveInsertPoint()) 2122 return; 2123 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 2124 auto &M = CGM.getModule(); 2125 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 2126 PrePostActionTy &) { 2127 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 2128 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2129 llvm::Value *Args[] = { 2130 RTLoc, 2131 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 2132 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 2133 llvm::SmallVector<llvm::Value *, 16> RealArgs; 2134 RealArgs.append(std::begin(Args), std::end(Args)); 2135 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 2136 2137 llvm::FunctionCallee RTLFn = 2138 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2139 M, OMPRTL___kmpc_fork_call); 2140 CGF.EmitRuntimeCall(RTLFn, RealArgs); 2141 }; 2142 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, 2143 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 2144 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2145 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 2146 // Build calls: 2147 // __kmpc_serialized_parallel(&Loc, GTid); 2148 llvm::Value *Args[] = {RTLoc, ThreadID}; 2149 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2150 M, OMPRTL___kmpc_serialized_parallel), 2151 Args); 2152 2153 // OutlinedFn(>id, &zero_bound, CapturedStruct); 2154 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 2155 Address ZeroAddrBound = 2156 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 2157 /*Name=*/".bound.zero.addr"); 2158 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 2159 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 2160 // ThreadId for serialized parallels is 0. 2161 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 2162 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 2163 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 2164 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 2165 2166 // __kmpc_end_serialized_parallel(&Loc, GTid); 2167 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 2168 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2169 M, OMPRTL___kmpc_end_serialized_parallel), 2170 EndArgs); 2171 }; 2172 if (IfCond) { 2173 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 2174 } else { 2175 RegionCodeGenTy ThenRCG(ThenGen); 2176 ThenRCG(CGF); 2177 } 2178 } 2179 2180 // If we're inside an (outlined) parallel region, use the region info's 2181 // thread-ID variable (it is passed in a first argument of the outlined function 2182 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 2183 // regular serial code region, get thread ID by calling kmp_int32 2184 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 2185 // return the address of that temp. 2186 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 2187 SourceLocation Loc) { 2188 if (auto *OMPRegionInfo = 2189 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2190 if (OMPRegionInfo->getThreadIDVariable()) 2191 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 2192 2193 llvm::Value *ThreadID = getThreadID(CGF, Loc); 2194 QualType Int32Ty = 2195 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 2196 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 2197 CGF.EmitStoreOfScalar(ThreadID, 2198 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 2199 2200 return ThreadIDTemp; 2201 } 2202 2203 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 2204 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 2205 SmallString<256> Buffer; 2206 llvm::raw_svector_ostream Out(Buffer); 2207 Out << Name; 2208 StringRef RuntimeName = Out.str(); 2209 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 2210 if (Elem.second) { 2211 assert(Elem.second->getType()->getPointerElementType() == Ty && 2212 "OMP internal variable has different type than requested"); 2213 return &*Elem.second; 2214 } 2215 2216 return Elem.second = new llvm::GlobalVariable( 2217 CGM.getModule(), Ty, /*IsConstant*/ false, 2218 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 2219 Elem.first(), /*InsertBefore=*/nullptr, 2220 llvm::GlobalValue::NotThreadLocal, AddressSpace); 2221 } 2222 2223 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 2224 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 2225 std::string Name = getName({Prefix, "var"}); 2226 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 2227 } 2228 2229 namespace { 2230 /// Common pre(post)-action for different OpenMP constructs. 2231 class CommonActionTy final : public PrePostActionTy { 2232 llvm::FunctionCallee EnterCallee; 2233 ArrayRef<llvm::Value *> EnterArgs; 2234 llvm::FunctionCallee ExitCallee; 2235 ArrayRef<llvm::Value *> ExitArgs; 2236 bool Conditional; 2237 llvm::BasicBlock *ContBlock = nullptr; 2238 2239 public: 2240 CommonActionTy(llvm::FunctionCallee EnterCallee, 2241 ArrayRef<llvm::Value *> EnterArgs, 2242 llvm::FunctionCallee ExitCallee, 2243 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 2244 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 2245 ExitArgs(ExitArgs), Conditional(Conditional) {} 2246 void Enter(CodeGenFunction &CGF) override { 2247 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 2248 if (Conditional) { 2249 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 2250 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2251 ContBlock = CGF.createBasicBlock("omp_if.end"); 2252 // Generate the branch (If-stmt) 2253 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 2254 CGF.EmitBlock(ThenBlock); 2255 } 2256 } 2257 void Done(CodeGenFunction &CGF) { 2258 // Emit the rest of blocks/branches 2259 CGF.EmitBranch(ContBlock); 2260 CGF.EmitBlock(ContBlock, true); 2261 } 2262 void Exit(CodeGenFunction &CGF) override { 2263 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 2264 } 2265 }; 2266 } // anonymous namespace 2267 2268 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 2269 StringRef CriticalName, 2270 const RegionCodeGenTy &CriticalOpGen, 2271 SourceLocation Loc, const Expr *Hint) { 2272 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 2273 // CriticalOpGen(); 2274 // __kmpc_end_critical(ident_t *, gtid, Lock); 2275 // Prepare arguments and build a call to __kmpc_critical 2276 if (!CGF.HaveInsertPoint()) 2277 return; 2278 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2279 getCriticalRegionLock(CriticalName)}; 2280 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 2281 std::end(Args)); 2282 if (Hint) { 2283 EnterArgs.push_back(CGF.Builder.CreateIntCast( 2284 CGF.EmitScalarExpr(Hint), CGM.Int32Ty, /*isSigned=*/false)); 2285 } 2286 CommonActionTy Action( 2287 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2288 CGM.getModule(), 2289 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical), 2290 EnterArgs, 2291 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2292 CGM.getModule(), OMPRTL___kmpc_end_critical), 2293 Args); 2294 CriticalOpGen.setAction(Action); 2295 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 2296 } 2297 2298 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 2299 const RegionCodeGenTy &MasterOpGen, 2300 SourceLocation Loc) { 2301 if (!CGF.HaveInsertPoint()) 2302 return; 2303 // if(__kmpc_master(ident_t *, gtid)) { 2304 // MasterOpGen(); 2305 // __kmpc_end_master(ident_t *, gtid); 2306 // } 2307 // Prepare arguments and build a call to __kmpc_master 2308 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2309 CommonActionTy Action(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2310 CGM.getModule(), OMPRTL___kmpc_master), 2311 Args, 2312 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2313 CGM.getModule(), OMPRTL___kmpc_end_master), 2314 Args, 2315 /*Conditional=*/true); 2316 MasterOpGen.setAction(Action); 2317 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 2318 Action.Done(CGF); 2319 } 2320 2321 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 2322 SourceLocation Loc) { 2323 if (!CGF.HaveInsertPoint()) 2324 return; 2325 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 2326 if (OMPBuilder) { 2327 OMPBuilder->CreateTaskyield(CGF.Builder); 2328 } else { 2329 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 2330 llvm::Value *Args[] = { 2331 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2332 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 2333 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2334 CGM.getModule(), OMPRTL___kmpc_omp_taskyield), 2335 Args); 2336 } 2337 2338 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2339 Region->emitUntiedSwitch(CGF); 2340 } 2341 2342 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 2343 const RegionCodeGenTy &TaskgroupOpGen, 2344 SourceLocation Loc) { 2345 if (!CGF.HaveInsertPoint()) 2346 return; 2347 // __kmpc_taskgroup(ident_t *, gtid); 2348 // TaskgroupOpGen(); 2349 // __kmpc_end_taskgroup(ident_t *, gtid); 2350 // Prepare arguments and build a call to __kmpc_taskgroup 2351 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2352 CommonActionTy Action(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2353 CGM.getModule(), OMPRTL___kmpc_taskgroup), 2354 Args, 2355 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2356 CGM.getModule(), OMPRTL___kmpc_end_taskgroup), 2357 Args); 2358 TaskgroupOpGen.setAction(Action); 2359 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 2360 } 2361 2362 /// Given an array of pointers to variables, project the address of a 2363 /// given variable. 2364 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 2365 unsigned Index, const VarDecl *Var) { 2366 // Pull out the pointer to the variable. 2367 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 2368 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 2369 2370 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 2371 Addr = CGF.Builder.CreateElementBitCast( 2372 Addr, CGF.ConvertTypeForMem(Var->getType())); 2373 return Addr; 2374 } 2375 2376 static llvm::Value *emitCopyprivateCopyFunction( 2377 CodeGenModule &CGM, llvm::Type *ArgsType, 2378 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 2379 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 2380 SourceLocation Loc) { 2381 ASTContext &C = CGM.getContext(); 2382 // void copy_func(void *LHSArg, void *RHSArg); 2383 FunctionArgList Args; 2384 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2385 ImplicitParamDecl::Other); 2386 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2387 ImplicitParamDecl::Other); 2388 Args.push_back(&LHSArg); 2389 Args.push_back(&RHSArg); 2390 const auto &CGFI = 2391 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2392 std::string Name = 2393 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 2394 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 2395 llvm::GlobalValue::InternalLinkage, Name, 2396 &CGM.getModule()); 2397 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 2398 Fn->setDoesNotRecurse(); 2399 CodeGenFunction CGF(CGM); 2400 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 2401 // Dest = (void*[n])(LHSArg); 2402 // Src = (void*[n])(RHSArg); 2403 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2404 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 2405 ArgsType), CGF.getPointerAlign()); 2406 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2407 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 2408 ArgsType), CGF.getPointerAlign()); 2409 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 2410 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 2411 // ... 2412 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 2413 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 2414 const auto *DestVar = 2415 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 2416 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 2417 2418 const auto *SrcVar = 2419 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 2420 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 2421 2422 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 2423 QualType Type = VD->getType(); 2424 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 2425 } 2426 CGF.FinishFunction(); 2427 return Fn; 2428 } 2429 2430 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 2431 const RegionCodeGenTy &SingleOpGen, 2432 SourceLocation Loc, 2433 ArrayRef<const Expr *> CopyprivateVars, 2434 ArrayRef<const Expr *> SrcExprs, 2435 ArrayRef<const Expr *> DstExprs, 2436 ArrayRef<const Expr *> AssignmentOps) { 2437 if (!CGF.HaveInsertPoint()) 2438 return; 2439 assert(CopyprivateVars.size() == SrcExprs.size() && 2440 CopyprivateVars.size() == DstExprs.size() && 2441 CopyprivateVars.size() == AssignmentOps.size()); 2442 ASTContext &C = CGM.getContext(); 2443 // int32 did_it = 0; 2444 // if(__kmpc_single(ident_t *, gtid)) { 2445 // SingleOpGen(); 2446 // __kmpc_end_single(ident_t *, gtid); 2447 // did_it = 1; 2448 // } 2449 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2450 // <copy_func>, did_it); 2451 2452 Address DidIt = Address::invalid(); 2453 if (!CopyprivateVars.empty()) { 2454 // int32 did_it = 0; 2455 QualType KmpInt32Ty = 2456 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2457 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 2458 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 2459 } 2460 // Prepare arguments and build a call to __kmpc_single 2461 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2462 CommonActionTy Action(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2463 CGM.getModule(), OMPRTL___kmpc_single), 2464 Args, 2465 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2466 CGM.getModule(), OMPRTL___kmpc_end_single), 2467 Args, 2468 /*Conditional=*/true); 2469 SingleOpGen.setAction(Action); 2470 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 2471 if (DidIt.isValid()) { 2472 // did_it = 1; 2473 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 2474 } 2475 Action.Done(CGF); 2476 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2477 // <copy_func>, did_it); 2478 if (DidIt.isValid()) { 2479 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 2480 QualType CopyprivateArrayTy = C.getConstantArrayType( 2481 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 2482 /*IndexTypeQuals=*/0); 2483 // Create a list of all private variables for copyprivate. 2484 Address CopyprivateList = 2485 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 2486 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 2487 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 2488 CGF.Builder.CreateStore( 2489 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2490 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 2491 CGF.VoidPtrTy), 2492 Elem); 2493 } 2494 // Build function that copies private values from single region to all other 2495 // threads in the corresponding parallel region. 2496 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 2497 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 2498 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 2499 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 2500 Address CL = 2501 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 2502 CGF.VoidPtrTy); 2503 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 2504 llvm::Value *Args[] = { 2505 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 2506 getThreadID(CGF, Loc), // i32 <gtid> 2507 BufSize, // size_t <buf_size> 2508 CL.getPointer(), // void *<copyprivate list> 2509 CpyFn, // void (*) (void *, void *) <copy_func> 2510 DidItVal // i32 did_it 2511 }; 2512 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2513 CGM.getModule(), OMPRTL___kmpc_copyprivate), 2514 Args); 2515 } 2516 } 2517 2518 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 2519 const RegionCodeGenTy &OrderedOpGen, 2520 SourceLocation Loc, bool IsThreads) { 2521 if (!CGF.HaveInsertPoint()) 2522 return; 2523 // __kmpc_ordered(ident_t *, gtid); 2524 // OrderedOpGen(); 2525 // __kmpc_end_ordered(ident_t *, gtid); 2526 // Prepare arguments and build a call to __kmpc_ordered 2527 if (IsThreads) { 2528 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2529 CommonActionTy Action(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2530 CGM.getModule(), OMPRTL___kmpc_ordered), 2531 Args, 2532 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2533 CGM.getModule(), OMPRTL___kmpc_end_ordered), 2534 Args); 2535 OrderedOpGen.setAction(Action); 2536 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2537 return; 2538 } 2539 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2540 } 2541 2542 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 2543 unsigned Flags; 2544 if (Kind == OMPD_for) 2545 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 2546 else if (Kind == OMPD_sections) 2547 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 2548 else if (Kind == OMPD_single) 2549 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 2550 else if (Kind == OMPD_barrier) 2551 Flags = OMP_IDENT_BARRIER_EXPL; 2552 else 2553 Flags = OMP_IDENT_BARRIER_IMPL; 2554 return Flags; 2555 } 2556 2557 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 2558 CodeGenFunction &CGF, const OMPLoopDirective &S, 2559 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 2560 // Check if the loop directive is actually a doacross loop directive. In this 2561 // case choose static, 1 schedule. 2562 if (llvm::any_of( 2563 S.getClausesOfKind<OMPOrderedClause>(), 2564 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 2565 ScheduleKind = OMPC_SCHEDULE_static; 2566 // Chunk size is 1 in this case. 2567 llvm::APInt ChunkSize(32, 1); 2568 ChunkExpr = IntegerLiteral::Create( 2569 CGF.getContext(), ChunkSize, 2570 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 2571 SourceLocation()); 2572 } 2573 } 2574 2575 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 2576 OpenMPDirectiveKind Kind, bool EmitChecks, 2577 bool ForceSimpleCall) { 2578 // Check if we should use the OMPBuilder 2579 auto *OMPRegionInfo = 2580 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 2581 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 2582 if (OMPBuilder) { 2583 CGF.Builder.restoreIP(OMPBuilder->CreateBarrier( 2584 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 2585 return; 2586 } 2587 2588 if (!CGF.HaveInsertPoint()) 2589 return; 2590 // Build call __kmpc_cancel_barrier(loc, thread_id); 2591 // Build call __kmpc_barrier(loc, thread_id); 2592 unsigned Flags = getDefaultFlagsForBarriers(Kind); 2593 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 2594 // thread_id); 2595 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 2596 getThreadID(CGF, Loc)}; 2597 if (OMPRegionInfo) { 2598 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 2599 llvm::Value *Result = CGF.EmitRuntimeCall( 2600 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2601 CGM.getModule(), OMPRTL___kmpc_cancel_barrier), 2602 Args); 2603 if (EmitChecks) { 2604 // if (__kmpc_cancel_barrier()) { 2605 // exit from construct; 2606 // } 2607 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2608 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 2609 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 2610 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2611 CGF.EmitBlock(ExitBB); 2612 // exit from construct; 2613 CodeGenFunction::JumpDest CancelDestination = 2614 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2615 CGF.EmitBranchThroughCleanup(CancelDestination); 2616 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2617 } 2618 return; 2619 } 2620 } 2621 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2622 CGM.getModule(), OMPRTL___kmpc_barrier), 2623 Args); 2624 } 2625 2626 /// Map the OpenMP loop schedule to the runtime enumeration. 2627 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 2628 bool Chunked, bool Ordered) { 2629 switch (ScheduleKind) { 2630 case OMPC_SCHEDULE_static: 2631 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 2632 : (Ordered ? OMP_ord_static : OMP_sch_static); 2633 case OMPC_SCHEDULE_dynamic: 2634 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 2635 case OMPC_SCHEDULE_guided: 2636 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 2637 case OMPC_SCHEDULE_runtime: 2638 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 2639 case OMPC_SCHEDULE_auto: 2640 return Ordered ? OMP_ord_auto : OMP_sch_auto; 2641 case OMPC_SCHEDULE_unknown: 2642 assert(!Chunked && "chunk was specified but schedule kind not known"); 2643 return Ordered ? OMP_ord_static : OMP_sch_static; 2644 } 2645 llvm_unreachable("Unexpected runtime schedule"); 2646 } 2647 2648 /// Map the OpenMP distribute schedule to the runtime enumeration. 2649 static OpenMPSchedType 2650 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 2651 // only static is allowed for dist_schedule 2652 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 2653 } 2654 2655 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 2656 bool Chunked) const { 2657 OpenMPSchedType Schedule = 2658 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2659 return Schedule == OMP_sch_static; 2660 } 2661 2662 bool CGOpenMPRuntime::isStaticNonchunked( 2663 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2664 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2665 return Schedule == OMP_dist_sch_static; 2666 } 2667 2668 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 2669 bool Chunked) const { 2670 OpenMPSchedType Schedule = 2671 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2672 return Schedule == OMP_sch_static_chunked; 2673 } 2674 2675 bool CGOpenMPRuntime::isStaticChunked( 2676 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2677 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2678 return Schedule == OMP_dist_sch_static_chunked; 2679 } 2680 2681 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 2682 OpenMPSchedType Schedule = 2683 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 2684 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 2685 return Schedule != OMP_sch_static; 2686 } 2687 2688 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 2689 OpenMPScheduleClauseModifier M1, 2690 OpenMPScheduleClauseModifier M2) { 2691 int Modifier = 0; 2692 switch (M1) { 2693 case OMPC_SCHEDULE_MODIFIER_monotonic: 2694 Modifier = OMP_sch_modifier_monotonic; 2695 break; 2696 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2697 Modifier = OMP_sch_modifier_nonmonotonic; 2698 break; 2699 case OMPC_SCHEDULE_MODIFIER_simd: 2700 if (Schedule == OMP_sch_static_chunked) 2701 Schedule = OMP_sch_static_balanced_chunked; 2702 break; 2703 case OMPC_SCHEDULE_MODIFIER_last: 2704 case OMPC_SCHEDULE_MODIFIER_unknown: 2705 break; 2706 } 2707 switch (M2) { 2708 case OMPC_SCHEDULE_MODIFIER_monotonic: 2709 Modifier = OMP_sch_modifier_monotonic; 2710 break; 2711 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2712 Modifier = OMP_sch_modifier_nonmonotonic; 2713 break; 2714 case OMPC_SCHEDULE_MODIFIER_simd: 2715 if (Schedule == OMP_sch_static_chunked) 2716 Schedule = OMP_sch_static_balanced_chunked; 2717 break; 2718 case OMPC_SCHEDULE_MODIFIER_last: 2719 case OMPC_SCHEDULE_MODIFIER_unknown: 2720 break; 2721 } 2722 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 2723 // If the static schedule kind is specified or if the ordered clause is 2724 // specified, and if the nonmonotonic modifier is not specified, the effect is 2725 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 2726 // modifier is specified, the effect is as if the nonmonotonic modifier is 2727 // specified. 2728 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 2729 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 2730 Schedule == OMP_sch_static_balanced_chunked || 2731 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 2732 Schedule == OMP_dist_sch_static_chunked || 2733 Schedule == OMP_dist_sch_static)) 2734 Modifier = OMP_sch_modifier_nonmonotonic; 2735 } 2736 return Schedule | Modifier; 2737 } 2738 2739 void CGOpenMPRuntime::emitForDispatchInit( 2740 CodeGenFunction &CGF, SourceLocation Loc, 2741 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 2742 bool Ordered, const DispatchRTInput &DispatchValues) { 2743 if (!CGF.HaveInsertPoint()) 2744 return; 2745 OpenMPSchedType Schedule = getRuntimeSchedule( 2746 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 2747 assert(Ordered || 2748 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 2749 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 2750 Schedule != OMP_sch_static_balanced_chunked)); 2751 // Call __kmpc_dispatch_init( 2752 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 2753 // kmp_int[32|64] lower, kmp_int[32|64] upper, 2754 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 2755 2756 // If the Chunk was not specified in the clause - use default value 1. 2757 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 2758 : CGF.Builder.getIntN(IVSize, 1); 2759 llvm::Value *Args[] = { 2760 emitUpdateLocation(CGF, Loc), 2761 getThreadID(CGF, Loc), 2762 CGF.Builder.getInt32(addMonoNonMonoModifier( 2763 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 2764 DispatchValues.LB, // Lower 2765 DispatchValues.UB, // Upper 2766 CGF.Builder.getIntN(IVSize, 1), // Stride 2767 Chunk // Chunk 2768 }; 2769 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 2770 } 2771 2772 static void emitForStaticInitCall( 2773 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 2774 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 2775 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 2776 const CGOpenMPRuntime::StaticRTInput &Values) { 2777 if (!CGF.HaveInsertPoint()) 2778 return; 2779 2780 assert(!Values.Ordered); 2781 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 2782 Schedule == OMP_sch_static_balanced_chunked || 2783 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 2784 Schedule == OMP_dist_sch_static || 2785 Schedule == OMP_dist_sch_static_chunked); 2786 2787 // Call __kmpc_for_static_init( 2788 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 2789 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 2790 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 2791 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 2792 llvm::Value *Chunk = Values.Chunk; 2793 if (Chunk == nullptr) { 2794 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 2795 Schedule == OMP_dist_sch_static) && 2796 "expected static non-chunked schedule"); 2797 // If the Chunk was not specified in the clause - use default value 1. 2798 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 2799 } else { 2800 assert((Schedule == OMP_sch_static_chunked || 2801 Schedule == OMP_sch_static_balanced_chunked || 2802 Schedule == OMP_ord_static_chunked || 2803 Schedule == OMP_dist_sch_static_chunked) && 2804 "expected static chunked schedule"); 2805 } 2806 llvm::Value *Args[] = { 2807 UpdateLocation, 2808 ThreadId, 2809 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 2810 M2)), // Schedule type 2811 Values.IL.getPointer(), // &isLastIter 2812 Values.LB.getPointer(), // &LB 2813 Values.UB.getPointer(), // &UB 2814 Values.ST.getPointer(), // &Stride 2815 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 2816 Chunk // Chunk 2817 }; 2818 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 2819 } 2820 2821 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 2822 SourceLocation Loc, 2823 OpenMPDirectiveKind DKind, 2824 const OpenMPScheduleTy &ScheduleKind, 2825 const StaticRTInput &Values) { 2826 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 2827 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 2828 assert(isOpenMPWorksharingDirective(DKind) && 2829 "Expected loop-based or sections-based directive."); 2830 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 2831 isOpenMPLoopDirective(DKind) 2832 ? OMP_IDENT_WORK_LOOP 2833 : OMP_IDENT_WORK_SECTIONS); 2834 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2835 llvm::FunctionCallee StaticInitFunction = 2836 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 2837 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2838 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2839 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 2840 } 2841 2842 void CGOpenMPRuntime::emitDistributeStaticInit( 2843 CodeGenFunction &CGF, SourceLocation Loc, 2844 OpenMPDistScheduleClauseKind SchedKind, 2845 const CGOpenMPRuntime::StaticRTInput &Values) { 2846 OpenMPSchedType ScheduleNum = 2847 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 2848 llvm::Value *UpdatedLocation = 2849 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 2850 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2851 llvm::FunctionCallee StaticInitFunction = 2852 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 2853 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2854 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 2855 OMPC_SCHEDULE_MODIFIER_unknown, Values); 2856 } 2857 2858 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 2859 SourceLocation Loc, 2860 OpenMPDirectiveKind DKind) { 2861 if (!CGF.HaveInsertPoint()) 2862 return; 2863 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 2864 llvm::Value *Args[] = { 2865 emitUpdateLocation(CGF, Loc, 2866 isOpenMPDistributeDirective(DKind) 2867 ? OMP_IDENT_WORK_DISTRIBUTE 2868 : isOpenMPLoopDirective(DKind) 2869 ? OMP_IDENT_WORK_LOOP 2870 : OMP_IDENT_WORK_SECTIONS), 2871 getThreadID(CGF, Loc)}; 2872 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2873 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2874 CGM.getModule(), OMPRTL___kmpc_for_static_fini), 2875 Args); 2876 } 2877 2878 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 2879 SourceLocation Loc, 2880 unsigned IVSize, 2881 bool IVSigned) { 2882 if (!CGF.HaveInsertPoint()) 2883 return; 2884 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 2885 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2886 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 2887 } 2888 2889 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 2890 SourceLocation Loc, unsigned IVSize, 2891 bool IVSigned, Address IL, 2892 Address LB, Address UB, 2893 Address ST) { 2894 // Call __kmpc_dispatch_next( 2895 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 2896 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 2897 // kmp_int[32|64] *p_stride); 2898 llvm::Value *Args[] = { 2899 emitUpdateLocation(CGF, Loc), 2900 getThreadID(CGF, Loc), 2901 IL.getPointer(), // &isLastIter 2902 LB.getPointer(), // &Lower 2903 UB.getPointer(), // &Upper 2904 ST.getPointer() // &Stride 2905 }; 2906 llvm::Value *Call = 2907 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 2908 return CGF.EmitScalarConversion( 2909 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 2910 CGF.getContext().BoolTy, Loc); 2911 } 2912 2913 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 2914 llvm::Value *NumThreads, 2915 SourceLocation Loc) { 2916 if (!CGF.HaveInsertPoint()) 2917 return; 2918 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 2919 llvm::Value *Args[] = { 2920 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2921 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 2922 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2923 CGM.getModule(), OMPRTL___kmpc_push_num_threads), 2924 Args); 2925 } 2926 2927 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 2928 ProcBindKind ProcBind, 2929 SourceLocation Loc) { 2930 if (!CGF.HaveInsertPoint()) 2931 return; 2932 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 2933 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 2934 llvm::Value *Args[] = { 2935 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2936 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 2937 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2938 CGM.getModule(), OMPRTL___kmpc_push_proc_bind), 2939 Args); 2940 } 2941 2942 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 2943 SourceLocation Loc, llvm::AtomicOrdering AO) { 2944 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 2945 if (OMPBuilder) { 2946 OMPBuilder->CreateFlush(CGF.Builder); 2947 } else { 2948 if (!CGF.HaveInsertPoint()) 2949 return; 2950 // Build call void __kmpc_flush(ident_t *loc) 2951 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 2952 CGM.getModule(), OMPRTL___kmpc_flush), 2953 emitUpdateLocation(CGF, Loc)); 2954 } 2955 } 2956 2957 namespace { 2958 /// Indexes of fields for type kmp_task_t. 2959 enum KmpTaskTFields { 2960 /// List of shared variables. 2961 KmpTaskTShareds, 2962 /// Task routine. 2963 KmpTaskTRoutine, 2964 /// Partition id for the untied tasks. 2965 KmpTaskTPartId, 2966 /// Function with call of destructors for private variables. 2967 Data1, 2968 /// Task priority. 2969 Data2, 2970 /// (Taskloops only) Lower bound. 2971 KmpTaskTLowerBound, 2972 /// (Taskloops only) Upper bound. 2973 KmpTaskTUpperBound, 2974 /// (Taskloops only) Stride. 2975 KmpTaskTStride, 2976 /// (Taskloops only) Is last iteration flag. 2977 KmpTaskTLastIter, 2978 /// (Taskloops only) Reduction data. 2979 KmpTaskTReductions, 2980 }; 2981 } // anonymous namespace 2982 2983 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 2984 return OffloadEntriesTargetRegion.empty() && 2985 OffloadEntriesDeviceGlobalVar.empty(); 2986 } 2987 2988 /// Initialize target region entry. 2989 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2990 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2991 StringRef ParentName, unsigned LineNum, 2992 unsigned Order) { 2993 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 2994 "only required for the device " 2995 "code generation."); 2996 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 2997 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 2998 OMPTargetRegionEntryTargetRegion); 2999 ++OffloadingEntriesNum; 3000 } 3001 3002 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3003 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3004 StringRef ParentName, unsigned LineNum, 3005 llvm::Constant *Addr, llvm::Constant *ID, 3006 OMPTargetRegionEntryKind Flags) { 3007 // If we are emitting code for a target, the entry is already initialized, 3008 // only has to be registered. 3009 if (CGM.getLangOpts().OpenMPIsDevice) { 3010 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3011 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3012 DiagnosticsEngine::Error, 3013 "Unable to find target region on line '%0' in the device code."); 3014 CGM.getDiags().Report(DiagID) << LineNum; 3015 return; 3016 } 3017 auto &Entry = 3018 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3019 assert(Entry.isValid() && "Entry not initialized!"); 3020 Entry.setAddress(Addr); 3021 Entry.setID(ID); 3022 Entry.setFlags(Flags); 3023 } else { 3024 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3025 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3026 ++OffloadingEntriesNum; 3027 } 3028 } 3029 3030 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3031 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3032 unsigned LineNum) const { 3033 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3034 if (PerDevice == OffloadEntriesTargetRegion.end()) 3035 return false; 3036 auto PerFile = PerDevice->second.find(FileID); 3037 if (PerFile == PerDevice->second.end()) 3038 return false; 3039 auto PerParentName = PerFile->second.find(ParentName); 3040 if (PerParentName == PerFile->second.end()) 3041 return false; 3042 auto PerLine = PerParentName->second.find(LineNum); 3043 if (PerLine == PerParentName->second.end()) 3044 return false; 3045 // Fail if this entry is already registered. 3046 if (PerLine->second.getAddress() || PerLine->second.getID()) 3047 return false; 3048 return true; 3049 } 3050 3051 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3052 const OffloadTargetRegionEntryInfoActTy &Action) { 3053 // Scan all target region entries and perform the provided action. 3054 for (const auto &D : OffloadEntriesTargetRegion) 3055 for (const auto &F : D.second) 3056 for (const auto &P : F.second) 3057 for (const auto &L : P.second) 3058 Action(D.first, F.first, P.first(), L.first, L.second); 3059 } 3060 3061 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3062 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3063 OMPTargetGlobalVarEntryKind Flags, 3064 unsigned Order) { 3065 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3066 "only required for the device " 3067 "code generation."); 3068 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3069 ++OffloadingEntriesNum; 3070 } 3071 3072 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3073 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3074 CharUnits VarSize, 3075 OMPTargetGlobalVarEntryKind Flags, 3076 llvm::GlobalValue::LinkageTypes Linkage) { 3077 if (CGM.getLangOpts().OpenMPIsDevice) { 3078 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3079 assert(Entry.isValid() && Entry.getFlags() == Flags && 3080 "Entry not initialized!"); 3081 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3082 "Resetting with the new address."); 3083 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3084 if (Entry.getVarSize().isZero()) { 3085 Entry.setVarSize(VarSize); 3086 Entry.setLinkage(Linkage); 3087 } 3088 return; 3089 } 3090 Entry.setVarSize(VarSize); 3091 Entry.setLinkage(Linkage); 3092 Entry.setAddress(Addr); 3093 } else { 3094 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3095 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3096 assert(Entry.isValid() && Entry.getFlags() == Flags && 3097 "Entry not initialized!"); 3098 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3099 "Resetting with the new address."); 3100 if (Entry.getVarSize().isZero()) { 3101 Entry.setVarSize(VarSize); 3102 Entry.setLinkage(Linkage); 3103 } 3104 return; 3105 } 3106 OffloadEntriesDeviceGlobalVar.try_emplace( 3107 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3108 ++OffloadingEntriesNum; 3109 } 3110 } 3111 3112 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3113 actOnDeviceGlobalVarEntriesInfo( 3114 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 3115 // Scan all target region entries and perform the provided action. 3116 for (const auto &E : OffloadEntriesDeviceGlobalVar) 3117 Action(E.getKey(), E.getValue()); 3118 } 3119 3120 void CGOpenMPRuntime::createOffloadEntry( 3121 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 3122 llvm::GlobalValue::LinkageTypes Linkage) { 3123 StringRef Name = Addr->getName(); 3124 llvm::Module &M = CGM.getModule(); 3125 llvm::LLVMContext &C = M.getContext(); 3126 3127 // Create constant string with the name. 3128 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 3129 3130 std::string StringName = getName({"omp_offloading", "entry_name"}); 3131 auto *Str = new llvm::GlobalVariable( 3132 M, StrPtrInit->getType(), /*isConstant=*/true, 3133 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 3134 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 3135 3136 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 3137 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 3138 llvm::ConstantInt::get(CGM.SizeTy, Size), 3139 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 3140 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 3141 std::string EntryName = getName({"omp_offloading", "entry", ""}); 3142 llvm::GlobalVariable *Entry = createGlobalStruct( 3143 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 3144 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 3145 3146 // The entry has to be created in the section the linker expects it to be. 3147 Entry->setSection("omp_offloading_entries"); 3148 } 3149 3150 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 3151 // Emit the offloading entries and metadata so that the device codegen side 3152 // can easily figure out what to emit. The produced metadata looks like 3153 // this: 3154 // 3155 // !omp_offload.info = !{!1, ...} 3156 // 3157 // Right now we only generate metadata for function that contain target 3158 // regions. 3159 3160 // If we are in simd mode or there are no entries, we don't need to do 3161 // anything. 3162 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 3163 return; 3164 3165 llvm::Module &M = CGM.getModule(); 3166 llvm::LLVMContext &C = M.getContext(); 3167 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 3168 SourceLocation, StringRef>, 3169 16> 3170 OrderedEntries(OffloadEntriesInfoManager.size()); 3171 llvm::SmallVector<StringRef, 16> ParentFunctions( 3172 OffloadEntriesInfoManager.size()); 3173 3174 // Auxiliary methods to create metadata values and strings. 3175 auto &&GetMDInt = [this](unsigned V) { 3176 return llvm::ConstantAsMetadata::get( 3177 llvm::ConstantInt::get(CGM.Int32Ty, V)); 3178 }; 3179 3180 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 3181 3182 // Create the offloading info metadata node. 3183 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 3184 3185 // Create function that emits metadata for each target region entry; 3186 auto &&TargetRegionMetadataEmitter = 3187 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 3188 &GetMDString]( 3189 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3190 unsigned Line, 3191 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 3192 // Generate metadata for target regions. Each entry of this metadata 3193 // contains: 3194 // - Entry 0 -> Kind of this type of metadata (0). 3195 // - Entry 1 -> Device ID of the file where the entry was identified. 3196 // - Entry 2 -> File ID of the file where the entry was identified. 3197 // - Entry 3 -> Mangled name of the function where the entry was 3198 // identified. 3199 // - Entry 4 -> Line in the file where the entry was identified. 3200 // - Entry 5 -> Order the entry was created. 3201 // The first element of the metadata node is the kind. 3202 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 3203 GetMDInt(FileID), GetMDString(ParentName), 3204 GetMDInt(Line), GetMDInt(E.getOrder())}; 3205 3206 SourceLocation Loc; 3207 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 3208 E = CGM.getContext().getSourceManager().fileinfo_end(); 3209 I != E; ++I) { 3210 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 3211 I->getFirst()->getUniqueID().getFile() == FileID) { 3212 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 3213 I->getFirst(), Line, 1); 3214 break; 3215 } 3216 } 3217 // Save this entry in the right position of the ordered entries array. 3218 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 3219 ParentFunctions[E.getOrder()] = ParentName; 3220 3221 // Add metadata to the named metadata node. 3222 MD->addOperand(llvm::MDNode::get(C, Ops)); 3223 }; 3224 3225 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 3226 TargetRegionMetadataEmitter); 3227 3228 // Create function that emits metadata for each device global variable entry; 3229 auto &&DeviceGlobalVarMetadataEmitter = 3230 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 3231 MD](StringRef MangledName, 3232 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 3233 &E) { 3234 // Generate metadata for global variables. Each entry of this metadata 3235 // contains: 3236 // - Entry 0 -> Kind of this type of metadata (1). 3237 // - Entry 1 -> Mangled name of the variable. 3238 // - Entry 2 -> Declare target kind. 3239 // - Entry 3 -> Order the entry was created. 3240 // The first element of the metadata node is the kind. 3241 llvm::Metadata *Ops[] = { 3242 GetMDInt(E.getKind()), GetMDString(MangledName), 3243 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 3244 3245 // Save this entry in the right position of the ordered entries array. 3246 OrderedEntries[E.getOrder()] = 3247 std::make_tuple(&E, SourceLocation(), MangledName); 3248 3249 // Add metadata to the named metadata node. 3250 MD->addOperand(llvm::MDNode::get(C, Ops)); 3251 }; 3252 3253 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 3254 DeviceGlobalVarMetadataEmitter); 3255 3256 for (const auto &E : OrderedEntries) { 3257 assert(std::get<0>(E) && "All ordered entries must exist!"); 3258 if (const auto *CE = 3259 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 3260 std::get<0>(E))) { 3261 if (!CE->getID() || !CE->getAddress()) { 3262 // Do not blame the entry if the parent funtion is not emitted. 3263 StringRef FnName = ParentFunctions[CE->getOrder()]; 3264 if (!CGM.GetGlobalValue(FnName)) 3265 continue; 3266 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3267 DiagnosticsEngine::Error, 3268 "Offloading entry for target region in %0 is incorrect: either the " 3269 "address or the ID is invalid."); 3270 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 3271 continue; 3272 } 3273 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 3274 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 3275 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 3276 OffloadEntryInfoDeviceGlobalVar>( 3277 std::get<0>(E))) { 3278 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 3279 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3280 CE->getFlags()); 3281 switch (Flags) { 3282 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 3283 if (CGM.getLangOpts().OpenMPIsDevice && 3284 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 3285 continue; 3286 if (!CE->getAddress()) { 3287 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3288 DiagnosticsEngine::Error, "Offloading entry for declare target " 3289 "variable %0 is incorrect: the " 3290 "address is invalid."); 3291 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 3292 continue; 3293 } 3294 // The vaiable has no definition - no need to add the entry. 3295 if (CE->getVarSize().isZero()) 3296 continue; 3297 break; 3298 } 3299 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 3300 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 3301 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 3302 "Declaret target link address is set."); 3303 if (CGM.getLangOpts().OpenMPIsDevice) 3304 continue; 3305 if (!CE->getAddress()) { 3306 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3307 DiagnosticsEngine::Error, 3308 "Offloading entry for declare target variable is incorrect: the " 3309 "address is invalid."); 3310 CGM.getDiags().Report(DiagID); 3311 continue; 3312 } 3313 break; 3314 } 3315 createOffloadEntry(CE->getAddress(), CE->getAddress(), 3316 CE->getVarSize().getQuantity(), Flags, 3317 CE->getLinkage()); 3318 } else { 3319 llvm_unreachable("Unsupported entry kind."); 3320 } 3321 } 3322 } 3323 3324 /// Loads all the offload entries information from the host IR 3325 /// metadata. 3326 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 3327 // If we are in target mode, load the metadata from the host IR. This code has 3328 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 3329 3330 if (!CGM.getLangOpts().OpenMPIsDevice) 3331 return; 3332 3333 if (CGM.getLangOpts().OMPHostIRFile.empty()) 3334 return; 3335 3336 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 3337 if (auto EC = Buf.getError()) { 3338 CGM.getDiags().Report(diag::err_cannot_open_file) 3339 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3340 return; 3341 } 3342 3343 llvm::LLVMContext C; 3344 auto ME = expectedToErrorOrAndEmitErrors( 3345 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 3346 3347 if (auto EC = ME.getError()) { 3348 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3349 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 3350 CGM.getDiags().Report(DiagID) 3351 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3352 return; 3353 } 3354 3355 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 3356 if (!MD) 3357 return; 3358 3359 for (llvm::MDNode *MN : MD->operands()) { 3360 auto &&GetMDInt = [MN](unsigned Idx) { 3361 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 3362 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 3363 }; 3364 3365 auto &&GetMDString = [MN](unsigned Idx) { 3366 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 3367 return V->getString(); 3368 }; 3369 3370 switch (GetMDInt(0)) { 3371 default: 3372 llvm_unreachable("Unexpected metadata!"); 3373 break; 3374 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3375 OffloadingEntryInfoTargetRegion: 3376 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 3377 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 3378 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 3379 /*Order=*/GetMDInt(5)); 3380 break; 3381 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3382 OffloadingEntryInfoDeviceGlobalVar: 3383 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 3384 /*MangledName=*/GetMDString(1), 3385 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3386 /*Flags=*/GetMDInt(2)), 3387 /*Order=*/GetMDInt(3)); 3388 break; 3389 } 3390 } 3391 } 3392 3393 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 3394 if (!KmpRoutineEntryPtrTy) { 3395 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 3396 ASTContext &C = CGM.getContext(); 3397 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 3398 FunctionProtoType::ExtProtoInfo EPI; 3399 KmpRoutineEntryPtrQTy = C.getPointerType( 3400 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 3401 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 3402 } 3403 } 3404 3405 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 3406 // Make sure the type of the entry is already created. This is the type we 3407 // have to create: 3408 // struct __tgt_offload_entry{ 3409 // void *addr; // Pointer to the offload entry info. 3410 // // (function or global) 3411 // char *name; // Name of the function or global. 3412 // size_t size; // Size of the entry info (0 if it a function). 3413 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 3414 // int32_t reserved; // Reserved, to use by the runtime library. 3415 // }; 3416 if (TgtOffloadEntryQTy.isNull()) { 3417 ASTContext &C = CGM.getContext(); 3418 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 3419 RD->startDefinition(); 3420 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3421 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 3422 addFieldToRecordDecl(C, RD, C.getSizeType()); 3423 addFieldToRecordDecl( 3424 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3425 addFieldToRecordDecl( 3426 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3427 RD->completeDefinition(); 3428 RD->addAttr(PackedAttr::CreateImplicit(C)); 3429 TgtOffloadEntryQTy = C.getRecordType(RD); 3430 } 3431 return TgtOffloadEntryQTy; 3432 } 3433 3434 namespace { 3435 struct PrivateHelpersTy { 3436 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original, 3437 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit) 3438 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy), 3439 PrivateElemInit(PrivateElemInit) {} 3440 const Expr *OriginalRef = nullptr; 3441 const VarDecl *Original = nullptr; 3442 const VarDecl *PrivateCopy = nullptr; 3443 const VarDecl *PrivateElemInit = nullptr; 3444 }; 3445 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 3446 } // anonymous namespace 3447 3448 static RecordDecl * 3449 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 3450 if (!Privates.empty()) { 3451 ASTContext &C = CGM.getContext(); 3452 // Build struct .kmp_privates_t. { 3453 // /* private vars */ 3454 // }; 3455 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 3456 RD->startDefinition(); 3457 for (const auto &Pair : Privates) { 3458 const VarDecl *VD = Pair.second.Original; 3459 QualType Type = VD->getType().getNonReferenceType(); 3460 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 3461 if (VD->hasAttrs()) { 3462 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 3463 E(VD->getAttrs().end()); 3464 I != E; ++I) 3465 FD->addAttr(*I); 3466 } 3467 } 3468 RD->completeDefinition(); 3469 return RD; 3470 } 3471 return nullptr; 3472 } 3473 3474 static RecordDecl * 3475 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 3476 QualType KmpInt32Ty, 3477 QualType KmpRoutineEntryPointerQTy) { 3478 ASTContext &C = CGM.getContext(); 3479 // Build struct kmp_task_t { 3480 // void * shareds; 3481 // kmp_routine_entry_t routine; 3482 // kmp_int32 part_id; 3483 // kmp_cmplrdata_t data1; 3484 // kmp_cmplrdata_t data2; 3485 // For taskloops additional fields: 3486 // kmp_uint64 lb; 3487 // kmp_uint64 ub; 3488 // kmp_int64 st; 3489 // kmp_int32 liter; 3490 // void * reductions; 3491 // }; 3492 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 3493 UD->startDefinition(); 3494 addFieldToRecordDecl(C, UD, KmpInt32Ty); 3495 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 3496 UD->completeDefinition(); 3497 QualType KmpCmplrdataTy = C.getRecordType(UD); 3498 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 3499 RD->startDefinition(); 3500 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3501 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 3502 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3503 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3504 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3505 if (isOpenMPTaskLoopDirective(Kind)) { 3506 QualType KmpUInt64Ty = 3507 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 3508 QualType KmpInt64Ty = 3509 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 3510 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3511 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3512 addFieldToRecordDecl(C, RD, KmpInt64Ty); 3513 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3514 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3515 } 3516 RD->completeDefinition(); 3517 return RD; 3518 } 3519 3520 static RecordDecl * 3521 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 3522 ArrayRef<PrivateDataTy> Privates) { 3523 ASTContext &C = CGM.getContext(); 3524 // Build struct kmp_task_t_with_privates { 3525 // kmp_task_t task_data; 3526 // .kmp_privates_t. privates; 3527 // }; 3528 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 3529 RD->startDefinition(); 3530 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 3531 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 3532 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 3533 RD->completeDefinition(); 3534 return RD; 3535 } 3536 3537 /// Emit a proxy function which accepts kmp_task_t as the second 3538 /// argument. 3539 /// \code 3540 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 3541 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 3542 /// For taskloops: 3543 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3544 /// tt->reductions, tt->shareds); 3545 /// return 0; 3546 /// } 3547 /// \endcode 3548 static llvm::Function * 3549 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 3550 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 3551 QualType KmpTaskTWithPrivatesPtrQTy, 3552 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 3553 QualType SharedsPtrTy, llvm::Function *TaskFunction, 3554 llvm::Value *TaskPrivatesMap) { 3555 ASTContext &C = CGM.getContext(); 3556 FunctionArgList Args; 3557 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3558 ImplicitParamDecl::Other); 3559 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3560 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3561 ImplicitParamDecl::Other); 3562 Args.push_back(&GtidArg); 3563 Args.push_back(&TaskTypeArg); 3564 const auto &TaskEntryFnInfo = 3565 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3566 llvm::FunctionType *TaskEntryTy = 3567 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 3568 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 3569 auto *TaskEntry = llvm::Function::Create( 3570 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3571 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 3572 TaskEntry->setDoesNotRecurse(); 3573 CodeGenFunction CGF(CGM); 3574 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 3575 Loc, Loc); 3576 3577 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 3578 // tt, 3579 // For taskloops: 3580 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3581 // tt->task_data.shareds); 3582 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 3583 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 3584 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3585 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3586 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3587 const auto *KmpTaskTWithPrivatesQTyRD = 3588 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3589 LValue Base = 3590 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3591 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3592 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 3593 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 3594 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 3595 3596 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 3597 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 3598 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3599 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 3600 CGF.ConvertTypeForMem(SharedsPtrTy)); 3601 3602 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 3603 llvm::Value *PrivatesParam; 3604 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 3605 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 3606 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3607 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 3608 } else { 3609 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3610 } 3611 3612 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 3613 TaskPrivatesMap, 3614 CGF.Builder 3615 .CreatePointerBitCastOrAddrSpaceCast( 3616 TDBase.getAddress(CGF), CGF.VoidPtrTy) 3617 .getPointer()}; 3618 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 3619 std::end(CommonArgs)); 3620 if (isOpenMPTaskLoopDirective(Kind)) { 3621 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 3622 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 3623 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 3624 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 3625 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 3626 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 3627 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 3628 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 3629 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 3630 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3631 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3632 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 3633 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 3634 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 3635 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 3636 CallArgs.push_back(LBParam); 3637 CallArgs.push_back(UBParam); 3638 CallArgs.push_back(StParam); 3639 CallArgs.push_back(LIParam); 3640 CallArgs.push_back(RParam); 3641 } 3642 CallArgs.push_back(SharedsParam); 3643 3644 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 3645 CallArgs); 3646 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 3647 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 3648 CGF.FinishFunction(); 3649 return TaskEntry; 3650 } 3651 3652 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 3653 SourceLocation Loc, 3654 QualType KmpInt32Ty, 3655 QualType KmpTaskTWithPrivatesPtrQTy, 3656 QualType KmpTaskTWithPrivatesQTy) { 3657 ASTContext &C = CGM.getContext(); 3658 FunctionArgList Args; 3659 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3660 ImplicitParamDecl::Other); 3661 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3662 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3663 ImplicitParamDecl::Other); 3664 Args.push_back(&GtidArg); 3665 Args.push_back(&TaskTypeArg); 3666 const auto &DestructorFnInfo = 3667 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3668 llvm::FunctionType *DestructorFnTy = 3669 CGM.getTypes().GetFunctionType(DestructorFnInfo); 3670 std::string Name = 3671 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 3672 auto *DestructorFn = 3673 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 3674 Name, &CGM.getModule()); 3675 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 3676 DestructorFnInfo); 3677 DestructorFn->setDoesNotRecurse(); 3678 CodeGenFunction CGF(CGM); 3679 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 3680 Args, Loc, Loc); 3681 3682 LValue Base = CGF.EmitLoadOfPointerLValue( 3683 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3684 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3685 const auto *KmpTaskTWithPrivatesQTyRD = 3686 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3687 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3688 Base = CGF.EmitLValueForField(Base, *FI); 3689 for (const auto *Field : 3690 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 3691 if (QualType::DestructionKind DtorKind = 3692 Field->getType().isDestructedType()) { 3693 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 3694 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 3695 } 3696 } 3697 CGF.FinishFunction(); 3698 return DestructorFn; 3699 } 3700 3701 /// Emit a privates mapping function for correct handling of private and 3702 /// firstprivate variables. 3703 /// \code 3704 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 3705 /// **noalias priv1,..., <tyn> **noalias privn) { 3706 /// *priv1 = &.privates.priv1; 3707 /// ...; 3708 /// *privn = &.privates.privn; 3709 /// } 3710 /// \endcode 3711 static llvm::Value * 3712 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 3713 ArrayRef<const Expr *> PrivateVars, 3714 ArrayRef<const Expr *> FirstprivateVars, 3715 ArrayRef<const Expr *> LastprivateVars, 3716 QualType PrivatesQTy, 3717 ArrayRef<PrivateDataTy> Privates) { 3718 ASTContext &C = CGM.getContext(); 3719 FunctionArgList Args; 3720 ImplicitParamDecl TaskPrivatesArg( 3721 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3722 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 3723 ImplicitParamDecl::Other); 3724 Args.push_back(&TaskPrivatesArg); 3725 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 3726 unsigned Counter = 1; 3727 for (const Expr *E : PrivateVars) { 3728 Args.push_back(ImplicitParamDecl::Create( 3729 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3730 C.getPointerType(C.getPointerType(E->getType())) 3731 .withConst() 3732 .withRestrict(), 3733 ImplicitParamDecl::Other)); 3734 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3735 PrivateVarsPos[VD] = Counter; 3736 ++Counter; 3737 } 3738 for (const Expr *E : FirstprivateVars) { 3739 Args.push_back(ImplicitParamDecl::Create( 3740 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3741 C.getPointerType(C.getPointerType(E->getType())) 3742 .withConst() 3743 .withRestrict(), 3744 ImplicitParamDecl::Other)); 3745 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3746 PrivateVarsPos[VD] = Counter; 3747 ++Counter; 3748 } 3749 for (const Expr *E : LastprivateVars) { 3750 Args.push_back(ImplicitParamDecl::Create( 3751 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3752 C.getPointerType(C.getPointerType(E->getType())) 3753 .withConst() 3754 .withRestrict(), 3755 ImplicitParamDecl::Other)); 3756 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3757 PrivateVarsPos[VD] = Counter; 3758 ++Counter; 3759 } 3760 const auto &TaskPrivatesMapFnInfo = 3761 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3762 llvm::FunctionType *TaskPrivatesMapTy = 3763 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 3764 std::string Name = 3765 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 3766 auto *TaskPrivatesMap = llvm::Function::Create( 3767 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 3768 &CGM.getModule()); 3769 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 3770 TaskPrivatesMapFnInfo); 3771 if (CGM.getLangOpts().Optimize) { 3772 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 3773 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 3774 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 3775 } 3776 CodeGenFunction CGF(CGM); 3777 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 3778 TaskPrivatesMapFnInfo, Args, Loc, Loc); 3779 3780 // *privi = &.privates.privi; 3781 LValue Base = CGF.EmitLoadOfPointerLValue( 3782 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 3783 TaskPrivatesArg.getType()->castAs<PointerType>()); 3784 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 3785 Counter = 0; 3786 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 3787 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 3788 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 3789 LValue RefLVal = 3790 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 3791 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 3792 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 3793 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 3794 ++Counter; 3795 } 3796 CGF.FinishFunction(); 3797 return TaskPrivatesMap; 3798 } 3799 3800 /// Emit initialization for private variables in task-based directives. 3801 static void emitPrivatesInit(CodeGenFunction &CGF, 3802 const OMPExecutableDirective &D, 3803 Address KmpTaskSharedsPtr, LValue TDBase, 3804 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3805 QualType SharedsTy, QualType SharedsPtrTy, 3806 const OMPTaskDataTy &Data, 3807 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 3808 ASTContext &C = CGF.getContext(); 3809 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3810 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 3811 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 3812 ? OMPD_taskloop 3813 : OMPD_task; 3814 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 3815 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 3816 LValue SrcBase; 3817 bool IsTargetTask = 3818 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 3819 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 3820 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 3821 // PointersArray and SizesArray. The original variables for these arrays are 3822 // not captured and we get their addresses explicitly. 3823 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) || 3824 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 3825 SrcBase = CGF.MakeAddrLValue( 3826 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3827 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 3828 SharedsTy); 3829 } 3830 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 3831 for (const PrivateDataTy &Pair : Privates) { 3832 const VarDecl *VD = Pair.second.PrivateCopy; 3833 const Expr *Init = VD->getAnyInitializer(); 3834 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 3835 !CGF.isTrivialInitializer(Init)))) { 3836 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 3837 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 3838 const VarDecl *OriginalVD = Pair.second.Original; 3839 // Check if the variable is the target-based BasePointersArray, 3840 // PointersArray or SizesArray. 3841 LValue SharedRefLValue; 3842 QualType Type = PrivateLValue.getType(); 3843 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 3844 if (IsTargetTask && !SharedField) { 3845 assert(isa<ImplicitParamDecl>(OriginalVD) && 3846 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 3847 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3848 ->getNumParams() == 0 && 3849 isa<TranslationUnitDecl>( 3850 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3851 ->getDeclContext()) && 3852 "Expected artificial target data variable."); 3853 SharedRefLValue = 3854 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 3855 } else if (ForDup) { 3856 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 3857 SharedRefLValue = CGF.MakeAddrLValue( 3858 Address(SharedRefLValue.getPointer(CGF), 3859 C.getDeclAlign(OriginalVD)), 3860 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 3861 SharedRefLValue.getTBAAInfo()); 3862 } else if (CGF.LambdaCaptureFields.count( 3863 Pair.second.Original->getCanonicalDecl()) > 0 || 3864 dyn_cast_or_null<BlockDecl>(CGF.CurCodeDecl)) { 3865 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3866 } else { 3867 // Processing for implicitly captured variables. 3868 InlinedOpenMPRegionRAII Region( 3869 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown, 3870 /*HasCancel=*/false); 3871 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3872 } 3873 if (Type->isArrayType()) { 3874 // Initialize firstprivate array. 3875 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 3876 // Perform simple memcpy. 3877 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 3878 } else { 3879 // Initialize firstprivate array using element-by-element 3880 // initialization. 3881 CGF.EmitOMPAggregateAssign( 3882 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 3883 Type, 3884 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 3885 Address SrcElement) { 3886 // Clean up any temporaries needed by the initialization. 3887 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3888 InitScope.addPrivate( 3889 Elem, [SrcElement]() -> Address { return SrcElement; }); 3890 (void)InitScope.Privatize(); 3891 // Emit initialization for single element. 3892 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 3893 CGF, &CapturesInfo); 3894 CGF.EmitAnyExprToMem(Init, DestElement, 3895 Init->getType().getQualifiers(), 3896 /*IsInitializer=*/false); 3897 }); 3898 } 3899 } else { 3900 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3901 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 3902 return SharedRefLValue.getAddress(CGF); 3903 }); 3904 (void)InitScope.Privatize(); 3905 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 3906 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 3907 /*capturedByInit=*/false); 3908 } 3909 } else { 3910 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 3911 } 3912 } 3913 ++FI; 3914 } 3915 } 3916 3917 /// Check if duplication function is required for taskloops. 3918 static bool checkInitIsRequired(CodeGenFunction &CGF, 3919 ArrayRef<PrivateDataTy> Privates) { 3920 bool InitRequired = false; 3921 for (const PrivateDataTy &Pair : Privates) { 3922 const VarDecl *VD = Pair.second.PrivateCopy; 3923 const Expr *Init = VD->getAnyInitializer(); 3924 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 3925 !CGF.isTrivialInitializer(Init)); 3926 if (InitRequired) 3927 break; 3928 } 3929 return InitRequired; 3930 } 3931 3932 3933 /// Emit task_dup function (for initialization of 3934 /// private/firstprivate/lastprivate vars and last_iter flag) 3935 /// \code 3936 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 3937 /// lastpriv) { 3938 /// // setup lastprivate flag 3939 /// task_dst->last = lastpriv; 3940 /// // could be constructor calls here... 3941 /// } 3942 /// \endcode 3943 static llvm::Value * 3944 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 3945 const OMPExecutableDirective &D, 3946 QualType KmpTaskTWithPrivatesPtrQTy, 3947 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3948 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 3949 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 3950 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 3951 ASTContext &C = CGM.getContext(); 3952 FunctionArgList Args; 3953 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3954 KmpTaskTWithPrivatesPtrQTy, 3955 ImplicitParamDecl::Other); 3956 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3957 KmpTaskTWithPrivatesPtrQTy, 3958 ImplicitParamDecl::Other); 3959 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 3960 ImplicitParamDecl::Other); 3961 Args.push_back(&DstArg); 3962 Args.push_back(&SrcArg); 3963 Args.push_back(&LastprivArg); 3964 const auto &TaskDupFnInfo = 3965 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3966 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 3967 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 3968 auto *TaskDup = llvm::Function::Create( 3969 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3970 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 3971 TaskDup->setDoesNotRecurse(); 3972 CodeGenFunction CGF(CGM); 3973 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 3974 Loc); 3975 3976 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3977 CGF.GetAddrOfLocalVar(&DstArg), 3978 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3979 // task_dst->liter = lastpriv; 3980 if (WithLastIter) { 3981 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3982 LValue Base = CGF.EmitLValueForField( 3983 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3984 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3985 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 3986 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 3987 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 3988 } 3989 3990 // Emit initial values for private copies (if any). 3991 assert(!Privates.empty()); 3992 Address KmpTaskSharedsPtr = Address::invalid(); 3993 if (!Data.FirstprivateVars.empty()) { 3994 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3995 CGF.GetAddrOfLocalVar(&SrcArg), 3996 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3997 LValue Base = CGF.EmitLValueForField( 3998 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3999 KmpTaskSharedsPtr = Address( 4000 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4001 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4002 KmpTaskTShareds)), 4003 Loc), 4004 CGM.getNaturalTypeAlignment(SharedsTy)); 4005 } 4006 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4007 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4008 CGF.FinishFunction(); 4009 return TaskDup; 4010 } 4011 4012 /// Checks if destructor function is required to be generated. 4013 /// \return true if cleanups are required, false otherwise. 4014 static bool 4015 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4016 bool NeedsCleanup = false; 4017 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4018 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4019 for (const FieldDecl *FD : PrivateRD->fields()) { 4020 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4021 if (NeedsCleanup) 4022 break; 4023 } 4024 return NeedsCleanup; 4025 } 4026 4027 CGOpenMPRuntime::TaskResultTy 4028 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4029 const OMPExecutableDirective &D, 4030 llvm::Function *TaskFunction, QualType SharedsTy, 4031 Address Shareds, const OMPTaskDataTy &Data) { 4032 ASTContext &C = CGM.getContext(); 4033 llvm::SmallVector<PrivateDataTy, 4> Privates; 4034 // Aggregate privates and sort them by the alignment. 4035 const auto *I = Data.PrivateCopies.begin(); 4036 for (const Expr *E : Data.PrivateVars) { 4037 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4038 Privates.emplace_back( 4039 C.getDeclAlign(VD), 4040 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4041 /*PrivateElemInit=*/nullptr)); 4042 ++I; 4043 } 4044 I = Data.FirstprivateCopies.begin(); 4045 const auto *IElemInitRef = Data.FirstprivateInits.begin(); 4046 for (const Expr *E : Data.FirstprivateVars) { 4047 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4048 Privates.emplace_back( 4049 C.getDeclAlign(VD), 4050 PrivateHelpersTy( 4051 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4052 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4053 ++I; 4054 ++IElemInitRef; 4055 } 4056 I = Data.LastprivateCopies.begin(); 4057 for (const Expr *E : Data.LastprivateVars) { 4058 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4059 Privates.emplace_back( 4060 C.getDeclAlign(VD), 4061 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4062 /*PrivateElemInit=*/nullptr)); 4063 ++I; 4064 } 4065 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 4066 return L.first > R.first; 4067 }); 4068 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4069 // Build type kmp_routine_entry_t (if not built yet). 4070 emitKmpRoutineEntryT(KmpInt32Ty); 4071 // Build type kmp_task_t (if not built yet). 4072 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 4073 if (SavedKmpTaskloopTQTy.isNull()) { 4074 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4075 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4076 } 4077 KmpTaskTQTy = SavedKmpTaskloopTQTy; 4078 } else { 4079 assert((D.getDirectiveKind() == OMPD_task || 4080 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 4081 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 4082 "Expected taskloop, task or target directive"); 4083 if (SavedKmpTaskTQTy.isNull()) { 4084 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4085 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4086 } 4087 KmpTaskTQTy = SavedKmpTaskTQTy; 4088 } 4089 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4090 // Build particular struct kmp_task_t for the given task. 4091 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 4092 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 4093 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 4094 QualType KmpTaskTWithPrivatesPtrQTy = 4095 C.getPointerType(KmpTaskTWithPrivatesQTy); 4096 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 4097 llvm::Type *KmpTaskTWithPrivatesPtrTy = 4098 KmpTaskTWithPrivatesTy->getPointerTo(); 4099 llvm::Value *KmpTaskTWithPrivatesTySize = 4100 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 4101 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 4102 4103 // Emit initial values for private copies (if any). 4104 llvm::Value *TaskPrivatesMap = nullptr; 4105 llvm::Type *TaskPrivatesMapTy = 4106 std::next(TaskFunction->arg_begin(), 3)->getType(); 4107 if (!Privates.empty()) { 4108 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4109 TaskPrivatesMap = emitTaskPrivateMappingFunction( 4110 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 4111 FI->getType(), Privates); 4112 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4113 TaskPrivatesMap, TaskPrivatesMapTy); 4114 } else { 4115 TaskPrivatesMap = llvm::ConstantPointerNull::get( 4116 cast<llvm::PointerType>(TaskPrivatesMapTy)); 4117 } 4118 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 4119 // kmp_task_t *tt); 4120 llvm::Function *TaskEntry = emitProxyTaskFunction( 4121 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4122 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 4123 TaskPrivatesMap); 4124 4125 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 4126 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 4127 // kmp_routine_entry_t *task_entry); 4128 // Task flags. Format is taken from 4129 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 4130 // description of kmp_tasking_flags struct. 4131 enum { 4132 TiedFlag = 0x1, 4133 FinalFlag = 0x2, 4134 DestructorsFlag = 0x8, 4135 PriorityFlag = 0x20, 4136 DetachableFlag = 0x40, 4137 }; 4138 unsigned Flags = Data.Tied ? TiedFlag : 0; 4139 bool NeedsCleanup = false; 4140 if (!Privates.empty()) { 4141 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 4142 if (NeedsCleanup) 4143 Flags = Flags | DestructorsFlag; 4144 } 4145 if (Data.Priority.getInt()) 4146 Flags = Flags | PriorityFlag; 4147 if (D.hasClausesOfKind<OMPDetachClause>()) 4148 Flags = Flags | DetachableFlag; 4149 llvm::Value *TaskFlags = 4150 Data.Final.getPointer() 4151 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 4152 CGF.Builder.getInt32(FinalFlag), 4153 CGF.Builder.getInt32(/*C=*/0)) 4154 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 4155 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 4156 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 4157 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 4158 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 4159 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4160 TaskEntry, KmpRoutineEntryPtrTy)}; 4161 llvm::Value *NewTask; 4162 if (D.hasClausesOfKind<OMPNowaitClause>()) { 4163 // Check if we have any device clause associated with the directive. 4164 const Expr *Device = nullptr; 4165 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 4166 Device = C->getDevice(); 4167 // Emit device ID if any otherwise use default value. 4168 llvm::Value *DeviceID; 4169 if (Device) 4170 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 4171 CGF.Int64Ty, /*isSigned=*/true); 4172 else 4173 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 4174 AllocArgs.push_back(DeviceID); 4175 NewTask = CGF.EmitRuntimeCall( 4176 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 4177 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc), 4178 AllocArgs); 4179 } else { 4180 NewTask = 4181 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 4182 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc), 4183 AllocArgs); 4184 } 4185 // Emit detach clause initialization. 4186 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid, 4187 // task_descriptor); 4188 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) { 4189 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts(); 4190 LValue EvtLVal = CGF.EmitLValue(Evt); 4191 4192 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 4193 // int gtid, kmp_task_t *task); 4194 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc()); 4195 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc()); 4196 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false); 4197 llvm::Value *EvtVal = CGF.EmitRuntimeCall( 4198 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 4199 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event), 4200 {Loc, Tid, NewTask}); 4201 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(), 4202 Evt->getExprLoc()); 4203 CGF.EmitStoreOfScalar(EvtVal, EvtLVal); 4204 } 4205 llvm::Value *NewTaskNewTaskTTy = 4206 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4207 NewTask, KmpTaskTWithPrivatesPtrTy); 4208 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 4209 KmpTaskTWithPrivatesQTy); 4210 LValue TDBase = 4211 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4212 // Fill the data in the resulting kmp_task_t record. 4213 // Copy shareds if there are any. 4214 Address KmpTaskSharedsPtr = Address::invalid(); 4215 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 4216 KmpTaskSharedsPtr = 4217 Address(CGF.EmitLoadOfScalar( 4218 CGF.EmitLValueForField( 4219 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 4220 KmpTaskTShareds)), 4221 Loc), 4222 CGM.getNaturalTypeAlignment(SharedsTy)); 4223 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 4224 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 4225 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 4226 } 4227 // Emit initial values for private copies (if any). 4228 TaskResultTy Result; 4229 if (!Privates.empty()) { 4230 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 4231 SharedsTy, SharedsPtrTy, Data, Privates, 4232 /*ForDup=*/false); 4233 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 4234 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 4235 Result.TaskDupFn = emitTaskDupFunction( 4236 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 4237 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 4238 /*WithLastIter=*/!Data.LastprivateVars.empty()); 4239 } 4240 } 4241 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 4242 enum { Priority = 0, Destructors = 1 }; 4243 // Provide pointer to function with destructors for privates. 4244 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 4245 const RecordDecl *KmpCmplrdataUD = 4246 (*FI)->getType()->getAsUnionType()->getDecl(); 4247 if (NeedsCleanup) { 4248 llvm::Value *DestructorFn = emitDestructorsFunction( 4249 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4250 KmpTaskTWithPrivatesQTy); 4251 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 4252 LValue DestructorsLV = CGF.EmitLValueForField( 4253 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 4254 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4255 DestructorFn, KmpRoutineEntryPtrTy), 4256 DestructorsLV); 4257 } 4258 // Set priority. 4259 if (Data.Priority.getInt()) { 4260 LValue Data2LV = CGF.EmitLValueForField( 4261 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 4262 LValue PriorityLV = CGF.EmitLValueForField( 4263 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 4264 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 4265 } 4266 Result.NewTask = NewTask; 4267 Result.TaskEntry = TaskEntry; 4268 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 4269 Result.TDBase = TDBase; 4270 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 4271 return Result; 4272 } 4273 4274 namespace { 4275 /// Dependence kind for RTL. 4276 enum RTLDependenceKindTy { 4277 DepIn = 0x01, 4278 DepInOut = 0x3, 4279 DepMutexInOutSet = 0x4 4280 }; 4281 /// Fields ids in kmp_depend_info record. 4282 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 4283 } // namespace 4284 4285 /// Translates internal dependency kind into the runtime kind. 4286 static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { 4287 RTLDependenceKindTy DepKind; 4288 switch (K) { 4289 case OMPC_DEPEND_in: 4290 DepKind = DepIn; 4291 break; 4292 // Out and InOut dependencies must use the same code. 4293 case OMPC_DEPEND_out: 4294 case OMPC_DEPEND_inout: 4295 DepKind = DepInOut; 4296 break; 4297 case OMPC_DEPEND_mutexinoutset: 4298 DepKind = DepMutexInOutSet; 4299 break; 4300 case OMPC_DEPEND_source: 4301 case OMPC_DEPEND_sink: 4302 case OMPC_DEPEND_depobj: 4303 case OMPC_DEPEND_unknown: 4304 llvm_unreachable("Unknown task dependence type"); 4305 } 4306 return DepKind; 4307 } 4308 4309 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4310 static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, 4311 QualType &FlagsTy) { 4312 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 4313 if (KmpDependInfoTy.isNull()) { 4314 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 4315 KmpDependInfoRD->startDefinition(); 4316 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 4317 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 4318 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 4319 KmpDependInfoRD->completeDefinition(); 4320 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 4321 } 4322 } 4323 4324 std::pair<llvm::Value *, LValue> 4325 CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, 4326 SourceLocation Loc) { 4327 ASTContext &C = CGM.getContext(); 4328 QualType FlagsTy; 4329 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4330 RecordDecl *KmpDependInfoRD = 4331 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4332 LValue Base = CGF.EmitLoadOfPointerLValue( 4333 DepobjLVal.getAddress(CGF), 4334 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4335 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4336 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4337 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 4338 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4339 Base.getTBAAInfo()); 4340 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4341 Addr.getPointer(), 4342 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4343 LValue NumDepsBase = CGF.MakeAddrLValue( 4344 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4345 Base.getBaseInfo(), Base.getTBAAInfo()); 4346 // NumDeps = deps[i].base_addr; 4347 LValue BaseAddrLVal = CGF.EmitLValueForField( 4348 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4349 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc); 4350 return std::make_pair(NumDeps, Base); 4351 } 4352 4353 namespace { 4354 /// Loop generator for OpenMP iterator expression. 4355 class OMPIteratorGeneratorScope final 4356 : public CodeGenFunction::OMPPrivateScope { 4357 CodeGenFunction &CGF; 4358 const OMPIteratorExpr *E = nullptr; 4359 SmallVector<CodeGenFunction::JumpDest, 4> ContDests; 4360 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests; 4361 OMPIteratorGeneratorScope() = delete; 4362 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete; 4363 4364 public: 4365 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E) 4366 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) { 4367 if (!E) 4368 return; 4369 SmallVector<llvm::Value *, 4> Uppers; 4370 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4371 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper)); 4372 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I)); 4373 addPrivate(VD, [&CGF, VD]() { 4374 return CGF.CreateMemTemp(VD->getType(), VD->getName()); 4375 }); 4376 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4377 addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() { 4378 return CGF.CreateMemTemp(HelperData.CounterVD->getType(), 4379 "counter.addr"); 4380 }); 4381 } 4382 Privatize(); 4383 4384 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4385 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4386 LValue CLVal = 4387 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD), 4388 HelperData.CounterVD->getType()); 4389 // Counter = 0; 4390 CGF.EmitStoreOfScalar( 4391 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0), 4392 CLVal); 4393 CodeGenFunction::JumpDest &ContDest = 4394 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont")); 4395 CodeGenFunction::JumpDest &ExitDest = 4396 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit")); 4397 // N = <number-of_iterations>; 4398 llvm::Value *N = Uppers[I]; 4399 // cont: 4400 // if (Counter < N) goto body; else goto exit; 4401 CGF.EmitBlock(ContDest.getBlock()); 4402 auto *CVal = 4403 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation()); 4404 llvm::Value *Cmp = 4405 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType() 4406 ? CGF.Builder.CreateICmpSLT(CVal, N) 4407 : CGF.Builder.CreateICmpULT(CVal, N); 4408 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body"); 4409 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock()); 4410 // body: 4411 CGF.EmitBlock(BodyBB); 4412 // Iteri = Begini + Counter * Stepi; 4413 CGF.EmitIgnoredExpr(HelperData.Update); 4414 } 4415 } 4416 ~OMPIteratorGeneratorScope() { 4417 if (!E) 4418 return; 4419 for (unsigned I = E->numOfIterators(); I > 0; --I) { 4420 // Counter = Counter + 1; 4421 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1); 4422 CGF.EmitIgnoredExpr(HelperData.CounterUpdate); 4423 // goto cont; 4424 CGF.EmitBranchThroughCleanup(ContDests[I - 1]); 4425 // exit: 4426 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1); 4427 } 4428 } 4429 }; 4430 } // namespace 4431 4432 static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4433 llvm::PointerUnion<unsigned *, LValue *> Pos, 4434 const OMPTaskDataTy::DependData &Data, 4435 Address DependenciesArray) { 4436 CodeGenModule &CGM = CGF.CGM; 4437 ASTContext &C = CGM.getContext(); 4438 QualType FlagsTy; 4439 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4440 RecordDecl *KmpDependInfoRD = 4441 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4442 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 4443 4444 OMPIteratorGeneratorScope IteratorScope( 4445 CGF, cast_or_null<OMPIteratorExpr>( 4446 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4447 : nullptr)); 4448 for (const Expr *E : Data.DepExprs) { 4449 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E); 4450 llvm::Value *Addr; 4451 if (OASE) { 4452 const Expr *Base = OASE->getBase(); 4453 Addr = CGF.EmitScalarExpr(Base); 4454 } else { 4455 Addr = CGF.EmitLValue(E).getPointer(CGF); 4456 } 4457 llvm::Value *Size; 4458 QualType Ty = E->getType(); 4459 if (OASE) { 4460 Size = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType()); 4461 for (const Expr *SE : OASE->getDimensions()) { 4462 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 4463 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 4464 CGF.getContext().getSizeType(), 4465 SE->getExprLoc()); 4466 Size = CGF.Builder.CreateNUWMul(Size, Sz); 4467 } 4468 } else if (const auto *ASE = 4469 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 4470 LValue UpAddrLVal = 4471 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 4472 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 4473 UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 4474 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGM.SizeTy); 4475 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 4476 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 4477 } else { 4478 Size = CGF.getTypeSize(Ty); 4479 } 4480 LValue Base; 4481 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4482 Base = CGF.MakeAddrLValue( 4483 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy); 4484 } else { 4485 LValue &PosLVal = *Pos.get<LValue *>(); 4486 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4487 Base = CGF.MakeAddrLValue( 4488 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Idx), 4489 DependenciesArray.getAlignment()), 4490 KmpDependInfoTy); 4491 } 4492 // deps[i].base_addr = &<Dependencies[i].second>; 4493 LValue BaseAddrLVal = CGF.EmitLValueForField( 4494 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4495 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4496 BaseAddrLVal); 4497 // deps[i].len = sizeof(<Dependencies[i].second>); 4498 LValue LenLVal = CGF.EmitLValueForField( 4499 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 4500 CGF.EmitStoreOfScalar(Size, LenLVal); 4501 // deps[i].flags = <Dependencies[i].first>; 4502 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind); 4503 LValue FlagsLVal = CGF.EmitLValueForField( 4504 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 4505 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 4506 FlagsLVal); 4507 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4508 ++(*P); 4509 } else { 4510 LValue &PosLVal = *Pos.get<LValue *>(); 4511 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4512 Idx = CGF.Builder.CreateNUWAdd(Idx, 4513 llvm::ConstantInt::get(Idx->getType(), 1)); 4514 CGF.EmitStoreOfScalar(Idx, PosLVal); 4515 } 4516 } 4517 } 4518 4519 static SmallVector<llvm::Value *, 4> 4520 emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4521 const OMPTaskDataTy::DependData &Data) { 4522 assert(Data.DepKind == OMPC_DEPEND_depobj && 4523 "Expected depobj dependecy kind."); 4524 SmallVector<llvm::Value *, 4> Sizes; 4525 SmallVector<LValue, 4> SizeLVals; 4526 ASTContext &C = CGF.getContext(); 4527 QualType FlagsTy; 4528 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4529 RecordDecl *KmpDependInfoRD = 4530 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4531 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4532 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4533 { 4534 OMPIteratorGeneratorScope IteratorScope( 4535 CGF, cast_or_null<OMPIteratorExpr>( 4536 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4537 : nullptr)); 4538 for (const Expr *E : Data.DepExprs) { 4539 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4540 LValue Base = CGF.EmitLoadOfPointerLValue( 4541 DepobjLVal.getAddress(CGF), 4542 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4543 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4544 Base.getAddress(CGF), KmpDependInfoPtrT); 4545 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4546 Base.getTBAAInfo()); 4547 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4548 Addr.getPointer(), 4549 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4550 LValue NumDepsBase = CGF.MakeAddrLValue( 4551 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4552 Base.getBaseInfo(), Base.getTBAAInfo()); 4553 // NumDeps = deps[i].base_addr; 4554 LValue BaseAddrLVal = CGF.EmitLValueForField( 4555 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4556 llvm::Value *NumDeps = 4557 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4558 LValue NumLVal = CGF.MakeAddrLValue( 4559 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"), 4560 C.getUIntPtrType()); 4561 CGF.InitTempAlloca(NumLVal.getAddress(CGF), 4562 llvm::ConstantInt::get(CGF.IntPtrTy, 0)); 4563 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc()); 4564 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps); 4565 CGF.EmitStoreOfScalar(Add, NumLVal); 4566 SizeLVals.push_back(NumLVal); 4567 } 4568 } 4569 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) { 4570 llvm::Value *Size = 4571 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc()); 4572 Sizes.push_back(Size); 4573 } 4574 return Sizes; 4575 } 4576 4577 static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4578 LValue PosLVal, 4579 const OMPTaskDataTy::DependData &Data, 4580 Address DependenciesArray) { 4581 assert(Data.DepKind == OMPC_DEPEND_depobj && 4582 "Expected depobj dependecy kind."); 4583 ASTContext &C = CGF.getContext(); 4584 QualType FlagsTy; 4585 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4586 RecordDecl *KmpDependInfoRD = 4587 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4588 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4589 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4590 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy); 4591 { 4592 OMPIteratorGeneratorScope IteratorScope( 4593 CGF, cast_or_null<OMPIteratorExpr>( 4594 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4595 : nullptr)); 4596 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) { 4597 const Expr *E = Data.DepExprs[I]; 4598 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4599 LValue Base = CGF.EmitLoadOfPointerLValue( 4600 DepobjLVal.getAddress(CGF), 4601 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4602 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4603 Base.getAddress(CGF), KmpDependInfoPtrT); 4604 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4605 Base.getTBAAInfo()); 4606 4607 // Get number of elements in a single depobj. 4608 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4609 Addr.getPointer(), 4610 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4611 LValue NumDepsBase = CGF.MakeAddrLValue( 4612 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4613 Base.getBaseInfo(), Base.getTBAAInfo()); 4614 // NumDeps = deps[i].base_addr; 4615 LValue BaseAddrLVal = CGF.EmitLValueForField( 4616 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4617 llvm::Value *NumDeps = 4618 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4619 4620 // memcopy dependency data. 4621 llvm::Value *Size = CGF.Builder.CreateNUWMul( 4622 ElSize, 4623 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); 4624 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4625 Address DepAddr = 4626 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Pos), 4627 DependenciesArray.getAlignment()); 4628 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); 4629 4630 // Increase pos. 4631 // pos += size; 4632 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps); 4633 CGF.EmitStoreOfScalar(Add, PosLVal); 4634 } 4635 } 4636 } 4637 4638 std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause( 4639 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies, 4640 SourceLocation Loc) { 4641 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) { 4642 return D.DepExprs.empty(); 4643 })) 4644 return std::make_pair(nullptr, Address::invalid()); 4645 // Process list of dependencies. 4646 ASTContext &C = CGM.getContext(); 4647 Address DependenciesArray = Address::invalid(); 4648 llvm::Value *NumOfElements = nullptr; 4649 unsigned NumDependencies = std::accumulate( 4650 Dependencies.begin(), Dependencies.end(), 0, 4651 [](unsigned V, const OMPTaskDataTy::DependData &D) { 4652 return D.DepKind == OMPC_DEPEND_depobj 4653 ? V 4654 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size())); 4655 }); 4656 QualType FlagsTy; 4657 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4658 bool HasDepobjDeps = false; 4659 bool HasRegularWithIterators = false; 4660 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0); 4661 llvm::Value *NumOfRegularWithIterators = 4662 llvm::ConstantInt::get(CGF.IntPtrTy, 1); 4663 // Calculate number of depobj dependecies and regular deps with the iterators. 4664 for (const OMPTaskDataTy::DependData &D : Dependencies) { 4665 if (D.DepKind == OMPC_DEPEND_depobj) { 4666 SmallVector<llvm::Value *, 4> Sizes = 4667 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D); 4668 for (llvm::Value *Size : Sizes) { 4669 NumOfDepobjElements = 4670 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size); 4671 } 4672 HasDepobjDeps = true; 4673 continue; 4674 } 4675 // Include number of iterations, if any. 4676 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) { 4677 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4678 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4679 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false); 4680 NumOfRegularWithIterators = 4681 CGF.Builder.CreateNUWMul(NumOfRegularWithIterators, Sz); 4682 } 4683 HasRegularWithIterators = true; 4684 continue; 4685 } 4686 } 4687 4688 QualType KmpDependInfoArrayTy; 4689 if (HasDepobjDeps || HasRegularWithIterators) { 4690 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies, 4691 /*isSigned=*/false); 4692 if (HasDepobjDeps) { 4693 NumOfElements = 4694 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements); 4695 } 4696 if (HasRegularWithIterators) { 4697 NumOfElements = 4698 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements); 4699 } 4700 OpaqueValueExpr OVE(Loc, 4701 C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0), 4702 VK_RValue); 4703 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 4704 RValue::get(NumOfElements)); 4705 KmpDependInfoArrayTy = 4706 C.getVariableArrayType(KmpDependInfoTy, &OVE, ArrayType::Normal, 4707 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4708 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy); 4709 // Properly emit variable-sized array. 4710 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy, 4711 ImplicitParamDecl::Other); 4712 CGF.EmitVarDecl(*PD); 4713 DependenciesArray = CGF.GetAddrOfLocalVar(PD); 4714 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4715 /*isSigned=*/false); 4716 } else { 4717 KmpDependInfoArrayTy = C.getConstantArrayType( 4718 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr, 4719 ArrayType::Normal, /*IndexTypeQuals=*/0); 4720 DependenciesArray = 4721 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 4722 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0); 4723 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 4724 /*isSigned=*/false); 4725 } 4726 unsigned Pos = 0; 4727 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4728 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4729 Dependencies[I].IteratorExpr) 4730 continue; 4731 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I], 4732 DependenciesArray); 4733 } 4734 // Copy regular dependecies with iterators. 4735 LValue PosLVal = CGF.MakeAddrLValue( 4736 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType()); 4737 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4738 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4739 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4740 !Dependencies[I].IteratorExpr) 4741 continue; 4742 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I], 4743 DependenciesArray); 4744 } 4745 // Copy final depobj arrays without iterators. 4746 if (HasDepobjDeps) { 4747 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4748 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj) 4749 continue; 4750 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I], 4751 DependenciesArray); 4752 } 4753 } 4754 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4755 DependenciesArray, CGF.VoidPtrTy); 4756 return std::make_pair(NumOfElements, DependenciesArray); 4757 } 4758 4759 Address CGOpenMPRuntime::emitDepobjDependClause( 4760 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, 4761 SourceLocation Loc) { 4762 if (Dependencies.DepExprs.empty()) 4763 return Address::invalid(); 4764 // Process list of dependencies. 4765 ASTContext &C = CGM.getContext(); 4766 Address DependenciesArray = Address::invalid(); 4767 unsigned NumDependencies = Dependencies.DepExprs.size(); 4768 QualType FlagsTy; 4769 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4770 RecordDecl *KmpDependInfoRD = 4771 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4772 4773 llvm::Value *Size; 4774 // Define type kmp_depend_info[<Dependencies.size()>]; 4775 // For depobj reserve one extra element to store the number of elements. 4776 // It is required to handle depobj(x) update(in) construct. 4777 // kmp_depend_info[<Dependencies.size()>] deps; 4778 llvm::Value *NumDepsVal; 4779 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy); 4780 if (const auto *IE = 4781 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) { 4782 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1); 4783 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4784 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4785 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4786 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz); 4787 } 4788 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1), 4789 NumDepsVal); 4790 CharUnits SizeInBytes = 4791 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align); 4792 llvm::Value *RecSize = CGM.getSize(SizeInBytes); 4793 Size = CGF.Builder.CreateNUWMul(Size, RecSize); 4794 NumDepsVal = 4795 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false); 4796 } else { 4797 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 4798 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1), 4799 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 4800 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy); 4801 Size = CGM.getSize(Sz.alignTo(Align)); 4802 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies); 4803 } 4804 // Need to allocate on the dynamic memory. 4805 llvm::Value *ThreadID = getThreadID(CGF, Loc); 4806 // Use default allocator. 4807 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4808 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 4809 4810 llvm::Value *Addr = 4811 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 4812 CGM.getModule(), OMPRTL___kmpc_alloc), 4813 Args, ".dep.arr.addr"); 4814 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4815 Addr, CGF.ConvertTypeForMem(KmpDependInfoTy)->getPointerTo()); 4816 DependenciesArray = Address(Addr, Align); 4817 // Write number of elements in the first element of array for depobj. 4818 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy); 4819 // deps[i].base_addr = NumDependencies; 4820 LValue BaseAddrLVal = CGF.EmitLValueForField( 4821 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4822 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal); 4823 llvm::PointerUnion<unsigned *, LValue *> Pos; 4824 unsigned Idx = 1; 4825 LValue PosLVal; 4826 if (Dependencies.IteratorExpr) { 4827 PosLVal = CGF.MakeAddrLValue( 4828 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"), 4829 C.getSizeType()); 4830 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal, 4831 /*IsInit=*/true); 4832 Pos = &PosLVal; 4833 } else { 4834 Pos = &Idx; 4835 } 4836 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray); 4837 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4838 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy); 4839 return DependenciesArray; 4840 } 4841 4842 void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 4843 SourceLocation Loc) { 4844 ASTContext &C = CGM.getContext(); 4845 QualType FlagsTy; 4846 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4847 LValue Base = CGF.EmitLoadOfPointerLValue( 4848 DepobjLVal.getAddress(CGF), 4849 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4850 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4851 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4852 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 4853 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4854 Addr.getPointer(), 4855 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4856 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, 4857 CGF.VoidPtrTy); 4858 llvm::Value *ThreadID = getThreadID(CGF, Loc); 4859 // Use default allocator. 4860 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4861 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator}; 4862 4863 // _kmpc_free(gtid, addr, nullptr); 4864 (void)CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 4865 CGM.getModule(), OMPRTL___kmpc_free), 4866 Args); 4867 } 4868 4869 void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 4870 OpenMPDependClauseKind NewDepKind, 4871 SourceLocation Loc) { 4872 ASTContext &C = CGM.getContext(); 4873 QualType FlagsTy; 4874 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4875 RecordDecl *KmpDependInfoRD = 4876 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4877 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 4878 llvm::Value *NumDeps; 4879 LValue Base; 4880 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 4881 4882 Address Begin = Base.getAddress(CGF); 4883 // Cast from pointer to array type to pointer to single element. 4884 llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps); 4885 // The basic structure here is a while-do loop. 4886 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); 4887 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); 4888 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 4889 CGF.EmitBlock(BodyBB); 4890 llvm::PHINode *ElementPHI = 4891 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); 4892 ElementPHI->addIncoming(Begin.getPointer(), EntryBB); 4893 Begin = Address(ElementPHI, Begin.getAlignment()); 4894 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), 4895 Base.getTBAAInfo()); 4896 // deps[i].flags = NewDepKind; 4897 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind); 4898 LValue FlagsLVal = CGF.EmitLValueForField( 4899 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 4900 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 4901 FlagsLVal); 4902 4903 // Shift the address forward by one element. 4904 Address ElementNext = 4905 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); 4906 ElementPHI->addIncoming(ElementNext.getPointer(), 4907 CGF.Builder.GetInsertBlock()); 4908 llvm::Value *IsEmpty = 4909 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); 4910 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 4911 // Done. 4912 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 4913 } 4914 4915 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 4916 const OMPExecutableDirective &D, 4917 llvm::Function *TaskFunction, 4918 QualType SharedsTy, Address Shareds, 4919 const Expr *IfCond, 4920 const OMPTaskDataTy &Data) { 4921 if (!CGF.HaveInsertPoint()) 4922 return; 4923 4924 TaskResultTy Result = 4925 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 4926 llvm::Value *NewTask = Result.NewTask; 4927 llvm::Function *TaskEntry = Result.TaskEntry; 4928 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 4929 LValue TDBase = Result.TDBase; 4930 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 4931 // Process list of dependences. 4932 Address DependenciesArray = Address::invalid(); 4933 llvm::Value *NumOfElements; 4934 std::tie(NumOfElements, DependenciesArray) = 4935 emitDependClause(CGF, Data.Dependences, Loc); 4936 4937 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 4938 // libcall. 4939 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 4940 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 4941 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 4942 // list is not empty 4943 llvm::Value *ThreadID = getThreadID(CGF, Loc); 4944 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 4945 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 4946 llvm::Value *DepTaskArgs[7]; 4947 if (!Data.Dependences.empty()) { 4948 DepTaskArgs[0] = UpLoc; 4949 DepTaskArgs[1] = ThreadID; 4950 DepTaskArgs[2] = NewTask; 4951 DepTaskArgs[3] = NumOfElements; 4952 DepTaskArgs[4] = DependenciesArray.getPointer(); 4953 DepTaskArgs[5] = CGF.Builder.getInt32(0); 4954 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4955 } 4956 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs, 4957 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 4958 if (!Data.Tied) { 4959 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4960 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 4961 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 4962 } 4963 if (!Data.Dependences.empty()) { 4964 CGF.EmitRuntimeCall( 4965 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 4966 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps), 4967 DepTaskArgs); 4968 } else { 4969 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 4970 CGM.getModule(), OMPRTL___kmpc_omp_task), 4971 TaskArgs); 4972 } 4973 // Check if parent region is untied and build return for untied task; 4974 if (auto *Region = 4975 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 4976 Region->emitUntiedSwitch(CGF); 4977 }; 4978 4979 llvm::Value *DepWaitTaskArgs[6]; 4980 if (!Data.Dependences.empty()) { 4981 DepWaitTaskArgs[0] = UpLoc; 4982 DepWaitTaskArgs[1] = ThreadID; 4983 DepWaitTaskArgs[2] = NumOfElements; 4984 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 4985 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 4986 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4987 } 4988 auto &M = CGM.getModule(); 4989 auto &&ElseCodeGen = [&M, &TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 4990 &Data, &DepWaitTaskArgs, 4991 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 4992 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 4993 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 4994 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 4995 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 4996 // is specified. 4997 if (!Data.Dependences.empty()) 4998 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 4999 M, OMPRTL___kmpc_omp_wait_deps), 5000 DepWaitTaskArgs); 5001 // Call proxy_task_entry(gtid, new_task); 5002 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5003 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5004 Action.Enter(CGF); 5005 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5006 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5007 OutlinedFnArgs); 5008 }; 5009 5010 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5011 // kmp_task_t *new_task); 5012 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5013 // kmp_task_t *new_task); 5014 RegionCodeGenTy RCG(CodeGen); 5015 CommonActionTy Action(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 5016 M, OMPRTL___kmpc_omp_task_begin_if0), 5017 TaskArgs, 5018 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 5019 M, OMPRTL___kmpc_omp_task_complete_if0), 5020 TaskArgs); 5021 RCG.setAction(Action); 5022 RCG(CGF); 5023 }; 5024 5025 if (IfCond) { 5026 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5027 } else { 5028 RegionCodeGenTy ThenRCG(ThenCodeGen); 5029 ThenRCG(CGF); 5030 } 5031 } 5032 5033 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5034 const OMPLoopDirective &D, 5035 llvm::Function *TaskFunction, 5036 QualType SharedsTy, Address Shareds, 5037 const Expr *IfCond, 5038 const OMPTaskDataTy &Data) { 5039 if (!CGF.HaveInsertPoint()) 5040 return; 5041 TaskResultTy Result = 5042 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5043 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5044 // libcall. 5045 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5046 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5047 // sched, kmp_uint64 grainsize, void *task_dup); 5048 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5049 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5050 llvm::Value *IfVal; 5051 if (IfCond) { 5052 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5053 /*isSigned=*/true); 5054 } else { 5055 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5056 } 5057 5058 LValue LBLVal = CGF.EmitLValueForField( 5059 Result.TDBase, 5060 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5061 const auto *LBVar = 5062 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5063 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5064 LBLVal.getQuals(), 5065 /*IsInitializer=*/true); 5066 LValue UBLVal = CGF.EmitLValueForField( 5067 Result.TDBase, 5068 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5069 const auto *UBVar = 5070 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5071 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5072 UBLVal.getQuals(), 5073 /*IsInitializer=*/true); 5074 LValue StLVal = CGF.EmitLValueForField( 5075 Result.TDBase, 5076 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5077 const auto *StVar = 5078 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5079 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5080 StLVal.getQuals(), 5081 /*IsInitializer=*/true); 5082 // Store reductions address. 5083 LValue RedLVal = CGF.EmitLValueForField( 5084 Result.TDBase, 5085 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5086 if (Data.Reductions) { 5087 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5088 } else { 5089 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5090 CGF.getContext().VoidPtrTy); 5091 } 5092 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5093 llvm::Value *TaskArgs[] = { 5094 UpLoc, 5095 ThreadID, 5096 Result.NewTask, 5097 IfVal, 5098 LBLVal.getPointer(CGF), 5099 UBLVal.getPointer(CGF), 5100 CGF.EmitLoadOfScalar(StLVal, Loc), 5101 llvm::ConstantInt::getSigned( 5102 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5103 llvm::ConstantInt::getSigned( 5104 CGF.IntTy, Data.Schedule.getPointer() 5105 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5106 : NoSchedule), 5107 Data.Schedule.getPointer() 5108 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5109 /*isSigned=*/false) 5110 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5111 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5112 Result.TaskDupFn, CGF.VoidPtrTy) 5113 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5114 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 5115 CGM.getModule(), OMPRTL___kmpc_taskloop), 5116 TaskArgs); 5117 } 5118 5119 /// Emit reduction operation for each element of array (required for 5120 /// array sections) LHS op = RHS. 5121 /// \param Type Type of array. 5122 /// \param LHSVar Variable on the left side of the reduction operation 5123 /// (references element of array in original variable). 5124 /// \param RHSVar Variable on the right side of the reduction operation 5125 /// (references element of array in original variable). 5126 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5127 /// RHSVar. 5128 static void EmitOMPAggregateReduction( 5129 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5130 const VarDecl *RHSVar, 5131 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5132 const Expr *, const Expr *)> &RedOpGen, 5133 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5134 const Expr *UpExpr = nullptr) { 5135 // Perform element-by-element initialization. 5136 QualType ElementTy; 5137 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5138 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5139 5140 // Drill down to the base element type on both arrays. 5141 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5142 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5143 5144 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5145 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5146 // Cast from pointer to array type to pointer to single element. 5147 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5148 // The basic structure here is a while-do loop. 5149 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5150 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5151 llvm::Value *IsEmpty = 5152 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5153 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5154 5155 // Enter the loop body, making that address the current address. 5156 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5157 CGF.EmitBlock(BodyBB); 5158 5159 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5160 5161 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5162 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5163 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5164 Address RHSElementCurrent = 5165 Address(RHSElementPHI, 5166 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5167 5168 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5169 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5170 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5171 Address LHSElementCurrent = 5172 Address(LHSElementPHI, 5173 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5174 5175 // Emit copy. 5176 CodeGenFunction::OMPPrivateScope Scope(CGF); 5177 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5178 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5179 Scope.Privatize(); 5180 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5181 Scope.ForceCleanup(); 5182 5183 // Shift the address forward by one element. 5184 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5185 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5186 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5187 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5188 // Check whether we've reached the end. 5189 llvm::Value *Done = 5190 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5191 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5192 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5193 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5194 5195 // Done. 5196 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5197 } 5198 5199 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5200 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5201 /// UDR combiner function. 5202 static void emitReductionCombiner(CodeGenFunction &CGF, 5203 const Expr *ReductionOp) { 5204 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5205 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5206 if (const auto *DRE = 5207 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5208 if (const auto *DRD = 5209 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5210 std::pair<llvm::Function *, llvm::Function *> Reduction = 5211 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5212 RValue Func = RValue::get(Reduction.first); 5213 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5214 CGF.EmitIgnoredExpr(ReductionOp); 5215 return; 5216 } 5217 CGF.EmitIgnoredExpr(ReductionOp); 5218 } 5219 5220 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5221 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5222 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5223 ArrayRef<const Expr *> ReductionOps) { 5224 ASTContext &C = CGM.getContext(); 5225 5226 // void reduction_func(void *LHSArg, void *RHSArg); 5227 FunctionArgList Args; 5228 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5229 ImplicitParamDecl::Other); 5230 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5231 ImplicitParamDecl::Other); 5232 Args.push_back(&LHSArg); 5233 Args.push_back(&RHSArg); 5234 const auto &CGFI = 5235 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5236 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5237 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5238 llvm::GlobalValue::InternalLinkage, Name, 5239 &CGM.getModule()); 5240 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5241 Fn->setDoesNotRecurse(); 5242 CodeGenFunction CGF(CGM); 5243 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5244 5245 // Dst = (void*[n])(LHSArg); 5246 // Src = (void*[n])(RHSArg); 5247 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5248 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5249 ArgsType), CGF.getPointerAlign()); 5250 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5251 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5252 ArgsType), CGF.getPointerAlign()); 5253 5254 // ... 5255 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5256 // ... 5257 CodeGenFunction::OMPPrivateScope Scope(CGF); 5258 auto IPriv = Privates.begin(); 5259 unsigned Idx = 0; 5260 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5261 const auto *RHSVar = 5262 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5263 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5264 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5265 }); 5266 const auto *LHSVar = 5267 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5268 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5269 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5270 }); 5271 QualType PrivTy = (*IPriv)->getType(); 5272 if (PrivTy->isVariablyModifiedType()) { 5273 // Get array size and emit VLA type. 5274 ++Idx; 5275 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5276 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5277 const VariableArrayType *VLA = 5278 CGF.getContext().getAsVariableArrayType(PrivTy); 5279 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5280 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5281 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5282 CGF.EmitVariablyModifiedType(PrivTy); 5283 } 5284 } 5285 Scope.Privatize(); 5286 IPriv = Privates.begin(); 5287 auto ILHS = LHSExprs.begin(); 5288 auto IRHS = RHSExprs.begin(); 5289 for (const Expr *E : ReductionOps) { 5290 if ((*IPriv)->getType()->isArrayType()) { 5291 // Emit reduction for array section. 5292 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5293 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5294 EmitOMPAggregateReduction( 5295 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5296 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5297 emitReductionCombiner(CGF, E); 5298 }); 5299 } else { 5300 // Emit reduction for array subscript or single variable. 5301 emitReductionCombiner(CGF, E); 5302 } 5303 ++IPriv; 5304 ++ILHS; 5305 ++IRHS; 5306 } 5307 Scope.ForceCleanup(); 5308 CGF.FinishFunction(); 5309 return Fn; 5310 } 5311 5312 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5313 const Expr *ReductionOp, 5314 const Expr *PrivateRef, 5315 const DeclRefExpr *LHS, 5316 const DeclRefExpr *RHS) { 5317 if (PrivateRef->getType()->isArrayType()) { 5318 // Emit reduction for array section. 5319 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5320 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5321 EmitOMPAggregateReduction( 5322 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5323 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5324 emitReductionCombiner(CGF, ReductionOp); 5325 }); 5326 } else { 5327 // Emit reduction for array subscript or single variable. 5328 emitReductionCombiner(CGF, ReductionOp); 5329 } 5330 } 5331 5332 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5333 ArrayRef<const Expr *> Privates, 5334 ArrayRef<const Expr *> LHSExprs, 5335 ArrayRef<const Expr *> RHSExprs, 5336 ArrayRef<const Expr *> ReductionOps, 5337 ReductionOptionsTy Options) { 5338 if (!CGF.HaveInsertPoint()) 5339 return; 5340 5341 bool WithNowait = Options.WithNowait; 5342 bool SimpleReduction = Options.SimpleReduction; 5343 5344 // Next code should be emitted for reduction: 5345 // 5346 // static kmp_critical_name lock = { 0 }; 5347 // 5348 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5349 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5350 // ... 5351 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5352 // *(Type<n>-1*)rhs[<n>-1]); 5353 // } 5354 // 5355 // ... 5356 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5357 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5358 // RedList, reduce_func, &<lock>)) { 5359 // case 1: 5360 // ... 5361 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5362 // ... 5363 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5364 // break; 5365 // case 2: 5366 // ... 5367 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5368 // ... 5369 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5370 // break; 5371 // default:; 5372 // } 5373 // 5374 // if SimpleReduction is true, only the next code is generated: 5375 // ... 5376 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5377 // ... 5378 5379 ASTContext &C = CGM.getContext(); 5380 5381 if (SimpleReduction) { 5382 CodeGenFunction::RunCleanupsScope Scope(CGF); 5383 auto IPriv = Privates.begin(); 5384 auto ILHS = LHSExprs.begin(); 5385 auto IRHS = RHSExprs.begin(); 5386 for (const Expr *E : ReductionOps) { 5387 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5388 cast<DeclRefExpr>(*IRHS)); 5389 ++IPriv; 5390 ++ILHS; 5391 ++IRHS; 5392 } 5393 return; 5394 } 5395 5396 // 1. Build a list of reduction variables. 5397 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5398 auto Size = RHSExprs.size(); 5399 for (const Expr *E : Privates) { 5400 if (E->getType()->isVariablyModifiedType()) 5401 // Reserve place for array size. 5402 ++Size; 5403 } 5404 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5405 QualType ReductionArrayTy = 5406 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5407 /*IndexTypeQuals=*/0); 5408 Address ReductionList = 5409 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5410 auto IPriv = Privates.begin(); 5411 unsigned Idx = 0; 5412 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5413 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5414 CGF.Builder.CreateStore( 5415 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5416 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5417 Elem); 5418 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5419 // Store array size. 5420 ++Idx; 5421 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5422 llvm::Value *Size = CGF.Builder.CreateIntCast( 5423 CGF.getVLASize( 5424 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5425 .NumElts, 5426 CGF.SizeTy, /*isSigned=*/false); 5427 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5428 Elem); 5429 } 5430 } 5431 5432 // 2. Emit reduce_func(). 5433 llvm::Function *ReductionFn = emitReductionFunction( 5434 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5435 LHSExprs, RHSExprs, ReductionOps); 5436 5437 // 3. Create static kmp_critical_name lock = { 0 }; 5438 std::string Name = getName({"reduction"}); 5439 llvm::Value *Lock = getCriticalRegionLock(Name); 5440 5441 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5442 // RedList, reduce_func, &<lock>); 5443 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5444 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5445 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5446 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5447 ReductionList.getPointer(), CGF.VoidPtrTy); 5448 llvm::Value *Args[] = { 5449 IdentTLoc, // ident_t *<loc> 5450 ThreadId, // i32 <gtid> 5451 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5452 ReductionArrayTySize, // size_type sizeof(RedList) 5453 RL, // void *RedList 5454 ReductionFn, // void (*) (void *, void *) <reduce_func> 5455 Lock // kmp_critical_name *&<lock> 5456 }; 5457 llvm::Value *Res = CGF.EmitRuntimeCall( 5458 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 5459 CGM.getModule(), 5460 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce), 5461 Args); 5462 5463 // 5. Build switch(res) 5464 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5465 llvm::SwitchInst *SwInst = 5466 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5467 5468 // 6. Build case 1: 5469 // ... 5470 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5471 // ... 5472 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5473 // break; 5474 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5475 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5476 CGF.EmitBlock(Case1BB); 5477 5478 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5479 llvm::Value *EndArgs[] = { 5480 IdentTLoc, // ident_t *<loc> 5481 ThreadId, // i32 <gtid> 5482 Lock // kmp_critical_name *&<lock> 5483 }; 5484 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5485 CodeGenFunction &CGF, PrePostActionTy &Action) { 5486 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5487 auto IPriv = Privates.begin(); 5488 auto ILHS = LHSExprs.begin(); 5489 auto IRHS = RHSExprs.begin(); 5490 for (const Expr *E : ReductionOps) { 5491 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5492 cast<DeclRefExpr>(*IRHS)); 5493 ++IPriv; 5494 ++ILHS; 5495 ++IRHS; 5496 } 5497 }; 5498 RegionCodeGenTy RCG(CodeGen); 5499 CommonActionTy Action( 5500 nullptr, llvm::None, 5501 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 5502 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait 5503 : OMPRTL___kmpc_end_reduce), 5504 EndArgs); 5505 RCG.setAction(Action); 5506 RCG(CGF); 5507 5508 CGF.EmitBranch(DefaultBB); 5509 5510 // 7. Build case 2: 5511 // ... 5512 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5513 // ... 5514 // break; 5515 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5516 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5517 CGF.EmitBlock(Case2BB); 5518 5519 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5520 CodeGenFunction &CGF, PrePostActionTy &Action) { 5521 auto ILHS = LHSExprs.begin(); 5522 auto IRHS = RHSExprs.begin(); 5523 auto IPriv = Privates.begin(); 5524 for (const Expr *E : ReductionOps) { 5525 const Expr *XExpr = nullptr; 5526 const Expr *EExpr = nullptr; 5527 const Expr *UpExpr = nullptr; 5528 BinaryOperatorKind BO = BO_Comma; 5529 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5530 if (BO->getOpcode() == BO_Assign) { 5531 XExpr = BO->getLHS(); 5532 UpExpr = BO->getRHS(); 5533 } 5534 } 5535 // Try to emit update expression as a simple atomic. 5536 const Expr *RHSExpr = UpExpr; 5537 if (RHSExpr) { 5538 // Analyze RHS part of the whole expression. 5539 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5540 RHSExpr->IgnoreParenImpCasts())) { 5541 // If this is a conditional operator, analyze its condition for 5542 // min/max reduction operator. 5543 RHSExpr = ACO->getCond(); 5544 } 5545 if (const auto *BORHS = 5546 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5547 EExpr = BORHS->getRHS(); 5548 BO = BORHS->getOpcode(); 5549 } 5550 } 5551 if (XExpr) { 5552 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5553 auto &&AtomicRedGen = [BO, VD, 5554 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5555 const Expr *EExpr, const Expr *UpExpr) { 5556 LValue X = CGF.EmitLValue(XExpr); 5557 RValue E; 5558 if (EExpr) 5559 E = CGF.EmitAnyExpr(EExpr); 5560 CGF.EmitOMPAtomicSimpleUpdateExpr( 5561 X, E, BO, /*IsXLHSInRHSPart=*/true, 5562 llvm::AtomicOrdering::Monotonic, Loc, 5563 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5564 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5565 PrivateScope.addPrivate( 5566 VD, [&CGF, VD, XRValue, Loc]() { 5567 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5568 CGF.emitOMPSimpleStore( 5569 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5570 VD->getType().getNonReferenceType(), Loc); 5571 return LHSTemp; 5572 }); 5573 (void)PrivateScope.Privatize(); 5574 return CGF.EmitAnyExpr(UpExpr); 5575 }); 5576 }; 5577 if ((*IPriv)->getType()->isArrayType()) { 5578 // Emit atomic reduction for array section. 5579 const auto *RHSVar = 5580 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5581 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5582 AtomicRedGen, XExpr, EExpr, UpExpr); 5583 } else { 5584 // Emit atomic reduction for array subscript or single variable. 5585 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5586 } 5587 } else { 5588 // Emit as a critical region. 5589 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5590 const Expr *, const Expr *) { 5591 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5592 std::string Name = RT.getName({"atomic_reduction"}); 5593 RT.emitCriticalRegion( 5594 CGF, Name, 5595 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5596 Action.Enter(CGF); 5597 emitReductionCombiner(CGF, E); 5598 }, 5599 Loc); 5600 }; 5601 if ((*IPriv)->getType()->isArrayType()) { 5602 const auto *LHSVar = 5603 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5604 const auto *RHSVar = 5605 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5606 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5607 CritRedGen); 5608 } else { 5609 CritRedGen(CGF, nullptr, nullptr, nullptr); 5610 } 5611 } 5612 ++ILHS; 5613 ++IRHS; 5614 ++IPriv; 5615 } 5616 }; 5617 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5618 if (!WithNowait) { 5619 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5620 llvm::Value *EndArgs[] = { 5621 IdentTLoc, // ident_t *<loc> 5622 ThreadId, // i32 <gtid> 5623 Lock // kmp_critical_name *&<lock> 5624 }; 5625 CommonActionTy Action(nullptr, llvm::None, 5626 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 5627 CGM.getModule(), OMPRTL___kmpc_end_reduce), 5628 EndArgs); 5629 AtomicRCG.setAction(Action); 5630 AtomicRCG(CGF); 5631 } else { 5632 AtomicRCG(CGF); 5633 } 5634 5635 CGF.EmitBranch(DefaultBB); 5636 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5637 } 5638 5639 /// Generates unique name for artificial threadprivate variables. 5640 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5641 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5642 const Expr *Ref) { 5643 SmallString<256> Buffer; 5644 llvm::raw_svector_ostream Out(Buffer); 5645 const clang::DeclRefExpr *DE; 5646 const VarDecl *D = ::getBaseDecl(Ref, DE); 5647 if (!D) 5648 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5649 D = D->getCanonicalDecl(); 5650 std::string Name = CGM.getOpenMPRuntime().getName( 5651 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5652 Out << Prefix << Name << "_" 5653 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5654 return std::string(Out.str()); 5655 } 5656 5657 /// Emits reduction initializer function: 5658 /// \code 5659 /// void @.red_init(void* %arg, void* %orig) { 5660 /// %0 = bitcast void* %arg to <type>* 5661 /// store <type> <init>, <type>* %0 5662 /// ret void 5663 /// } 5664 /// \endcode 5665 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 5666 SourceLocation Loc, 5667 ReductionCodeGen &RCG, unsigned N) { 5668 ASTContext &C = CGM.getContext(); 5669 QualType VoidPtrTy = C.VoidPtrTy; 5670 VoidPtrTy.addRestrict(); 5671 FunctionArgList Args; 5672 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5673 ImplicitParamDecl::Other); 5674 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5675 ImplicitParamDecl::Other); 5676 Args.emplace_back(&Param); 5677 Args.emplace_back(&ParamOrig); 5678 const auto &FnInfo = 5679 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5680 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5681 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 5682 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5683 Name, &CGM.getModule()); 5684 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5685 Fn->setDoesNotRecurse(); 5686 CodeGenFunction CGF(CGM); 5687 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5688 Address PrivateAddr = CGF.EmitLoadOfPointer( 5689 CGF.GetAddrOfLocalVar(&Param), 5690 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5691 llvm::Value *Size = nullptr; 5692 // If the size of the reduction item is non-constant, load it from global 5693 // threadprivate variable. 5694 if (RCG.getSizes(N).second) { 5695 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5696 CGF, CGM.getContext().getSizeType(), 5697 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5698 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5699 CGM.getContext().getSizeType(), Loc); 5700 } 5701 RCG.emitAggregateType(CGF, N, Size); 5702 LValue OrigLVal; 5703 // If initializer uses initializer from declare reduction construct, emit a 5704 // pointer to the address of the original reduction item (reuired by reduction 5705 // initializer) 5706 if (RCG.usesReductionInitializer(N)) { 5707 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig); 5708 SharedAddr = CGF.EmitLoadOfPointer( 5709 SharedAddr, 5710 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 5711 OrigLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 5712 } else { 5713 OrigLVal = CGF.MakeNaturalAlignAddrLValue( 5714 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 5715 CGM.getContext().VoidPtrTy); 5716 } 5717 // Emit the initializer: 5718 // %0 = bitcast void* %arg to <type>* 5719 // store <type> <init>, <type>* %0 5720 RCG.emitInitialization(CGF, N, PrivateAddr, OrigLVal, 5721 [](CodeGenFunction &) { return false; }); 5722 CGF.FinishFunction(); 5723 return Fn; 5724 } 5725 5726 /// Emits reduction combiner function: 5727 /// \code 5728 /// void @.red_comb(void* %arg0, void* %arg1) { 5729 /// %lhs = bitcast void* %arg0 to <type>* 5730 /// %rhs = bitcast void* %arg1 to <type>* 5731 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 5732 /// store <type> %2, <type>* %lhs 5733 /// ret void 5734 /// } 5735 /// \endcode 5736 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 5737 SourceLocation Loc, 5738 ReductionCodeGen &RCG, unsigned N, 5739 const Expr *ReductionOp, 5740 const Expr *LHS, const Expr *RHS, 5741 const Expr *PrivateRef) { 5742 ASTContext &C = CGM.getContext(); 5743 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 5744 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 5745 FunctionArgList Args; 5746 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 5747 C.VoidPtrTy, ImplicitParamDecl::Other); 5748 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5749 ImplicitParamDecl::Other); 5750 Args.emplace_back(&ParamInOut); 5751 Args.emplace_back(&ParamIn); 5752 const auto &FnInfo = 5753 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5754 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5755 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 5756 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5757 Name, &CGM.getModule()); 5758 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5759 Fn->setDoesNotRecurse(); 5760 CodeGenFunction CGF(CGM); 5761 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5762 llvm::Value *Size = nullptr; 5763 // If the size of the reduction item is non-constant, load it from global 5764 // threadprivate variable. 5765 if (RCG.getSizes(N).second) { 5766 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5767 CGF, CGM.getContext().getSizeType(), 5768 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5769 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5770 CGM.getContext().getSizeType(), Loc); 5771 } 5772 RCG.emitAggregateType(CGF, N, Size); 5773 // Remap lhs and rhs variables to the addresses of the function arguments. 5774 // %lhs = bitcast void* %arg0 to <type>* 5775 // %rhs = bitcast void* %arg1 to <type>* 5776 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5777 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 5778 // Pull out the pointer to the variable. 5779 Address PtrAddr = CGF.EmitLoadOfPointer( 5780 CGF.GetAddrOfLocalVar(&ParamInOut), 5781 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5782 return CGF.Builder.CreateElementBitCast( 5783 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 5784 }); 5785 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 5786 // Pull out the pointer to the variable. 5787 Address PtrAddr = CGF.EmitLoadOfPointer( 5788 CGF.GetAddrOfLocalVar(&ParamIn), 5789 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5790 return CGF.Builder.CreateElementBitCast( 5791 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 5792 }); 5793 PrivateScope.Privatize(); 5794 // Emit the combiner body: 5795 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 5796 // store <type> %2, <type>* %lhs 5797 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 5798 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 5799 cast<DeclRefExpr>(RHS)); 5800 CGF.FinishFunction(); 5801 return Fn; 5802 } 5803 5804 /// Emits reduction finalizer function: 5805 /// \code 5806 /// void @.red_fini(void* %arg) { 5807 /// %0 = bitcast void* %arg to <type>* 5808 /// <destroy>(<type>* %0) 5809 /// ret void 5810 /// } 5811 /// \endcode 5812 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 5813 SourceLocation Loc, 5814 ReductionCodeGen &RCG, unsigned N) { 5815 if (!RCG.needCleanups(N)) 5816 return nullptr; 5817 ASTContext &C = CGM.getContext(); 5818 FunctionArgList Args; 5819 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5820 ImplicitParamDecl::Other); 5821 Args.emplace_back(&Param); 5822 const auto &FnInfo = 5823 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5824 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5825 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 5826 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5827 Name, &CGM.getModule()); 5828 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5829 Fn->setDoesNotRecurse(); 5830 CodeGenFunction CGF(CGM); 5831 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5832 Address PrivateAddr = CGF.EmitLoadOfPointer( 5833 CGF.GetAddrOfLocalVar(&Param), 5834 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5835 llvm::Value *Size = nullptr; 5836 // If the size of the reduction item is non-constant, load it from global 5837 // threadprivate variable. 5838 if (RCG.getSizes(N).second) { 5839 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5840 CGF, CGM.getContext().getSizeType(), 5841 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5842 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5843 CGM.getContext().getSizeType(), Loc); 5844 } 5845 RCG.emitAggregateType(CGF, N, Size); 5846 // Emit the finalizer body: 5847 // <destroy>(<type>* %0) 5848 RCG.emitCleanups(CGF, N, PrivateAddr); 5849 CGF.FinishFunction(Loc); 5850 return Fn; 5851 } 5852 5853 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 5854 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 5855 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 5856 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 5857 return nullptr; 5858 5859 // Build typedef struct: 5860 // kmp_taskred_input { 5861 // void *reduce_shar; // shared reduction item 5862 // void *reduce_orig; // original reduction item used for initialization 5863 // size_t reduce_size; // size of data item 5864 // void *reduce_init; // data initialization routine 5865 // void *reduce_fini; // data finalization routine 5866 // void *reduce_comb; // data combiner routine 5867 // kmp_task_red_flags_t flags; // flags for additional info from compiler 5868 // } kmp_taskred_input_t; 5869 ASTContext &C = CGM.getContext(); 5870 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t"); 5871 RD->startDefinition(); 5872 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 5873 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 5874 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 5875 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 5876 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 5877 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 5878 const FieldDecl *FlagsFD = addFieldToRecordDecl( 5879 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 5880 RD->completeDefinition(); 5881 QualType RDType = C.getRecordType(RD); 5882 unsigned Size = Data.ReductionVars.size(); 5883 llvm::APInt ArraySize(/*numBits=*/64, Size); 5884 QualType ArrayRDType = C.getConstantArrayType( 5885 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5886 // kmp_task_red_input_t .rd_input.[Size]; 5887 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 5888 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, 5889 Data.ReductionCopies, Data.ReductionOps); 5890 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 5891 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 5892 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 5893 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 5894 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 5895 TaskRedInput.getPointer(), Idxs, 5896 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 5897 ".rd_input.gep."); 5898 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 5899 // ElemLVal.reduce_shar = &Shareds[Cnt]; 5900 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 5901 RCG.emitSharedOrigLValue(CGF, Cnt); 5902 llvm::Value *CastedShared = 5903 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 5904 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 5905 // ElemLVal.reduce_orig = &Origs[Cnt]; 5906 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD); 5907 llvm::Value *CastedOrig = 5908 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF)); 5909 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal); 5910 RCG.emitAggregateType(CGF, Cnt); 5911 llvm::Value *SizeValInChars; 5912 llvm::Value *SizeVal; 5913 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 5914 // We use delayed creation/initialization for VLAs and array sections. It is 5915 // required because runtime does not provide the way to pass the sizes of 5916 // VLAs/array sections to initializer/combiner/finalizer functions. Instead 5917 // threadprivate global variables are used to store these values and use 5918 // them in the functions. 5919 bool DelayedCreation = !!SizeVal; 5920 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 5921 /*isSigned=*/false); 5922 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 5923 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 5924 // ElemLVal.reduce_init = init; 5925 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 5926 llvm::Value *InitAddr = 5927 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 5928 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 5929 // ElemLVal.reduce_fini = fini; 5930 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 5931 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 5932 llvm::Value *FiniAddr = Fini 5933 ? CGF.EmitCastToVoidPtr(Fini) 5934 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 5935 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 5936 // ElemLVal.reduce_comb = comb; 5937 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 5938 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 5939 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 5940 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 5941 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 5942 // ElemLVal.flags = 0; 5943 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 5944 if (DelayedCreation) { 5945 CGF.EmitStoreOfScalar( 5946 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 5947 FlagsLVal); 5948 } else 5949 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 5950 FlagsLVal.getType()); 5951 } 5952 if (Data.IsReductionWithTaskMod) { 5953 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 5954 // is_ws, int num, void *data); 5955 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 5956 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 5957 CGM.IntTy, /*isSigned=*/true); 5958 llvm::Value *Args[] = { 5959 IdentTLoc, GTid, 5960 llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0, 5961 /*isSigned=*/true), 5962 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 5963 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5964 TaskRedInput.getPointer(), CGM.VoidPtrTy)}; 5965 return CGF.EmitRuntimeCall( 5966 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 5967 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init), 5968 Args); 5969 } 5970 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data); 5971 llvm::Value *Args[] = { 5972 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 5973 /*isSigned=*/true), 5974 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 5975 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 5976 CGM.VoidPtrTy)}; 5977 return CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 5978 CGM.getModule(), OMPRTL___kmpc_taskred_init), 5979 Args); 5980 } 5981 5982 void CGOpenMPRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 5983 SourceLocation Loc, 5984 bool IsWorksharingReduction) { 5985 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 5986 // is_ws, int num, void *data); 5987 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 5988 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 5989 CGM.IntTy, /*isSigned=*/true); 5990 llvm::Value *Args[] = {IdentTLoc, GTid, 5991 llvm::ConstantInt::get(CGM.IntTy, 5992 IsWorksharingReduction ? 1 : 0, 5993 /*isSigned=*/true)}; 5994 (void)CGF.EmitRuntimeCall( 5995 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 5996 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini), 5997 Args); 5998 } 5999 6000 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6001 SourceLocation Loc, 6002 ReductionCodeGen &RCG, 6003 unsigned N) { 6004 auto Sizes = RCG.getSizes(N); 6005 // Emit threadprivate global variable if the type is non-constant 6006 // (Sizes.second = nullptr). 6007 if (Sizes.second) { 6008 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6009 /*isSigned=*/false); 6010 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6011 CGF, CGM.getContext().getSizeType(), 6012 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6013 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6014 } 6015 } 6016 6017 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6018 SourceLocation Loc, 6019 llvm::Value *ReductionsPtr, 6020 LValue SharedLVal) { 6021 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6022 // *d); 6023 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6024 CGM.IntTy, 6025 /*isSigned=*/true), 6026 ReductionsPtr, 6027 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6028 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6029 return Address( 6030 CGF.EmitRuntimeCall( 6031 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 6032 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data), 6033 Args), 6034 SharedLVal.getAlignment()); 6035 } 6036 6037 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6038 SourceLocation Loc) { 6039 if (!CGF.HaveInsertPoint()) 6040 return; 6041 6042 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 6043 if (OMPBuilder) { 6044 OMPBuilder->CreateTaskwait(CGF.Builder); 6045 } else { 6046 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6047 // global_tid); 6048 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6049 // Ignore return result until untied tasks are supported. 6050 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 6051 CGM.getModule(), OMPRTL___kmpc_omp_taskwait), 6052 Args); 6053 } 6054 6055 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6056 Region->emitUntiedSwitch(CGF); 6057 } 6058 6059 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6060 OpenMPDirectiveKind InnerKind, 6061 const RegionCodeGenTy &CodeGen, 6062 bool HasCancel) { 6063 if (!CGF.HaveInsertPoint()) 6064 return; 6065 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6066 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6067 } 6068 6069 namespace { 6070 enum RTCancelKind { 6071 CancelNoreq = 0, 6072 CancelParallel = 1, 6073 CancelLoop = 2, 6074 CancelSections = 3, 6075 CancelTaskgroup = 4 6076 }; 6077 } // anonymous namespace 6078 6079 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6080 RTCancelKind CancelKind = CancelNoreq; 6081 if (CancelRegion == OMPD_parallel) 6082 CancelKind = CancelParallel; 6083 else if (CancelRegion == OMPD_for) 6084 CancelKind = CancelLoop; 6085 else if (CancelRegion == OMPD_sections) 6086 CancelKind = CancelSections; 6087 else { 6088 assert(CancelRegion == OMPD_taskgroup); 6089 CancelKind = CancelTaskgroup; 6090 } 6091 return CancelKind; 6092 } 6093 6094 void CGOpenMPRuntime::emitCancellationPointCall( 6095 CodeGenFunction &CGF, SourceLocation Loc, 6096 OpenMPDirectiveKind CancelRegion) { 6097 if (!CGF.HaveInsertPoint()) 6098 return; 6099 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6100 // global_tid, kmp_int32 cncl_kind); 6101 if (auto *OMPRegionInfo = 6102 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6103 // For 'cancellation point taskgroup', the task region info may not have a 6104 // cancel. This may instead happen in another adjacent task. 6105 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6106 llvm::Value *Args[] = { 6107 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6108 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6109 // Ignore return result until untied tasks are supported. 6110 llvm::Value *Result = CGF.EmitRuntimeCall( 6111 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 6112 CGM.getModule(), OMPRTL___kmpc_cancellationpoint), 6113 Args); 6114 // if (__kmpc_cancellationpoint()) { 6115 // exit from construct; 6116 // } 6117 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6118 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6119 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6120 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6121 CGF.EmitBlock(ExitBB); 6122 // exit from construct; 6123 CodeGenFunction::JumpDest CancelDest = 6124 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6125 CGF.EmitBranchThroughCleanup(CancelDest); 6126 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6127 } 6128 } 6129 } 6130 6131 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6132 const Expr *IfCond, 6133 OpenMPDirectiveKind CancelRegion) { 6134 if (!CGF.HaveInsertPoint()) 6135 return; 6136 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6137 // kmp_int32 cncl_kind); 6138 auto &M = CGM.getModule(); 6139 if (auto *OMPRegionInfo = 6140 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6141 auto &&ThenGen = [&M, Loc, CancelRegion, 6142 OMPRegionInfo](CodeGenFunction &CGF, PrePostActionTy &) { 6143 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6144 llvm::Value *Args[] = { 6145 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6146 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6147 // Ignore return result until untied tasks are supported. 6148 llvm::Value *Result = 6149 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 6150 M, OMPRTL___kmpc_cancel), 6151 Args); 6152 // if (__kmpc_cancel()) { 6153 // exit from construct; 6154 // } 6155 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6156 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6157 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6158 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6159 CGF.EmitBlock(ExitBB); 6160 // exit from construct; 6161 CodeGenFunction::JumpDest CancelDest = 6162 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6163 CGF.EmitBranchThroughCleanup(CancelDest); 6164 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6165 }; 6166 if (IfCond) { 6167 emitIfClause(CGF, IfCond, ThenGen, 6168 [](CodeGenFunction &, PrePostActionTy &) {}); 6169 } else { 6170 RegionCodeGenTy ThenRCG(ThenGen); 6171 ThenRCG(CGF); 6172 } 6173 } 6174 } 6175 6176 namespace { 6177 /// Cleanup action for uses_allocators support. 6178 class OMPUsesAllocatorsActionTy final : public PrePostActionTy { 6179 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators; 6180 6181 public: 6182 OMPUsesAllocatorsActionTy( 6183 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators) 6184 : Allocators(Allocators) {} 6185 void Enter(CodeGenFunction &CGF) override { 6186 if (!CGF.HaveInsertPoint()) 6187 return; 6188 for (const auto &AllocatorData : Allocators) { 6189 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsInit( 6190 CGF, AllocatorData.first, AllocatorData.second); 6191 } 6192 } 6193 void Exit(CodeGenFunction &CGF) override { 6194 if (!CGF.HaveInsertPoint()) 6195 return; 6196 for (const auto &AllocatorData : Allocators) { 6197 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsFini(CGF, 6198 AllocatorData.first); 6199 } 6200 } 6201 }; 6202 } // namespace 6203 6204 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6205 const OMPExecutableDirective &D, StringRef ParentName, 6206 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6207 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6208 assert(!ParentName.empty() && "Invalid target region parent name!"); 6209 HasEmittedTargetRegion = true; 6210 SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators; 6211 for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) { 6212 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 6213 const OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 6214 if (!D.AllocatorTraits) 6215 continue; 6216 Allocators.emplace_back(D.Allocator, D.AllocatorTraits); 6217 } 6218 } 6219 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators); 6220 CodeGen.setAction(UsesAllocatorAction); 6221 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6222 IsOffloadEntry, CodeGen); 6223 } 6224 6225 void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, 6226 const Expr *Allocator, 6227 const Expr *AllocatorTraits) { 6228 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6229 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6230 // Use default memspace handle. 6231 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 6232 llvm::Value *NumTraits = llvm::ConstantInt::get( 6233 CGF.IntTy, cast<ConstantArrayType>( 6234 AllocatorTraits->getType()->getAsArrayTypeUnsafe()) 6235 ->getSize() 6236 .getLimitedValue()); 6237 LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits); 6238 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6239 AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy); 6240 AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, 6241 AllocatorTraitsLVal.getBaseInfo(), 6242 AllocatorTraitsLVal.getTBAAInfo()); 6243 llvm::Value *Traits = 6244 CGF.EmitLoadOfScalar(AllocatorTraitsLVal, AllocatorTraits->getExprLoc()); 6245 6246 llvm::Value *AllocatorVal = 6247 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 6248 CGM.getModule(), OMPRTL___kmpc_init_allocator), 6249 {ThreadId, MemSpaceHandle, NumTraits, Traits}); 6250 // Store to allocator. 6251 CGF.EmitVarDecl(*cast<VarDecl>( 6252 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl())); 6253 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6254 AllocatorVal = 6255 CGF.EmitScalarConversion(AllocatorVal, CGF.getContext().VoidPtrTy, 6256 Allocator->getType(), Allocator->getExprLoc()); 6257 CGF.EmitStoreOfScalar(AllocatorVal, AllocatorLVal); 6258 } 6259 6260 void CGOpenMPRuntime::emitUsesAllocatorsFini(CodeGenFunction &CGF, 6261 const Expr *Allocator) { 6262 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6263 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6264 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6265 llvm::Value *AllocatorVal = 6266 CGF.EmitLoadOfScalar(AllocatorLVal, Allocator->getExprLoc()); 6267 AllocatorVal = CGF.EmitScalarConversion(AllocatorVal, Allocator->getType(), 6268 CGF.getContext().VoidPtrTy, 6269 Allocator->getExprLoc()); 6270 (void)CGF.EmitRuntimeCall( 6271 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 6272 CGM.getModule(), OMPRTL___kmpc_destroy_allocator), 6273 {ThreadId, AllocatorVal}); 6274 } 6275 6276 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6277 const OMPExecutableDirective &D, StringRef ParentName, 6278 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6279 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6280 // Create a unique name for the entry function using the source location 6281 // information of the current target region. The name will be something like: 6282 // 6283 // __omp_offloading_DD_FFFF_PP_lBB 6284 // 6285 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6286 // mangled name of the function that encloses the target region and BB is the 6287 // line number of the target region. 6288 6289 unsigned DeviceID; 6290 unsigned FileID; 6291 unsigned Line; 6292 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6293 Line); 6294 SmallString<64> EntryFnName; 6295 { 6296 llvm::raw_svector_ostream OS(EntryFnName); 6297 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6298 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6299 } 6300 6301 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6302 6303 CodeGenFunction CGF(CGM, true); 6304 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6305 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6306 6307 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6308 6309 // If this target outline function is not an offload entry, we don't need to 6310 // register it. 6311 if (!IsOffloadEntry) 6312 return; 6313 6314 // The target region ID is used by the runtime library to identify the current 6315 // target region, so it only has to be unique and not necessarily point to 6316 // anything. It could be the pointer to the outlined function that implements 6317 // the target region, but we aren't using that so that the compiler doesn't 6318 // need to keep that, and could therefore inline the host function if proven 6319 // worthwhile during optimization. In the other hand, if emitting code for the 6320 // device, the ID has to be the function address so that it can retrieved from 6321 // the offloading entry and launched by the runtime library. We also mark the 6322 // outlined function to have external linkage in case we are emitting code for 6323 // the device, because these functions will be entry points to the device. 6324 6325 if (CGM.getLangOpts().OpenMPIsDevice) { 6326 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6327 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6328 OutlinedFn->setDSOLocal(false); 6329 } else { 6330 std::string Name = getName({EntryFnName, "region_id"}); 6331 OutlinedFnID = new llvm::GlobalVariable( 6332 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6333 llvm::GlobalValue::WeakAnyLinkage, 6334 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6335 } 6336 6337 // Register the information for the entry associated with this target region. 6338 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6339 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6340 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6341 } 6342 6343 /// Checks if the expression is constant or does not have non-trivial function 6344 /// calls. 6345 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6346 // We can skip constant expressions. 6347 // We can skip expressions with trivial calls or simple expressions. 6348 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6349 !E->hasNonTrivialCall(Ctx)) && 6350 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6351 } 6352 6353 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6354 const Stmt *Body) { 6355 const Stmt *Child = Body->IgnoreContainers(); 6356 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6357 Child = nullptr; 6358 for (const Stmt *S : C->body()) { 6359 if (const auto *E = dyn_cast<Expr>(S)) { 6360 if (isTrivial(Ctx, E)) 6361 continue; 6362 } 6363 // Some of the statements can be ignored. 6364 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6365 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6366 continue; 6367 // Analyze declarations. 6368 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6369 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6370 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6371 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6372 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6373 isa<UsingDirectiveDecl>(D) || 6374 isa<OMPDeclareReductionDecl>(D) || 6375 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6376 return true; 6377 const auto *VD = dyn_cast<VarDecl>(D); 6378 if (!VD) 6379 return false; 6380 return VD->isConstexpr() || 6381 ((VD->getType().isTrivialType(Ctx) || 6382 VD->getType()->isReferenceType()) && 6383 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6384 })) 6385 continue; 6386 } 6387 // Found multiple children - cannot get the one child only. 6388 if (Child) 6389 return nullptr; 6390 Child = S; 6391 } 6392 if (Child) 6393 Child = Child->IgnoreContainers(); 6394 } 6395 return Child; 6396 } 6397 6398 /// Emit the number of teams for a target directive. Inspect the num_teams 6399 /// clause associated with a teams construct combined or closely nested 6400 /// with the target directive. 6401 /// 6402 /// Emit a team of size one for directives such as 'target parallel' that 6403 /// have no associated teams construct. 6404 /// 6405 /// Otherwise, return nullptr. 6406 static llvm::Value * 6407 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6408 const OMPExecutableDirective &D) { 6409 assert(!CGF.getLangOpts().OpenMPIsDevice && 6410 "Clauses associated with the teams directive expected to be emitted " 6411 "only for the host!"); 6412 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6413 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6414 "Expected target-based executable directive."); 6415 CGBuilderTy &Bld = CGF.Builder; 6416 switch (DirectiveKind) { 6417 case OMPD_target: { 6418 const auto *CS = D.getInnermostCapturedStmt(); 6419 const auto *Body = 6420 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6421 const Stmt *ChildStmt = 6422 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6423 if (const auto *NestedDir = 6424 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6425 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6426 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6427 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6428 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6429 const Expr *NumTeams = 6430 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6431 llvm::Value *NumTeamsVal = 6432 CGF.EmitScalarExpr(NumTeams, 6433 /*IgnoreResultAssign*/ true); 6434 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6435 /*isSigned=*/true); 6436 } 6437 return Bld.getInt32(0); 6438 } 6439 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6440 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6441 return Bld.getInt32(1); 6442 return Bld.getInt32(0); 6443 } 6444 return nullptr; 6445 } 6446 case OMPD_target_teams: 6447 case OMPD_target_teams_distribute: 6448 case OMPD_target_teams_distribute_simd: 6449 case OMPD_target_teams_distribute_parallel_for: 6450 case OMPD_target_teams_distribute_parallel_for_simd: { 6451 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6452 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6453 const Expr *NumTeams = 6454 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6455 llvm::Value *NumTeamsVal = 6456 CGF.EmitScalarExpr(NumTeams, 6457 /*IgnoreResultAssign*/ true); 6458 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6459 /*isSigned=*/true); 6460 } 6461 return Bld.getInt32(0); 6462 } 6463 case OMPD_target_parallel: 6464 case OMPD_target_parallel_for: 6465 case OMPD_target_parallel_for_simd: 6466 case OMPD_target_simd: 6467 return Bld.getInt32(1); 6468 case OMPD_parallel: 6469 case OMPD_for: 6470 case OMPD_parallel_for: 6471 case OMPD_parallel_master: 6472 case OMPD_parallel_sections: 6473 case OMPD_for_simd: 6474 case OMPD_parallel_for_simd: 6475 case OMPD_cancel: 6476 case OMPD_cancellation_point: 6477 case OMPD_ordered: 6478 case OMPD_threadprivate: 6479 case OMPD_allocate: 6480 case OMPD_task: 6481 case OMPD_simd: 6482 case OMPD_sections: 6483 case OMPD_section: 6484 case OMPD_single: 6485 case OMPD_master: 6486 case OMPD_critical: 6487 case OMPD_taskyield: 6488 case OMPD_barrier: 6489 case OMPD_taskwait: 6490 case OMPD_taskgroup: 6491 case OMPD_atomic: 6492 case OMPD_flush: 6493 case OMPD_depobj: 6494 case OMPD_scan: 6495 case OMPD_teams: 6496 case OMPD_target_data: 6497 case OMPD_target_exit_data: 6498 case OMPD_target_enter_data: 6499 case OMPD_distribute: 6500 case OMPD_distribute_simd: 6501 case OMPD_distribute_parallel_for: 6502 case OMPD_distribute_parallel_for_simd: 6503 case OMPD_teams_distribute: 6504 case OMPD_teams_distribute_simd: 6505 case OMPD_teams_distribute_parallel_for: 6506 case OMPD_teams_distribute_parallel_for_simd: 6507 case OMPD_target_update: 6508 case OMPD_declare_simd: 6509 case OMPD_declare_variant: 6510 case OMPD_begin_declare_variant: 6511 case OMPD_end_declare_variant: 6512 case OMPD_declare_target: 6513 case OMPD_end_declare_target: 6514 case OMPD_declare_reduction: 6515 case OMPD_declare_mapper: 6516 case OMPD_taskloop: 6517 case OMPD_taskloop_simd: 6518 case OMPD_master_taskloop: 6519 case OMPD_master_taskloop_simd: 6520 case OMPD_parallel_master_taskloop: 6521 case OMPD_parallel_master_taskloop_simd: 6522 case OMPD_requires: 6523 case OMPD_unknown: 6524 break; 6525 } 6526 llvm_unreachable("Unexpected directive kind."); 6527 } 6528 6529 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6530 llvm::Value *DefaultThreadLimitVal) { 6531 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6532 CGF.getContext(), CS->getCapturedStmt()); 6533 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6534 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6535 llvm::Value *NumThreads = nullptr; 6536 llvm::Value *CondVal = nullptr; 6537 // Handle if clause. If if clause present, the number of threads is 6538 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6539 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6540 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6541 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6542 const OMPIfClause *IfClause = nullptr; 6543 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6544 if (C->getNameModifier() == OMPD_unknown || 6545 C->getNameModifier() == OMPD_parallel) { 6546 IfClause = C; 6547 break; 6548 } 6549 } 6550 if (IfClause) { 6551 const Expr *Cond = IfClause->getCondition(); 6552 bool Result; 6553 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6554 if (!Result) 6555 return CGF.Builder.getInt32(1); 6556 } else { 6557 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6558 if (const auto *PreInit = 6559 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6560 for (const auto *I : PreInit->decls()) { 6561 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6562 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6563 } else { 6564 CodeGenFunction::AutoVarEmission Emission = 6565 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6566 CGF.EmitAutoVarCleanups(Emission); 6567 } 6568 } 6569 } 6570 CondVal = CGF.EvaluateExprAsBool(Cond); 6571 } 6572 } 6573 } 6574 // Check the value of num_threads clause iff if clause was not specified 6575 // or is not evaluated to false. 6576 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6577 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6578 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6579 const auto *NumThreadsClause = 6580 Dir->getSingleClause<OMPNumThreadsClause>(); 6581 CodeGenFunction::LexicalScope Scope( 6582 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6583 if (const auto *PreInit = 6584 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6585 for (const auto *I : PreInit->decls()) { 6586 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6587 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6588 } else { 6589 CodeGenFunction::AutoVarEmission Emission = 6590 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6591 CGF.EmitAutoVarCleanups(Emission); 6592 } 6593 } 6594 } 6595 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6596 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6597 /*isSigned=*/false); 6598 if (DefaultThreadLimitVal) 6599 NumThreads = CGF.Builder.CreateSelect( 6600 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6601 DefaultThreadLimitVal, NumThreads); 6602 } else { 6603 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6604 : CGF.Builder.getInt32(0); 6605 } 6606 // Process condition of the if clause. 6607 if (CondVal) { 6608 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6609 CGF.Builder.getInt32(1)); 6610 } 6611 return NumThreads; 6612 } 6613 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6614 return CGF.Builder.getInt32(1); 6615 return DefaultThreadLimitVal; 6616 } 6617 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6618 : CGF.Builder.getInt32(0); 6619 } 6620 6621 /// Emit the number of threads for a target directive. Inspect the 6622 /// thread_limit clause associated with a teams construct combined or closely 6623 /// nested with the target directive. 6624 /// 6625 /// Emit the num_threads clause for directives such as 'target parallel' that 6626 /// have no associated teams construct. 6627 /// 6628 /// Otherwise, return nullptr. 6629 static llvm::Value * 6630 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6631 const OMPExecutableDirective &D) { 6632 assert(!CGF.getLangOpts().OpenMPIsDevice && 6633 "Clauses associated with the teams directive expected to be emitted " 6634 "only for the host!"); 6635 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6636 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6637 "Expected target-based executable directive."); 6638 CGBuilderTy &Bld = CGF.Builder; 6639 llvm::Value *ThreadLimitVal = nullptr; 6640 llvm::Value *NumThreadsVal = nullptr; 6641 switch (DirectiveKind) { 6642 case OMPD_target: { 6643 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6644 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6645 return NumThreads; 6646 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6647 CGF.getContext(), CS->getCapturedStmt()); 6648 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6649 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6650 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6651 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6652 const auto *ThreadLimitClause = 6653 Dir->getSingleClause<OMPThreadLimitClause>(); 6654 CodeGenFunction::LexicalScope Scope( 6655 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6656 if (const auto *PreInit = 6657 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6658 for (const auto *I : PreInit->decls()) { 6659 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6660 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6661 } else { 6662 CodeGenFunction::AutoVarEmission Emission = 6663 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6664 CGF.EmitAutoVarCleanups(Emission); 6665 } 6666 } 6667 } 6668 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6669 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6670 ThreadLimitVal = 6671 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6672 } 6673 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6674 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6675 CS = Dir->getInnermostCapturedStmt(); 6676 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6677 CGF.getContext(), CS->getCapturedStmt()); 6678 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6679 } 6680 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6681 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6682 CS = Dir->getInnermostCapturedStmt(); 6683 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6684 return NumThreads; 6685 } 6686 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6687 return Bld.getInt32(1); 6688 } 6689 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6690 } 6691 case OMPD_target_teams: { 6692 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6693 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6694 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6695 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6696 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6697 ThreadLimitVal = 6698 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6699 } 6700 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6701 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6702 return NumThreads; 6703 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6704 CGF.getContext(), CS->getCapturedStmt()); 6705 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6706 if (Dir->getDirectiveKind() == OMPD_distribute) { 6707 CS = Dir->getInnermostCapturedStmt(); 6708 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6709 return NumThreads; 6710 } 6711 } 6712 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6713 } 6714 case OMPD_target_teams_distribute: 6715 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6716 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6717 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6718 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6719 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6720 ThreadLimitVal = 6721 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6722 } 6723 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6724 case OMPD_target_parallel: 6725 case OMPD_target_parallel_for: 6726 case OMPD_target_parallel_for_simd: 6727 case OMPD_target_teams_distribute_parallel_for: 6728 case OMPD_target_teams_distribute_parallel_for_simd: { 6729 llvm::Value *CondVal = nullptr; 6730 // Handle if clause. If if clause present, the number of threads is 6731 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6732 if (D.hasClausesOfKind<OMPIfClause>()) { 6733 const OMPIfClause *IfClause = nullptr; 6734 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6735 if (C->getNameModifier() == OMPD_unknown || 6736 C->getNameModifier() == OMPD_parallel) { 6737 IfClause = C; 6738 break; 6739 } 6740 } 6741 if (IfClause) { 6742 const Expr *Cond = IfClause->getCondition(); 6743 bool Result; 6744 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6745 if (!Result) 6746 return Bld.getInt32(1); 6747 } else { 6748 CodeGenFunction::RunCleanupsScope Scope(CGF); 6749 CondVal = CGF.EvaluateExprAsBool(Cond); 6750 } 6751 } 6752 } 6753 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6754 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6755 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6756 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6757 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6758 ThreadLimitVal = 6759 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6760 } 6761 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6762 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6763 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6764 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6765 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6766 NumThreadsVal = 6767 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6768 ThreadLimitVal = ThreadLimitVal 6769 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6770 ThreadLimitVal), 6771 NumThreadsVal, ThreadLimitVal) 6772 : NumThreadsVal; 6773 } 6774 if (!ThreadLimitVal) 6775 ThreadLimitVal = Bld.getInt32(0); 6776 if (CondVal) 6777 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6778 return ThreadLimitVal; 6779 } 6780 case OMPD_target_teams_distribute_simd: 6781 case OMPD_target_simd: 6782 return Bld.getInt32(1); 6783 case OMPD_parallel: 6784 case OMPD_for: 6785 case OMPD_parallel_for: 6786 case OMPD_parallel_master: 6787 case OMPD_parallel_sections: 6788 case OMPD_for_simd: 6789 case OMPD_parallel_for_simd: 6790 case OMPD_cancel: 6791 case OMPD_cancellation_point: 6792 case OMPD_ordered: 6793 case OMPD_threadprivate: 6794 case OMPD_allocate: 6795 case OMPD_task: 6796 case OMPD_simd: 6797 case OMPD_sections: 6798 case OMPD_section: 6799 case OMPD_single: 6800 case OMPD_master: 6801 case OMPD_critical: 6802 case OMPD_taskyield: 6803 case OMPD_barrier: 6804 case OMPD_taskwait: 6805 case OMPD_taskgroup: 6806 case OMPD_atomic: 6807 case OMPD_flush: 6808 case OMPD_depobj: 6809 case OMPD_scan: 6810 case OMPD_teams: 6811 case OMPD_target_data: 6812 case OMPD_target_exit_data: 6813 case OMPD_target_enter_data: 6814 case OMPD_distribute: 6815 case OMPD_distribute_simd: 6816 case OMPD_distribute_parallel_for: 6817 case OMPD_distribute_parallel_for_simd: 6818 case OMPD_teams_distribute: 6819 case OMPD_teams_distribute_simd: 6820 case OMPD_teams_distribute_parallel_for: 6821 case OMPD_teams_distribute_parallel_for_simd: 6822 case OMPD_target_update: 6823 case OMPD_declare_simd: 6824 case OMPD_declare_variant: 6825 case OMPD_begin_declare_variant: 6826 case OMPD_end_declare_variant: 6827 case OMPD_declare_target: 6828 case OMPD_end_declare_target: 6829 case OMPD_declare_reduction: 6830 case OMPD_declare_mapper: 6831 case OMPD_taskloop: 6832 case OMPD_taskloop_simd: 6833 case OMPD_master_taskloop: 6834 case OMPD_master_taskloop_simd: 6835 case OMPD_parallel_master_taskloop: 6836 case OMPD_parallel_master_taskloop_simd: 6837 case OMPD_requires: 6838 case OMPD_unknown: 6839 break; 6840 } 6841 llvm_unreachable("Unsupported directive kind."); 6842 } 6843 6844 namespace { 6845 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 6846 6847 // Utility to handle information from clauses associated with a given 6848 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 6849 // It provides a convenient interface to obtain the information and generate 6850 // code for that information. 6851 class MappableExprsHandler { 6852 public: 6853 /// Values for bit flags used to specify the mapping type for 6854 /// offloading. 6855 enum OpenMPOffloadMappingFlags : uint64_t { 6856 /// No flags 6857 OMP_MAP_NONE = 0x0, 6858 /// Allocate memory on the device and move data from host to device. 6859 OMP_MAP_TO = 0x01, 6860 /// Allocate memory on the device and move data from device to host. 6861 OMP_MAP_FROM = 0x02, 6862 /// Always perform the requested mapping action on the element, even 6863 /// if it was already mapped before. 6864 OMP_MAP_ALWAYS = 0x04, 6865 /// Delete the element from the device environment, ignoring the 6866 /// current reference count associated with the element. 6867 OMP_MAP_DELETE = 0x08, 6868 /// The element being mapped is a pointer-pointee pair; both the 6869 /// pointer and the pointee should be mapped. 6870 OMP_MAP_PTR_AND_OBJ = 0x10, 6871 /// This flags signals that the base address of an entry should be 6872 /// passed to the target kernel as an argument. 6873 OMP_MAP_TARGET_PARAM = 0x20, 6874 /// Signal that the runtime library has to return the device pointer 6875 /// in the current position for the data being mapped. Used when we have the 6876 /// use_device_ptr clause. 6877 OMP_MAP_RETURN_PARAM = 0x40, 6878 /// This flag signals that the reference being passed is a pointer to 6879 /// private data. 6880 OMP_MAP_PRIVATE = 0x80, 6881 /// Pass the element to the device by value. 6882 OMP_MAP_LITERAL = 0x100, 6883 /// Implicit map 6884 OMP_MAP_IMPLICIT = 0x200, 6885 /// Close is a hint to the runtime to allocate memory close to 6886 /// the target device. 6887 OMP_MAP_CLOSE = 0x400, 6888 /// The 16 MSBs of the flags indicate whether the entry is member of some 6889 /// struct/class. 6890 OMP_MAP_MEMBER_OF = 0xffff000000000000, 6891 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 6892 }; 6893 6894 /// Get the offset of the OMP_MAP_MEMBER_OF field. 6895 static unsigned getFlagMemberOffset() { 6896 unsigned Offset = 0; 6897 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 6898 Remain = Remain >> 1) 6899 Offset++; 6900 return Offset; 6901 } 6902 6903 /// Class that associates information with a base pointer to be passed to the 6904 /// runtime library. 6905 class BasePointerInfo { 6906 /// The base pointer. 6907 llvm::Value *Ptr = nullptr; 6908 /// The base declaration that refers to this device pointer, or null if 6909 /// there is none. 6910 const ValueDecl *DevPtrDecl = nullptr; 6911 6912 public: 6913 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 6914 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 6915 llvm::Value *operator*() const { return Ptr; } 6916 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 6917 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 6918 }; 6919 6920 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 6921 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 6922 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 6923 6924 /// Map between a struct and the its lowest & highest elements which have been 6925 /// mapped. 6926 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 6927 /// HE(FieldIndex, Pointer)} 6928 struct StructRangeInfoTy { 6929 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 6930 0, Address::invalid()}; 6931 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 6932 0, Address::invalid()}; 6933 Address Base = Address::invalid(); 6934 }; 6935 6936 private: 6937 /// Kind that defines how a device pointer has to be returned. 6938 struct MapInfo { 6939 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 6940 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 6941 ArrayRef<OpenMPMapModifierKind> MapModifiers; 6942 bool ReturnDevicePointer = false; 6943 bool IsImplicit = false; 6944 6945 MapInfo() = default; 6946 MapInfo( 6947 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 6948 OpenMPMapClauseKind MapType, 6949 ArrayRef<OpenMPMapModifierKind> MapModifiers, 6950 bool ReturnDevicePointer, bool IsImplicit) 6951 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 6952 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 6953 }; 6954 6955 /// If use_device_ptr is used on a pointer which is a struct member and there 6956 /// is no map information about it, then emission of that entry is deferred 6957 /// until the whole struct has been processed. 6958 struct DeferredDevicePtrEntryTy { 6959 const Expr *IE = nullptr; 6960 const ValueDecl *VD = nullptr; 6961 6962 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 6963 : IE(IE), VD(VD) {} 6964 }; 6965 6966 /// The target directive from where the mappable clauses were extracted. It 6967 /// is either a executable directive or a user-defined mapper directive. 6968 llvm::PointerUnion<const OMPExecutableDirective *, 6969 const OMPDeclareMapperDecl *> 6970 CurDir; 6971 6972 /// Function the directive is being generated for. 6973 CodeGenFunction &CGF; 6974 6975 /// Set of all first private variables in the current directive. 6976 /// bool data is set to true if the variable is implicitly marked as 6977 /// firstprivate, false otherwise. 6978 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 6979 6980 /// Map between device pointer declarations and their expression components. 6981 /// The key value for declarations in 'this' is null. 6982 llvm::DenseMap< 6983 const ValueDecl *, 6984 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 6985 DevPointersMap; 6986 6987 llvm::Value *getExprTypeSize(const Expr *E) const { 6988 QualType ExprTy = E->getType().getCanonicalType(); 6989 6990 // Calculate the size for array shaping expression. 6991 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) { 6992 llvm::Value *Size = 6993 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType()); 6994 for (const Expr *SE : OAE->getDimensions()) { 6995 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 6996 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 6997 CGF.getContext().getSizeType(), 6998 SE->getExprLoc()); 6999 Size = CGF.Builder.CreateNUWMul(Size, Sz); 7000 } 7001 return Size; 7002 } 7003 7004 // Reference types are ignored for mapping purposes. 7005 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7006 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7007 7008 // Given that an array section is considered a built-in type, we need to 7009 // do the calculation based on the length of the section instead of relying 7010 // on CGF.getTypeSize(E->getType()). 7011 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7012 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7013 OAE->getBase()->IgnoreParenImpCasts()) 7014 .getCanonicalType(); 7015 7016 // If there is no length associated with the expression and lower bound is 7017 // not specified too, that means we are using the whole length of the 7018 // base. 7019 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7020 !OAE->getLowerBound()) 7021 return CGF.getTypeSize(BaseTy); 7022 7023 llvm::Value *ElemSize; 7024 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7025 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7026 } else { 7027 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7028 assert(ATy && "Expecting array type if not a pointer type."); 7029 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7030 } 7031 7032 // If we don't have a length at this point, that is because we have an 7033 // array section with a single element. 7034 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7035 return ElemSize; 7036 7037 if (const Expr *LenExpr = OAE->getLength()) { 7038 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7039 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7040 CGF.getContext().getSizeType(), 7041 LenExpr->getExprLoc()); 7042 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7043 } 7044 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7045 OAE->getLowerBound() && "expected array_section[lb:]."); 7046 // Size = sizetype - lb * elemtype; 7047 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7048 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7049 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7050 CGF.getContext().getSizeType(), 7051 OAE->getLowerBound()->getExprLoc()); 7052 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7053 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7054 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7055 LengthVal = CGF.Builder.CreateSelect( 7056 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7057 return LengthVal; 7058 } 7059 return CGF.getTypeSize(ExprTy); 7060 } 7061 7062 /// Return the corresponding bits for a given map clause modifier. Add 7063 /// a flag marking the map as a pointer if requested. Add a flag marking the 7064 /// map as the first one of a series of maps that relate to the same map 7065 /// expression. 7066 OpenMPOffloadMappingFlags getMapTypeBits( 7067 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7068 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7069 OpenMPOffloadMappingFlags Bits = 7070 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7071 switch (MapType) { 7072 case OMPC_MAP_alloc: 7073 case OMPC_MAP_release: 7074 // alloc and release is the default behavior in the runtime library, i.e. 7075 // if we don't pass any bits alloc/release that is what the runtime is 7076 // going to do. Therefore, we don't need to signal anything for these two 7077 // type modifiers. 7078 break; 7079 case OMPC_MAP_to: 7080 Bits |= OMP_MAP_TO; 7081 break; 7082 case OMPC_MAP_from: 7083 Bits |= OMP_MAP_FROM; 7084 break; 7085 case OMPC_MAP_tofrom: 7086 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7087 break; 7088 case OMPC_MAP_delete: 7089 Bits |= OMP_MAP_DELETE; 7090 break; 7091 case OMPC_MAP_unknown: 7092 llvm_unreachable("Unexpected map type!"); 7093 } 7094 if (AddPtrFlag) 7095 Bits |= OMP_MAP_PTR_AND_OBJ; 7096 if (AddIsTargetParamFlag) 7097 Bits |= OMP_MAP_TARGET_PARAM; 7098 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7099 != MapModifiers.end()) 7100 Bits |= OMP_MAP_ALWAYS; 7101 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7102 != MapModifiers.end()) 7103 Bits |= OMP_MAP_CLOSE; 7104 return Bits; 7105 } 7106 7107 /// Return true if the provided expression is a final array section. A 7108 /// final array section, is one whose length can't be proved to be one. 7109 bool isFinalArraySectionExpression(const Expr *E) const { 7110 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7111 7112 // It is not an array section and therefore not a unity-size one. 7113 if (!OASE) 7114 return false; 7115 7116 // An array section with no colon always refer to a single element. 7117 if (OASE->getColonLoc().isInvalid()) 7118 return false; 7119 7120 const Expr *Length = OASE->getLength(); 7121 7122 // If we don't have a length we have to check if the array has size 1 7123 // for this dimension. Also, we should always expect a length if the 7124 // base type is pointer. 7125 if (!Length) { 7126 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7127 OASE->getBase()->IgnoreParenImpCasts()) 7128 .getCanonicalType(); 7129 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7130 return ATy->getSize().getSExtValue() != 1; 7131 // If we don't have a constant dimension length, we have to consider 7132 // the current section as having any size, so it is not necessarily 7133 // unitary. If it happen to be unity size, that's user fault. 7134 return true; 7135 } 7136 7137 // Check if the length evaluates to 1. 7138 Expr::EvalResult Result; 7139 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7140 return true; // Can have more that size 1. 7141 7142 llvm::APSInt ConstLength = Result.Val.getInt(); 7143 return ConstLength.getSExtValue() != 1; 7144 } 7145 7146 /// Generate the base pointers, section pointers, sizes and map type 7147 /// bits for the provided map type, map modifier, and expression components. 7148 /// \a IsFirstComponent should be set to true if the provided set of 7149 /// components is the first associated with a capture. 7150 void generateInfoForComponentList( 7151 OpenMPMapClauseKind MapType, 7152 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7153 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7154 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7155 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7156 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7157 bool IsImplicit, 7158 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7159 OverlappedElements = llvm::None) const { 7160 // The following summarizes what has to be generated for each map and the 7161 // types below. The generated information is expressed in this order: 7162 // base pointer, section pointer, size, flags 7163 // (to add to the ones that come from the map type and modifier). 7164 // 7165 // double d; 7166 // int i[100]; 7167 // float *p; 7168 // 7169 // struct S1 { 7170 // int i; 7171 // float f[50]; 7172 // } 7173 // struct S2 { 7174 // int i; 7175 // float f[50]; 7176 // S1 s; 7177 // double *p; 7178 // struct S2 *ps; 7179 // } 7180 // S2 s; 7181 // S2 *ps; 7182 // 7183 // map(d) 7184 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7185 // 7186 // map(i) 7187 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7188 // 7189 // map(i[1:23]) 7190 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7191 // 7192 // map(p) 7193 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7194 // 7195 // map(p[1:24]) 7196 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7197 // 7198 // map(s) 7199 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7200 // 7201 // map(s.i) 7202 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7203 // 7204 // map(s.s.f) 7205 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7206 // 7207 // map(s.p) 7208 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7209 // 7210 // map(to: s.p[:22]) 7211 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7212 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7213 // &(s.p), &(s.p[0]), 22*sizeof(double), 7214 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7215 // (*) alloc space for struct members, only this is a target parameter 7216 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7217 // optimizes this entry out, same in the examples below) 7218 // (***) map the pointee (map: to) 7219 // 7220 // map(s.ps) 7221 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7222 // 7223 // map(from: s.ps->s.i) 7224 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7225 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7226 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7227 // 7228 // map(to: s.ps->ps) 7229 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7230 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7231 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7232 // 7233 // map(s.ps->ps->ps) 7234 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7235 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7236 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7237 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7238 // 7239 // map(to: s.ps->ps->s.f[:22]) 7240 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7241 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7242 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7243 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7244 // 7245 // map(ps) 7246 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7247 // 7248 // map(ps->i) 7249 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7250 // 7251 // map(ps->s.f) 7252 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7253 // 7254 // map(from: ps->p) 7255 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7256 // 7257 // map(to: ps->p[:22]) 7258 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7259 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7260 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7261 // 7262 // map(ps->ps) 7263 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7264 // 7265 // map(from: ps->ps->s.i) 7266 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7267 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7268 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7269 // 7270 // map(from: ps->ps->ps) 7271 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7272 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7273 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7274 // 7275 // map(ps->ps->ps->ps) 7276 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7277 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7278 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7279 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7280 // 7281 // map(to: ps->ps->ps->s.f[:22]) 7282 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7283 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7284 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7285 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7286 // 7287 // map(to: s.f[:22]) map(from: s.p[:33]) 7288 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7289 // sizeof(double*) (**), TARGET_PARAM 7290 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7291 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7292 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7293 // (*) allocate contiguous space needed to fit all mapped members even if 7294 // we allocate space for members not mapped (in this example, 7295 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7296 // them as well because they fall between &s.f[0] and &s.p) 7297 // 7298 // map(from: s.f[:22]) map(to: ps->p[:33]) 7299 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7300 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7301 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7302 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7303 // (*) the struct this entry pertains to is the 2nd element in the list of 7304 // arguments, hence MEMBER_OF(2) 7305 // 7306 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7307 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7308 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7309 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7310 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7311 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7312 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7313 // (*) the struct this entry pertains to is the 4th element in the list 7314 // of arguments, hence MEMBER_OF(4) 7315 7316 // Track if the map information being generated is the first for a capture. 7317 bool IsCaptureFirstInfo = IsFirstComponentList; 7318 // When the variable is on a declare target link or in a to clause with 7319 // unified memory, a reference is needed to hold the host/device address 7320 // of the variable. 7321 bool RequiresReference = false; 7322 7323 // Scan the components from the base to the complete expression. 7324 auto CI = Components.rbegin(); 7325 auto CE = Components.rend(); 7326 auto I = CI; 7327 7328 // Track if the map information being generated is the first for a list of 7329 // components. 7330 bool IsExpressionFirstInfo = true; 7331 Address BP = Address::invalid(); 7332 const Expr *AssocExpr = I->getAssociatedExpression(); 7333 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7334 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7335 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr); 7336 7337 if (isa<MemberExpr>(AssocExpr)) { 7338 // The base is the 'this' pointer. The content of the pointer is going 7339 // to be the base of the field being mapped. 7340 BP = CGF.LoadCXXThisAddress(); 7341 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7342 (OASE && 7343 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7344 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7345 } else if (OAShE && 7346 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) { 7347 BP = Address( 7348 CGF.EmitScalarExpr(OAShE->getBase()), 7349 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType())); 7350 } else { 7351 // The base is the reference to the variable. 7352 // BP = &Var. 7353 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7354 if (const auto *VD = 7355 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7356 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7357 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7358 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7359 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7360 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7361 RequiresReference = true; 7362 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7363 } 7364 } 7365 } 7366 7367 // If the variable is a pointer and is being dereferenced (i.e. is not 7368 // the last component), the base has to be the pointer itself, not its 7369 // reference. References are ignored for mapping purposes. 7370 QualType Ty = 7371 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7372 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7373 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7374 7375 // We do not need to generate individual map information for the 7376 // pointer, it can be associated with the combined storage. 7377 ++I; 7378 } 7379 } 7380 7381 // Track whether a component of the list should be marked as MEMBER_OF some 7382 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7383 // in a component list should be marked as MEMBER_OF, all subsequent entries 7384 // do not belong to the base struct. E.g. 7385 // struct S2 s; 7386 // s.ps->ps->ps->f[:] 7387 // (1) (2) (3) (4) 7388 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7389 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7390 // is the pointee of ps(2) which is not member of struct s, so it should not 7391 // be marked as such (it is still PTR_AND_OBJ). 7392 // The variable is initialized to false so that PTR_AND_OBJ entries which 7393 // are not struct members are not considered (e.g. array of pointers to 7394 // data). 7395 bool ShouldBeMemberOf = false; 7396 7397 // Variable keeping track of whether or not we have encountered a component 7398 // in the component list which is a member expression. Useful when we have a 7399 // pointer or a final array section, in which case it is the previous 7400 // component in the list which tells us whether we have a member expression. 7401 // E.g. X.f[:] 7402 // While processing the final array section "[:]" it is "f" which tells us 7403 // whether we are dealing with a member of a declared struct. 7404 const MemberExpr *EncounteredME = nullptr; 7405 7406 for (; I != CE; ++I) { 7407 // If the current component is member of a struct (parent struct) mark it. 7408 if (!EncounteredME) { 7409 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7410 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7411 // as MEMBER_OF the parent struct. 7412 if (EncounteredME) 7413 ShouldBeMemberOf = true; 7414 } 7415 7416 auto Next = std::next(I); 7417 7418 // We need to generate the addresses and sizes if this is the last 7419 // component, if the component is a pointer or if it is an array section 7420 // whose length can't be proved to be one. If this is a pointer, it 7421 // becomes the base address for the following components. 7422 7423 // A final array section, is one whose length can't be proved to be one. 7424 bool IsFinalArraySection = 7425 isFinalArraySectionExpression(I->getAssociatedExpression()); 7426 7427 // Get information on whether the element is a pointer. Have to do a 7428 // special treatment for array sections given that they are built-in 7429 // types. 7430 const auto *OASE = 7431 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7432 const auto *OAShE = 7433 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression()); 7434 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 7435 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 7436 bool IsPointer = 7437 OAShE || 7438 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7439 .getCanonicalType() 7440 ->isAnyPointerType()) || 7441 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7442 bool IsNonDerefPointer = IsPointer && !UO && !BO; 7443 7444 if (Next == CE || IsNonDerefPointer || IsFinalArraySection) { 7445 // If this is not the last component, we expect the pointer to be 7446 // associated with an array expression or member expression. 7447 assert((Next == CE || 7448 isa<MemberExpr>(Next->getAssociatedExpression()) || 7449 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7450 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 7451 isa<UnaryOperator>(Next->getAssociatedExpression()) || 7452 isa<BinaryOperator>(Next->getAssociatedExpression())) && 7453 "Unexpected expression"); 7454 7455 Address LB = Address::invalid(); 7456 if (OAShE) { 7457 LB = Address(CGF.EmitScalarExpr(OAShE->getBase()), 7458 CGF.getContext().getTypeAlignInChars( 7459 OAShE->getBase()->getType())); 7460 } else { 7461 LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7462 .getAddress(CGF); 7463 } 7464 7465 // If this component is a pointer inside the base struct then we don't 7466 // need to create any entry for it - it will be combined with the object 7467 // it is pointing to into a single PTR_AND_OBJ entry. 7468 bool IsMemberPointer = 7469 IsPointer && EncounteredME && 7470 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7471 EncounteredME); 7472 if (!OverlappedElements.empty()) { 7473 // Handle base element with the info for overlapped elements. 7474 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7475 assert(Next == CE && 7476 "Expected last element for the overlapped elements."); 7477 assert(!IsPointer && 7478 "Unexpected base element with the pointer type."); 7479 // Mark the whole struct as the struct that requires allocation on the 7480 // device. 7481 PartialStruct.LowestElem = {0, LB}; 7482 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7483 I->getAssociatedExpression()->getType()); 7484 Address HB = CGF.Builder.CreateConstGEP( 7485 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7486 CGF.VoidPtrTy), 7487 TypeSize.getQuantity() - 1); 7488 PartialStruct.HighestElem = { 7489 std::numeric_limits<decltype( 7490 PartialStruct.HighestElem.first)>::max(), 7491 HB}; 7492 PartialStruct.Base = BP; 7493 // Emit data for non-overlapped data. 7494 OpenMPOffloadMappingFlags Flags = 7495 OMP_MAP_MEMBER_OF | 7496 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7497 /*AddPtrFlag=*/false, 7498 /*AddIsTargetParamFlag=*/false); 7499 LB = BP; 7500 llvm::Value *Size = nullptr; 7501 // Do bitcopy of all non-overlapped structure elements. 7502 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7503 Component : OverlappedElements) { 7504 Address ComponentLB = Address::invalid(); 7505 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7506 Component) { 7507 if (MC.getAssociatedDeclaration()) { 7508 ComponentLB = 7509 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7510 .getAddress(CGF); 7511 Size = CGF.Builder.CreatePtrDiff( 7512 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7513 CGF.EmitCastToVoidPtr(LB.getPointer())); 7514 break; 7515 } 7516 } 7517 BasePointers.push_back(BP.getPointer()); 7518 Pointers.push_back(LB.getPointer()); 7519 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7520 /*isSigned=*/true)); 7521 Types.push_back(Flags); 7522 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7523 } 7524 BasePointers.push_back(BP.getPointer()); 7525 Pointers.push_back(LB.getPointer()); 7526 Size = CGF.Builder.CreatePtrDiff( 7527 CGF.EmitCastToVoidPtr( 7528 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7529 CGF.EmitCastToVoidPtr(LB.getPointer())); 7530 Sizes.push_back( 7531 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7532 Types.push_back(Flags); 7533 break; 7534 } 7535 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7536 if (!IsMemberPointer) { 7537 BasePointers.push_back(BP.getPointer()); 7538 Pointers.push_back(LB.getPointer()); 7539 Sizes.push_back( 7540 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7541 7542 // We need to add a pointer flag for each map that comes from the 7543 // same expression except for the first one. We also need to signal 7544 // this map is the first one that relates with the current capture 7545 // (there is a set of entries for each capture). 7546 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7547 MapType, MapModifiers, IsImplicit, 7548 !IsExpressionFirstInfo || RequiresReference, 7549 IsCaptureFirstInfo && !RequiresReference); 7550 7551 if (!IsExpressionFirstInfo) { 7552 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7553 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7554 if (IsPointer) 7555 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7556 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7557 7558 if (ShouldBeMemberOf) { 7559 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7560 // should be later updated with the correct value of MEMBER_OF. 7561 Flags |= OMP_MAP_MEMBER_OF; 7562 // From now on, all subsequent PTR_AND_OBJ entries should not be 7563 // marked as MEMBER_OF. 7564 ShouldBeMemberOf = false; 7565 } 7566 } 7567 7568 Types.push_back(Flags); 7569 } 7570 7571 // If we have encountered a member expression so far, keep track of the 7572 // mapped member. If the parent is "*this", then the value declaration 7573 // is nullptr. 7574 if (EncounteredME) { 7575 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 7576 unsigned FieldIndex = FD->getFieldIndex(); 7577 7578 // Update info about the lowest and highest elements for this struct 7579 if (!PartialStruct.Base.isValid()) { 7580 PartialStruct.LowestElem = {FieldIndex, LB}; 7581 PartialStruct.HighestElem = {FieldIndex, LB}; 7582 PartialStruct.Base = BP; 7583 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7584 PartialStruct.LowestElem = {FieldIndex, LB}; 7585 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7586 PartialStruct.HighestElem = {FieldIndex, LB}; 7587 } 7588 } 7589 7590 // If we have a final array section, we are done with this expression. 7591 if (IsFinalArraySection) 7592 break; 7593 7594 // The pointer becomes the base for the next element. 7595 if (Next != CE) 7596 BP = LB; 7597 7598 IsExpressionFirstInfo = false; 7599 IsCaptureFirstInfo = false; 7600 } 7601 } 7602 } 7603 7604 /// Return the adjusted map modifiers if the declaration a capture refers to 7605 /// appears in a first-private clause. This is expected to be used only with 7606 /// directives that start with 'target'. 7607 MappableExprsHandler::OpenMPOffloadMappingFlags 7608 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7609 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7610 7611 // A first private variable captured by reference will use only the 7612 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7613 // declaration is known as first-private in this handler. 7614 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7615 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7616 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7617 return MappableExprsHandler::OMP_MAP_ALWAYS | 7618 MappableExprsHandler::OMP_MAP_TO; 7619 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7620 return MappableExprsHandler::OMP_MAP_TO | 7621 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7622 return MappableExprsHandler::OMP_MAP_PRIVATE | 7623 MappableExprsHandler::OMP_MAP_TO; 7624 } 7625 return MappableExprsHandler::OMP_MAP_TO | 7626 MappableExprsHandler::OMP_MAP_FROM; 7627 } 7628 7629 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7630 // Rotate by getFlagMemberOffset() bits. 7631 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7632 << getFlagMemberOffset()); 7633 } 7634 7635 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7636 OpenMPOffloadMappingFlags MemberOfFlag) { 7637 // If the entry is PTR_AND_OBJ but has not been marked with the special 7638 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7639 // marked as MEMBER_OF. 7640 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7641 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7642 return; 7643 7644 // Reset the placeholder value to prepare the flag for the assignment of the 7645 // proper MEMBER_OF value. 7646 Flags &= ~OMP_MAP_MEMBER_OF; 7647 Flags |= MemberOfFlag; 7648 } 7649 7650 void getPlainLayout(const CXXRecordDecl *RD, 7651 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7652 bool AsBase) const { 7653 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7654 7655 llvm::StructType *St = 7656 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7657 7658 unsigned NumElements = St->getNumElements(); 7659 llvm::SmallVector< 7660 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7661 RecordLayout(NumElements); 7662 7663 // Fill bases. 7664 for (const auto &I : RD->bases()) { 7665 if (I.isVirtual()) 7666 continue; 7667 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7668 // Ignore empty bases. 7669 if (Base->isEmpty() || CGF.getContext() 7670 .getASTRecordLayout(Base) 7671 .getNonVirtualSize() 7672 .isZero()) 7673 continue; 7674 7675 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7676 RecordLayout[FieldIndex] = Base; 7677 } 7678 // Fill in virtual bases. 7679 for (const auto &I : RD->vbases()) { 7680 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7681 // Ignore empty bases. 7682 if (Base->isEmpty()) 7683 continue; 7684 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7685 if (RecordLayout[FieldIndex]) 7686 continue; 7687 RecordLayout[FieldIndex] = Base; 7688 } 7689 // Fill in all the fields. 7690 assert(!RD->isUnion() && "Unexpected union."); 7691 for (const auto *Field : RD->fields()) { 7692 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7693 // will fill in later.) 7694 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7695 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7696 RecordLayout[FieldIndex] = Field; 7697 } 7698 } 7699 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7700 &Data : RecordLayout) { 7701 if (Data.isNull()) 7702 continue; 7703 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7704 getPlainLayout(Base, Layout, /*AsBase=*/true); 7705 else 7706 Layout.push_back(Data.get<const FieldDecl *>()); 7707 } 7708 } 7709 7710 public: 7711 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7712 : CurDir(&Dir), CGF(CGF) { 7713 // Extract firstprivate clause information. 7714 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7715 for (const auto *D : C->varlists()) 7716 FirstPrivateDecls.try_emplace( 7717 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 7718 // Extract implicit firstprivates from uses_allocators clauses. 7719 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) { 7720 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 7721 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 7722 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits)) 7723 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()), 7724 /*Implicit=*/true); 7725 else if (const auto *VD = dyn_cast<VarDecl>( 7726 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts()) 7727 ->getDecl())) 7728 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true); 7729 } 7730 } 7731 // Extract device pointer clause information. 7732 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7733 for (auto L : C->component_lists()) 7734 DevPointersMap[L.first].push_back(L.second); 7735 } 7736 7737 /// Constructor for the declare mapper directive. 7738 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 7739 : CurDir(&Dir), CGF(CGF) {} 7740 7741 /// Generate code for the combined entry if we have a partially mapped struct 7742 /// and take care of the mapping flags of the arguments corresponding to 7743 /// individual struct members. 7744 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 7745 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7746 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 7747 const StructRangeInfoTy &PartialStruct) const { 7748 // Base is the base of the struct 7749 BasePointers.push_back(PartialStruct.Base.getPointer()); 7750 // Pointer is the address of the lowest element 7751 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7752 Pointers.push_back(LB); 7753 // Size is (addr of {highest+1} element) - (addr of lowest element) 7754 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7755 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7756 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7757 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7758 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7759 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 7760 /*isSigned=*/false); 7761 Sizes.push_back(Size); 7762 // Map type is always TARGET_PARAM 7763 Types.push_back(OMP_MAP_TARGET_PARAM); 7764 // Remove TARGET_PARAM flag from the first element 7765 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7766 7767 // All other current entries will be MEMBER_OF the combined entry 7768 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7769 // 0xFFFF in the MEMBER_OF field). 7770 OpenMPOffloadMappingFlags MemberOfFlag = 7771 getMemberOfFlag(BasePointers.size() - 1); 7772 for (auto &M : CurTypes) 7773 setCorrectMemberOfFlag(M, MemberOfFlag); 7774 } 7775 7776 /// Generate all the base pointers, section pointers, sizes and map 7777 /// types for the extracted mappable expressions. Also, for each item that 7778 /// relates with a device pointer, a pair of the relevant declaration and 7779 /// index where it occurs is appended to the device pointers info array. 7780 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 7781 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7782 MapFlagsArrayTy &Types) const { 7783 // We have to process the component lists that relate with the same 7784 // declaration in a single chunk so that we can generate the map flags 7785 // correctly. Therefore, we organize all lists in a map. 7786 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7787 7788 // Helper function to fill the information map for the different supported 7789 // clauses. 7790 auto &&InfoGen = [&Info]( 7791 const ValueDecl *D, 7792 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7793 OpenMPMapClauseKind MapType, 7794 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7795 bool ReturnDevicePointer, bool IsImplicit) { 7796 const ValueDecl *VD = 7797 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7798 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7799 IsImplicit); 7800 }; 7801 7802 assert(CurDir.is<const OMPExecutableDirective *>() && 7803 "Expect a executable directive"); 7804 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 7805 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 7806 for (const auto L : C->component_lists()) { 7807 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 7808 /*ReturnDevicePointer=*/false, C->isImplicit()); 7809 } 7810 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 7811 for (const auto L : C->component_lists()) { 7812 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 7813 /*ReturnDevicePointer=*/false, C->isImplicit()); 7814 } 7815 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 7816 for (const auto L : C->component_lists()) { 7817 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 7818 /*ReturnDevicePointer=*/false, C->isImplicit()); 7819 } 7820 7821 // Look at the use_device_ptr clause information and mark the existing map 7822 // entries as such. If there is no map information for an entry in the 7823 // use_device_ptr list, we create one with map type 'alloc' and zero size 7824 // section. It is the user fault if that was not mapped before. If there is 7825 // no map information and the pointer is a struct member, then we defer the 7826 // emission of that entry until the whole struct has been processed. 7827 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 7828 DeferredInfo; 7829 7830 for (const auto *C : 7831 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 7832 for (const auto L : C->component_lists()) { 7833 assert(!L.second.empty() && "Not expecting empty list of components!"); 7834 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 7835 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 7836 const Expr *IE = L.second.back().getAssociatedExpression(); 7837 // If the first component is a member expression, we have to look into 7838 // 'this', which maps to null in the map of map information. Otherwise 7839 // look directly for the information. 7840 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 7841 7842 // We potentially have map information for this declaration already. 7843 // Look for the first set of components that refer to it. 7844 if (It != Info.end()) { 7845 auto CI = std::find_if( 7846 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 7847 return MI.Components.back().getAssociatedDeclaration() == VD; 7848 }); 7849 // If we found a map entry, signal that the pointer has to be returned 7850 // and move on to the next declaration. 7851 if (CI != It->second.end()) { 7852 CI->ReturnDevicePointer = true; 7853 continue; 7854 } 7855 } 7856 7857 // We didn't find any match in our map information - generate a zero 7858 // size array section - if the pointer is a struct member we defer this 7859 // action until the whole struct has been processed. 7860 if (isa<MemberExpr>(IE)) { 7861 // Insert the pointer into Info to be processed by 7862 // generateInfoForComponentList. Because it is a member pointer 7863 // without a pointee, no entry will be generated for it, therefore 7864 // we need to generate one after the whole struct has been processed. 7865 // Nonetheless, generateInfoForComponentList must be called to take 7866 // the pointer into account for the calculation of the range of the 7867 // partial struct. 7868 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 7869 /*ReturnDevicePointer=*/false, C->isImplicit()); 7870 DeferredInfo[nullptr].emplace_back(IE, VD); 7871 } else { 7872 llvm::Value *Ptr = 7873 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 7874 BasePointers.emplace_back(Ptr, VD); 7875 Pointers.push_back(Ptr); 7876 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 7877 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 7878 } 7879 } 7880 } 7881 7882 for (const auto &M : Info) { 7883 // We need to know when we generate information for the first component 7884 // associated with a capture, because the mapping flags depend on it. 7885 bool IsFirstComponentList = true; 7886 7887 // Temporary versions of arrays 7888 MapBaseValuesArrayTy CurBasePointers; 7889 MapValuesArrayTy CurPointers; 7890 MapValuesArrayTy CurSizes; 7891 MapFlagsArrayTy CurTypes; 7892 StructRangeInfoTy PartialStruct; 7893 7894 for (const MapInfo &L : M.second) { 7895 assert(!L.Components.empty() && 7896 "Not expecting declaration with no component lists."); 7897 7898 // Remember the current base pointer index. 7899 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 7900 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 7901 CurBasePointers, CurPointers, CurSizes, 7902 CurTypes, PartialStruct, 7903 IsFirstComponentList, L.IsImplicit); 7904 7905 // If this entry relates with a device pointer, set the relevant 7906 // declaration and add the 'return pointer' flag. 7907 if (L.ReturnDevicePointer) { 7908 assert(CurBasePointers.size() > CurrentBasePointersIdx && 7909 "Unexpected number of mapped base pointers."); 7910 7911 const ValueDecl *RelevantVD = 7912 L.Components.back().getAssociatedDeclaration(); 7913 assert(RelevantVD && 7914 "No relevant declaration related with device pointer??"); 7915 7916 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 7917 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 7918 } 7919 IsFirstComponentList = false; 7920 } 7921 7922 // Append any pending zero-length pointers which are struct members and 7923 // used with use_device_ptr. 7924 auto CI = DeferredInfo.find(M.first); 7925 if (CI != DeferredInfo.end()) { 7926 for (const DeferredDevicePtrEntryTy &L : CI->second) { 7927 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 7928 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 7929 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 7930 CurBasePointers.emplace_back(BasePtr, L.VD); 7931 CurPointers.push_back(Ptr); 7932 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 7933 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 7934 // value MEMBER_OF=FFFF so that the entry is later updated with the 7935 // correct value of MEMBER_OF. 7936 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 7937 OMP_MAP_MEMBER_OF); 7938 } 7939 } 7940 7941 // If there is an entry in PartialStruct it means we have a struct with 7942 // individual members mapped. Emit an extra combined entry. 7943 if (PartialStruct.Base.isValid()) 7944 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 7945 PartialStruct); 7946 7947 // We need to append the results of this capture to what we already have. 7948 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 7949 Pointers.append(CurPointers.begin(), CurPointers.end()); 7950 Sizes.append(CurSizes.begin(), CurSizes.end()); 7951 Types.append(CurTypes.begin(), CurTypes.end()); 7952 } 7953 } 7954 7955 /// Generate all the base pointers, section pointers, sizes and map types for 7956 /// the extracted map clauses of user-defined mapper. 7957 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 7958 MapValuesArrayTy &Pointers, 7959 MapValuesArrayTy &Sizes, 7960 MapFlagsArrayTy &Types) const { 7961 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 7962 "Expect a declare mapper directive"); 7963 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 7964 // We have to process the component lists that relate with the same 7965 // declaration in a single chunk so that we can generate the map flags 7966 // correctly. Therefore, we organize all lists in a map. 7967 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7968 7969 // Helper function to fill the information map for the different supported 7970 // clauses. 7971 auto &&InfoGen = [&Info]( 7972 const ValueDecl *D, 7973 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7974 OpenMPMapClauseKind MapType, 7975 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7976 bool ReturnDevicePointer, bool IsImplicit) { 7977 const ValueDecl *VD = 7978 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7979 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7980 IsImplicit); 7981 }; 7982 7983 for (const auto *C : CurMapperDir->clauselists()) { 7984 const auto *MC = cast<OMPMapClause>(C); 7985 for (const auto L : MC->component_lists()) { 7986 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 7987 /*ReturnDevicePointer=*/false, MC->isImplicit()); 7988 } 7989 } 7990 7991 for (const auto &M : Info) { 7992 // We need to know when we generate information for the first component 7993 // associated with a capture, because the mapping flags depend on it. 7994 bool IsFirstComponentList = true; 7995 7996 // Temporary versions of arrays 7997 MapBaseValuesArrayTy CurBasePointers; 7998 MapValuesArrayTy CurPointers; 7999 MapValuesArrayTy CurSizes; 8000 MapFlagsArrayTy CurTypes; 8001 StructRangeInfoTy PartialStruct; 8002 8003 for (const MapInfo &L : M.second) { 8004 assert(!L.Components.empty() && 8005 "Not expecting declaration with no component lists."); 8006 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8007 CurBasePointers, CurPointers, CurSizes, 8008 CurTypes, PartialStruct, 8009 IsFirstComponentList, L.IsImplicit); 8010 IsFirstComponentList = false; 8011 } 8012 8013 // If there is an entry in PartialStruct it means we have a struct with 8014 // individual members mapped. Emit an extra combined entry. 8015 if (PartialStruct.Base.isValid()) 8016 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8017 PartialStruct); 8018 8019 // We need to append the results of this capture to what we already have. 8020 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8021 Pointers.append(CurPointers.begin(), CurPointers.end()); 8022 Sizes.append(CurSizes.begin(), CurSizes.end()); 8023 Types.append(CurTypes.begin(), CurTypes.end()); 8024 } 8025 } 8026 8027 /// Emit capture info for lambdas for variables captured by reference. 8028 void generateInfoForLambdaCaptures( 8029 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8030 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8031 MapFlagsArrayTy &Types, 8032 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8033 const auto *RD = VD->getType() 8034 .getCanonicalType() 8035 .getNonReferenceType() 8036 ->getAsCXXRecordDecl(); 8037 if (!RD || !RD->isLambda()) 8038 return; 8039 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8040 LValue VDLVal = CGF.MakeAddrLValue( 8041 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8042 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8043 FieldDecl *ThisCapture = nullptr; 8044 RD->getCaptureFields(Captures, ThisCapture); 8045 if (ThisCapture) { 8046 LValue ThisLVal = 8047 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8048 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8049 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8050 VDLVal.getPointer(CGF)); 8051 BasePointers.push_back(ThisLVal.getPointer(CGF)); 8052 Pointers.push_back(ThisLValVal.getPointer(CGF)); 8053 Sizes.push_back( 8054 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8055 CGF.Int64Ty, /*isSigned=*/true)); 8056 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8057 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8058 } 8059 for (const LambdaCapture &LC : RD->captures()) { 8060 if (!LC.capturesVariable()) 8061 continue; 8062 const VarDecl *VD = LC.getCapturedVar(); 8063 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8064 continue; 8065 auto It = Captures.find(VD); 8066 assert(It != Captures.end() && "Found lambda capture without field."); 8067 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8068 if (LC.getCaptureKind() == LCK_ByRef) { 8069 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8070 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8071 VDLVal.getPointer(CGF)); 8072 BasePointers.push_back(VarLVal.getPointer(CGF)); 8073 Pointers.push_back(VarLValVal.getPointer(CGF)); 8074 Sizes.push_back(CGF.Builder.CreateIntCast( 8075 CGF.getTypeSize( 8076 VD->getType().getCanonicalType().getNonReferenceType()), 8077 CGF.Int64Ty, /*isSigned=*/true)); 8078 } else { 8079 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8080 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8081 VDLVal.getPointer(CGF)); 8082 BasePointers.push_back(VarLVal.getPointer(CGF)); 8083 Pointers.push_back(VarRVal.getScalarVal()); 8084 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8085 } 8086 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8087 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8088 } 8089 } 8090 8091 /// Set correct indices for lambdas captures. 8092 void adjustMemberOfForLambdaCaptures( 8093 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8094 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8095 MapFlagsArrayTy &Types) const { 8096 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8097 // Set correct member_of idx for all implicit lambda captures. 8098 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8099 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8100 continue; 8101 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8102 assert(BasePtr && "Unable to find base lambda address."); 8103 int TgtIdx = -1; 8104 for (unsigned J = I; J > 0; --J) { 8105 unsigned Idx = J - 1; 8106 if (Pointers[Idx] != BasePtr) 8107 continue; 8108 TgtIdx = Idx; 8109 break; 8110 } 8111 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8112 // All other current entries will be MEMBER_OF the combined entry 8113 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8114 // 0xFFFF in the MEMBER_OF field). 8115 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8116 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8117 } 8118 } 8119 8120 /// Generate the base pointers, section pointers, sizes and map types 8121 /// associated to a given capture. 8122 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8123 llvm::Value *Arg, 8124 MapBaseValuesArrayTy &BasePointers, 8125 MapValuesArrayTy &Pointers, 8126 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8127 StructRangeInfoTy &PartialStruct) const { 8128 assert(!Cap->capturesVariableArrayType() && 8129 "Not expecting to generate map info for a variable array type!"); 8130 8131 // We need to know when we generating information for the first component 8132 const ValueDecl *VD = Cap->capturesThis() 8133 ? nullptr 8134 : Cap->getCapturedVar()->getCanonicalDecl(); 8135 8136 // If this declaration appears in a is_device_ptr clause we just have to 8137 // pass the pointer by value. If it is a reference to a declaration, we just 8138 // pass its value. 8139 if (DevPointersMap.count(VD)) { 8140 BasePointers.emplace_back(Arg, VD); 8141 Pointers.push_back(Arg); 8142 Sizes.push_back( 8143 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8144 CGF.Int64Ty, /*isSigned=*/true)); 8145 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8146 return; 8147 } 8148 8149 using MapData = 8150 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8151 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8152 SmallVector<MapData, 4> DeclComponentLists; 8153 assert(CurDir.is<const OMPExecutableDirective *>() && 8154 "Expect a executable directive"); 8155 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8156 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8157 for (const auto L : C->decl_component_lists(VD)) { 8158 assert(L.first == VD && 8159 "We got information for the wrong declaration??"); 8160 assert(!L.second.empty() && 8161 "Not expecting declaration with no component lists."); 8162 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8163 C->getMapTypeModifiers(), 8164 C->isImplicit()); 8165 } 8166 } 8167 8168 // Find overlapping elements (including the offset from the base element). 8169 llvm::SmallDenseMap< 8170 const MapData *, 8171 llvm::SmallVector< 8172 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8173 4> 8174 OverlappedData; 8175 size_t Count = 0; 8176 for (const MapData &L : DeclComponentLists) { 8177 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8178 OpenMPMapClauseKind MapType; 8179 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8180 bool IsImplicit; 8181 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8182 ++Count; 8183 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8184 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8185 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8186 auto CI = Components.rbegin(); 8187 auto CE = Components.rend(); 8188 auto SI = Components1.rbegin(); 8189 auto SE = Components1.rend(); 8190 for (; CI != CE && SI != SE; ++CI, ++SI) { 8191 if (CI->getAssociatedExpression()->getStmtClass() != 8192 SI->getAssociatedExpression()->getStmtClass()) 8193 break; 8194 // Are we dealing with different variables/fields? 8195 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8196 break; 8197 } 8198 // Found overlapping if, at least for one component, reached the head of 8199 // the components list. 8200 if (CI == CE || SI == SE) { 8201 assert((CI != CE || SI != SE) && 8202 "Unexpected full match of the mapping components."); 8203 const MapData &BaseData = CI == CE ? L : L1; 8204 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8205 SI == SE ? Components : Components1; 8206 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8207 OverlappedElements.getSecond().push_back(SubData); 8208 } 8209 } 8210 } 8211 // Sort the overlapped elements for each item. 8212 llvm::SmallVector<const FieldDecl *, 4> Layout; 8213 if (!OverlappedData.empty()) { 8214 if (const auto *CRD = 8215 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8216 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8217 else { 8218 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8219 Layout.append(RD->field_begin(), RD->field_end()); 8220 } 8221 } 8222 for (auto &Pair : OverlappedData) { 8223 llvm::sort( 8224 Pair.getSecond(), 8225 [&Layout]( 8226 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8227 OMPClauseMappableExprCommon::MappableExprComponentListRef 8228 Second) { 8229 auto CI = First.rbegin(); 8230 auto CE = First.rend(); 8231 auto SI = Second.rbegin(); 8232 auto SE = Second.rend(); 8233 for (; CI != CE && SI != SE; ++CI, ++SI) { 8234 if (CI->getAssociatedExpression()->getStmtClass() != 8235 SI->getAssociatedExpression()->getStmtClass()) 8236 break; 8237 // Are we dealing with different variables/fields? 8238 if (CI->getAssociatedDeclaration() != 8239 SI->getAssociatedDeclaration()) 8240 break; 8241 } 8242 8243 // Lists contain the same elements. 8244 if (CI == CE && SI == SE) 8245 return false; 8246 8247 // List with less elements is less than list with more elements. 8248 if (CI == CE || SI == SE) 8249 return CI == CE; 8250 8251 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8252 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8253 if (FD1->getParent() == FD2->getParent()) 8254 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8255 const auto It = 8256 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8257 return FD == FD1 || FD == FD2; 8258 }); 8259 return *It == FD1; 8260 }); 8261 } 8262 8263 // Associated with a capture, because the mapping flags depend on it. 8264 // Go through all of the elements with the overlapped elements. 8265 for (const auto &Pair : OverlappedData) { 8266 const MapData &L = *Pair.getFirst(); 8267 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8268 OpenMPMapClauseKind MapType; 8269 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8270 bool IsImplicit; 8271 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8272 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8273 OverlappedComponents = Pair.getSecond(); 8274 bool IsFirstComponentList = true; 8275 generateInfoForComponentList(MapType, MapModifiers, Components, 8276 BasePointers, Pointers, Sizes, Types, 8277 PartialStruct, IsFirstComponentList, 8278 IsImplicit, OverlappedComponents); 8279 } 8280 // Go through other elements without overlapped elements. 8281 bool IsFirstComponentList = OverlappedData.empty(); 8282 for (const MapData &L : DeclComponentLists) { 8283 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8284 OpenMPMapClauseKind MapType; 8285 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8286 bool IsImplicit; 8287 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8288 auto It = OverlappedData.find(&L); 8289 if (It == OverlappedData.end()) 8290 generateInfoForComponentList(MapType, MapModifiers, Components, 8291 BasePointers, Pointers, Sizes, Types, 8292 PartialStruct, IsFirstComponentList, 8293 IsImplicit); 8294 IsFirstComponentList = false; 8295 } 8296 } 8297 8298 /// Generate the base pointers, section pointers, sizes and map types 8299 /// associated with the declare target link variables. 8300 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8301 MapValuesArrayTy &Pointers, 8302 MapValuesArrayTy &Sizes, 8303 MapFlagsArrayTy &Types) const { 8304 assert(CurDir.is<const OMPExecutableDirective *>() && 8305 "Expect a executable directive"); 8306 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8307 // Map other list items in the map clause which are not captured variables 8308 // but "declare target link" global variables. 8309 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8310 for (const auto L : C->component_lists()) { 8311 if (!L.first) 8312 continue; 8313 const auto *VD = dyn_cast<VarDecl>(L.first); 8314 if (!VD) 8315 continue; 8316 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8317 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8318 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8319 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8320 continue; 8321 StructRangeInfoTy PartialStruct; 8322 generateInfoForComponentList( 8323 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8324 Pointers, Sizes, Types, PartialStruct, 8325 /*IsFirstComponentList=*/true, C->isImplicit()); 8326 assert(!PartialStruct.Base.isValid() && 8327 "No partial structs for declare target link expected."); 8328 } 8329 } 8330 } 8331 8332 /// Generate the default map information for a given capture \a CI, 8333 /// record field declaration \a RI and captured value \a CV. 8334 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8335 const FieldDecl &RI, llvm::Value *CV, 8336 MapBaseValuesArrayTy &CurBasePointers, 8337 MapValuesArrayTy &CurPointers, 8338 MapValuesArrayTy &CurSizes, 8339 MapFlagsArrayTy &CurMapTypes) const { 8340 bool IsImplicit = true; 8341 // Do the default mapping. 8342 if (CI.capturesThis()) { 8343 CurBasePointers.push_back(CV); 8344 CurPointers.push_back(CV); 8345 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8346 CurSizes.push_back( 8347 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8348 CGF.Int64Ty, /*isSigned=*/true)); 8349 // Default map type. 8350 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8351 } else if (CI.capturesVariableByCopy()) { 8352 CurBasePointers.push_back(CV); 8353 CurPointers.push_back(CV); 8354 if (!RI.getType()->isAnyPointerType()) { 8355 // We have to signal to the runtime captures passed by value that are 8356 // not pointers. 8357 CurMapTypes.push_back(OMP_MAP_LITERAL); 8358 CurSizes.push_back(CGF.Builder.CreateIntCast( 8359 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8360 } else { 8361 // Pointers are implicitly mapped with a zero size and no flags 8362 // (other than first map that is added for all implicit maps). 8363 CurMapTypes.push_back(OMP_MAP_NONE); 8364 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8365 } 8366 const VarDecl *VD = CI.getCapturedVar(); 8367 auto I = FirstPrivateDecls.find(VD); 8368 if (I != FirstPrivateDecls.end()) 8369 IsImplicit = I->getSecond(); 8370 } else { 8371 assert(CI.capturesVariable() && "Expected captured reference."); 8372 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8373 QualType ElementType = PtrTy->getPointeeType(); 8374 CurSizes.push_back(CGF.Builder.CreateIntCast( 8375 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8376 // The default map type for a scalar/complex type is 'to' because by 8377 // default the value doesn't have to be retrieved. For an aggregate 8378 // type, the default is 'tofrom'. 8379 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8380 const VarDecl *VD = CI.getCapturedVar(); 8381 auto I = FirstPrivateDecls.find(VD); 8382 if (I != FirstPrivateDecls.end() && 8383 VD->getType().isConstant(CGF.getContext())) { 8384 llvm::Constant *Addr = 8385 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8386 // Copy the value of the original variable to the new global copy. 8387 CGF.Builder.CreateMemCpy( 8388 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 8389 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8390 CurSizes.back(), /*IsVolatile=*/false); 8391 // Use new global variable as the base pointers. 8392 CurBasePointers.push_back(Addr); 8393 CurPointers.push_back(Addr); 8394 } else { 8395 CurBasePointers.push_back(CV); 8396 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8397 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8398 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8399 AlignmentSource::Decl)); 8400 CurPointers.push_back(PtrAddr.getPointer()); 8401 } else { 8402 CurPointers.push_back(CV); 8403 } 8404 } 8405 if (I != FirstPrivateDecls.end()) 8406 IsImplicit = I->getSecond(); 8407 } 8408 // Every default map produces a single argument which is a target parameter. 8409 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8410 8411 // Add flag stating this is an implicit map. 8412 if (IsImplicit) 8413 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8414 } 8415 }; 8416 } // anonymous namespace 8417 8418 /// Emit the arrays used to pass the captures and map information to the 8419 /// offloading runtime library. If there is no map or capture information, 8420 /// return nullptr by reference. 8421 static void 8422 emitOffloadingArrays(CodeGenFunction &CGF, 8423 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8424 MappableExprsHandler::MapValuesArrayTy &Pointers, 8425 MappableExprsHandler::MapValuesArrayTy &Sizes, 8426 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8427 CGOpenMPRuntime::TargetDataInfo &Info) { 8428 CodeGenModule &CGM = CGF.CGM; 8429 ASTContext &Ctx = CGF.getContext(); 8430 8431 // Reset the array information. 8432 Info.clearArrayInfo(); 8433 Info.NumberOfPtrs = BasePointers.size(); 8434 8435 if (Info.NumberOfPtrs) { 8436 // Detect if we have any capture size requiring runtime evaluation of the 8437 // size so that a constant array could be eventually used. 8438 bool hasRuntimeEvaluationCaptureSize = false; 8439 for (llvm::Value *S : Sizes) 8440 if (!isa<llvm::Constant>(S)) { 8441 hasRuntimeEvaluationCaptureSize = true; 8442 break; 8443 } 8444 8445 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8446 QualType PointerArrayType = Ctx.getConstantArrayType( 8447 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8448 /*IndexTypeQuals=*/0); 8449 8450 Info.BasePointersArray = 8451 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8452 Info.PointersArray = 8453 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8454 8455 // If we don't have any VLA types or other types that require runtime 8456 // evaluation, we can use a constant array for the map sizes, otherwise we 8457 // need to fill up the arrays as we do for the pointers. 8458 QualType Int64Ty = 8459 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8460 if (hasRuntimeEvaluationCaptureSize) { 8461 QualType SizeArrayType = Ctx.getConstantArrayType( 8462 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8463 /*IndexTypeQuals=*/0); 8464 Info.SizesArray = 8465 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8466 } else { 8467 // We expect all the sizes to be constant, so we collect them to create 8468 // a constant array. 8469 SmallVector<llvm::Constant *, 16> ConstSizes; 8470 for (llvm::Value *S : Sizes) 8471 ConstSizes.push_back(cast<llvm::Constant>(S)); 8472 8473 auto *SizesArrayInit = llvm::ConstantArray::get( 8474 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8475 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8476 auto *SizesArrayGbl = new llvm::GlobalVariable( 8477 CGM.getModule(), SizesArrayInit->getType(), 8478 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8479 SizesArrayInit, Name); 8480 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8481 Info.SizesArray = SizesArrayGbl; 8482 } 8483 8484 // The map types are always constant so we don't need to generate code to 8485 // fill arrays. Instead, we create an array constant. 8486 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8487 llvm::copy(MapTypes, Mapping.begin()); 8488 llvm::Constant *MapTypesArrayInit = 8489 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8490 std::string MaptypesName = 8491 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8492 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8493 CGM.getModule(), MapTypesArrayInit->getType(), 8494 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8495 MapTypesArrayInit, MaptypesName); 8496 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8497 Info.MapTypesArray = MapTypesArrayGbl; 8498 8499 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8500 llvm::Value *BPVal = *BasePointers[I]; 8501 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8502 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8503 Info.BasePointersArray, 0, I); 8504 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8505 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8506 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8507 CGF.Builder.CreateStore(BPVal, BPAddr); 8508 8509 if (Info.requiresDevicePointerInfo()) 8510 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8511 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8512 8513 llvm::Value *PVal = Pointers[I]; 8514 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8515 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8516 Info.PointersArray, 0, I); 8517 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8518 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8519 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8520 CGF.Builder.CreateStore(PVal, PAddr); 8521 8522 if (hasRuntimeEvaluationCaptureSize) { 8523 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8524 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8525 Info.SizesArray, 8526 /*Idx0=*/0, 8527 /*Idx1=*/I); 8528 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8529 CGF.Builder.CreateStore( 8530 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8531 SAddr); 8532 } 8533 } 8534 } 8535 } 8536 8537 /// Emit the arguments to be passed to the runtime library based on the 8538 /// arrays of pointers, sizes and map types. 8539 static void emitOffloadingArraysArgument( 8540 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8541 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8542 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8543 CodeGenModule &CGM = CGF.CGM; 8544 if (Info.NumberOfPtrs) { 8545 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8546 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8547 Info.BasePointersArray, 8548 /*Idx0=*/0, /*Idx1=*/0); 8549 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8550 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8551 Info.PointersArray, 8552 /*Idx0=*/0, 8553 /*Idx1=*/0); 8554 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8555 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8556 /*Idx0=*/0, /*Idx1=*/0); 8557 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8558 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8559 Info.MapTypesArray, 8560 /*Idx0=*/0, 8561 /*Idx1=*/0); 8562 } else { 8563 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8564 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8565 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8566 MapTypesArrayArg = 8567 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8568 } 8569 } 8570 8571 /// Check for inner distribute directive. 8572 static const OMPExecutableDirective * 8573 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8574 const auto *CS = D.getInnermostCapturedStmt(); 8575 const auto *Body = 8576 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8577 const Stmt *ChildStmt = 8578 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8579 8580 if (const auto *NestedDir = 8581 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8582 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8583 switch (D.getDirectiveKind()) { 8584 case OMPD_target: 8585 if (isOpenMPDistributeDirective(DKind)) 8586 return NestedDir; 8587 if (DKind == OMPD_teams) { 8588 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8589 /*IgnoreCaptured=*/true); 8590 if (!Body) 8591 return nullptr; 8592 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8593 if (const auto *NND = 8594 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8595 DKind = NND->getDirectiveKind(); 8596 if (isOpenMPDistributeDirective(DKind)) 8597 return NND; 8598 } 8599 } 8600 return nullptr; 8601 case OMPD_target_teams: 8602 if (isOpenMPDistributeDirective(DKind)) 8603 return NestedDir; 8604 return nullptr; 8605 case OMPD_target_parallel: 8606 case OMPD_target_simd: 8607 case OMPD_target_parallel_for: 8608 case OMPD_target_parallel_for_simd: 8609 return nullptr; 8610 case OMPD_target_teams_distribute: 8611 case OMPD_target_teams_distribute_simd: 8612 case OMPD_target_teams_distribute_parallel_for: 8613 case OMPD_target_teams_distribute_parallel_for_simd: 8614 case OMPD_parallel: 8615 case OMPD_for: 8616 case OMPD_parallel_for: 8617 case OMPD_parallel_master: 8618 case OMPD_parallel_sections: 8619 case OMPD_for_simd: 8620 case OMPD_parallel_for_simd: 8621 case OMPD_cancel: 8622 case OMPD_cancellation_point: 8623 case OMPD_ordered: 8624 case OMPD_threadprivate: 8625 case OMPD_allocate: 8626 case OMPD_task: 8627 case OMPD_simd: 8628 case OMPD_sections: 8629 case OMPD_section: 8630 case OMPD_single: 8631 case OMPD_master: 8632 case OMPD_critical: 8633 case OMPD_taskyield: 8634 case OMPD_barrier: 8635 case OMPD_taskwait: 8636 case OMPD_taskgroup: 8637 case OMPD_atomic: 8638 case OMPD_flush: 8639 case OMPD_depobj: 8640 case OMPD_scan: 8641 case OMPD_teams: 8642 case OMPD_target_data: 8643 case OMPD_target_exit_data: 8644 case OMPD_target_enter_data: 8645 case OMPD_distribute: 8646 case OMPD_distribute_simd: 8647 case OMPD_distribute_parallel_for: 8648 case OMPD_distribute_parallel_for_simd: 8649 case OMPD_teams_distribute: 8650 case OMPD_teams_distribute_simd: 8651 case OMPD_teams_distribute_parallel_for: 8652 case OMPD_teams_distribute_parallel_for_simd: 8653 case OMPD_target_update: 8654 case OMPD_declare_simd: 8655 case OMPD_declare_variant: 8656 case OMPD_begin_declare_variant: 8657 case OMPD_end_declare_variant: 8658 case OMPD_declare_target: 8659 case OMPD_end_declare_target: 8660 case OMPD_declare_reduction: 8661 case OMPD_declare_mapper: 8662 case OMPD_taskloop: 8663 case OMPD_taskloop_simd: 8664 case OMPD_master_taskloop: 8665 case OMPD_master_taskloop_simd: 8666 case OMPD_parallel_master_taskloop: 8667 case OMPD_parallel_master_taskloop_simd: 8668 case OMPD_requires: 8669 case OMPD_unknown: 8670 llvm_unreachable("Unexpected directive."); 8671 } 8672 } 8673 8674 return nullptr; 8675 } 8676 8677 /// Emit the user-defined mapper function. The code generation follows the 8678 /// pattern in the example below. 8679 /// \code 8680 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8681 /// void *base, void *begin, 8682 /// int64_t size, int64_t type) { 8683 /// // Allocate space for an array section first. 8684 /// if (size > 1 && !maptype.IsDelete) 8685 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8686 /// size*sizeof(Ty), clearToFrom(type)); 8687 /// // Map members. 8688 /// for (unsigned i = 0; i < size; i++) { 8689 /// // For each component specified by this mapper: 8690 /// for (auto c : all_components) { 8691 /// if (c.hasMapper()) 8692 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8693 /// c.arg_type); 8694 /// else 8695 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8696 /// c.arg_begin, c.arg_size, c.arg_type); 8697 /// } 8698 /// } 8699 /// // Delete the array section. 8700 /// if (size > 1 && maptype.IsDelete) 8701 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8702 /// size*sizeof(Ty), clearToFrom(type)); 8703 /// } 8704 /// \endcode 8705 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8706 CodeGenFunction *CGF) { 8707 if (UDMMap.count(D) > 0) 8708 return; 8709 ASTContext &C = CGM.getContext(); 8710 QualType Ty = D->getType(); 8711 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8712 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8713 auto *MapperVarDecl = 8714 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8715 SourceLocation Loc = D->getLocation(); 8716 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8717 8718 // Prepare mapper function arguments and attributes. 8719 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8720 C.VoidPtrTy, ImplicitParamDecl::Other); 8721 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8722 ImplicitParamDecl::Other); 8723 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8724 C.VoidPtrTy, ImplicitParamDecl::Other); 8725 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8726 ImplicitParamDecl::Other); 8727 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8728 ImplicitParamDecl::Other); 8729 FunctionArgList Args; 8730 Args.push_back(&HandleArg); 8731 Args.push_back(&BaseArg); 8732 Args.push_back(&BeginArg); 8733 Args.push_back(&SizeArg); 8734 Args.push_back(&TypeArg); 8735 const CGFunctionInfo &FnInfo = 8736 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8737 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8738 SmallString<64> TyStr; 8739 llvm::raw_svector_ostream Out(TyStr); 8740 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 8741 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 8742 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 8743 Name, &CGM.getModule()); 8744 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 8745 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 8746 // Start the mapper function code generation. 8747 CodeGenFunction MapperCGF(CGM); 8748 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 8749 // Compute the starting and end addreses of array elements. 8750 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 8751 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 8752 C.getPointerType(Int64Ty), Loc); 8753 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 8754 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 8755 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 8756 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 8757 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 8758 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 8759 C.getPointerType(Int64Ty), Loc); 8760 // Prepare common arguments for array initiation and deletion. 8761 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 8762 MapperCGF.GetAddrOfLocalVar(&HandleArg), 8763 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8764 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 8765 MapperCGF.GetAddrOfLocalVar(&BaseArg), 8766 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8767 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 8768 MapperCGF.GetAddrOfLocalVar(&BeginArg), 8769 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8770 8771 // Emit array initiation if this is an array section and \p MapType indicates 8772 // that memory allocation is required. 8773 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 8774 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8775 ElementSize, HeadBB, /*IsInit=*/true); 8776 8777 // Emit a for loop to iterate through SizeArg of elements and map all of them. 8778 8779 // Emit the loop header block. 8780 MapperCGF.EmitBlock(HeadBB); 8781 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 8782 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 8783 // Evaluate whether the initial condition is satisfied. 8784 llvm::Value *IsEmpty = 8785 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 8786 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 8787 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 8788 8789 // Emit the loop body block. 8790 MapperCGF.EmitBlock(BodyBB); 8791 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 8792 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 8793 PtrPHI->addIncoming(PtrBegin, EntryBB); 8794 Address PtrCurrent = 8795 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 8796 .getAlignment() 8797 .alignmentOfArrayElement(ElementSize)); 8798 // Privatize the declared variable of mapper to be the current array element. 8799 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 8800 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 8801 return MapperCGF 8802 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 8803 .getAddress(MapperCGF); 8804 }); 8805 (void)Scope.Privatize(); 8806 8807 // Get map clause information. Fill up the arrays with all mapped variables. 8808 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 8809 MappableExprsHandler::MapValuesArrayTy Pointers; 8810 MappableExprsHandler::MapValuesArrayTy Sizes; 8811 MappableExprsHandler::MapFlagsArrayTy MapTypes; 8812 MappableExprsHandler MEHandler(*D, MapperCGF); 8813 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 8814 8815 // Call the runtime API __tgt_mapper_num_components to get the number of 8816 // pre-existing components. 8817 llvm::Value *OffloadingArgs[] = {Handle}; 8818 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 8819 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 8820 CGM.getModule(), OMPRTL___tgt_mapper_num_components), 8821 OffloadingArgs); 8822 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 8823 PreviousSize, 8824 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 8825 8826 // Fill up the runtime mapper handle for all components. 8827 for (unsigned I = 0; I < BasePointers.size(); ++I) { 8828 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 8829 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8830 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 8831 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8832 llvm::Value *CurSizeArg = Sizes[I]; 8833 8834 // Extract the MEMBER_OF field from the map type. 8835 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 8836 MapperCGF.EmitBlock(MemberBB); 8837 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 8838 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 8839 OriMapType, 8840 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 8841 llvm::BasicBlock *MemberCombineBB = 8842 MapperCGF.createBasicBlock("omp.member.combine"); 8843 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 8844 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 8845 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 8846 // Add the number of pre-existing components to the MEMBER_OF field if it 8847 // is valid. 8848 MapperCGF.EmitBlock(MemberCombineBB); 8849 llvm::Value *CombinedMember = 8850 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 8851 // Do nothing if it is not a member of previous components. 8852 MapperCGF.EmitBlock(TypeBB); 8853 llvm::PHINode *MemberMapType = 8854 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 8855 MemberMapType->addIncoming(OriMapType, MemberBB); 8856 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 8857 8858 // Combine the map type inherited from user-defined mapper with that 8859 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 8860 // bits of the \a MapType, which is the input argument of the mapper 8861 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 8862 // bits of MemberMapType. 8863 // [OpenMP 5.0], 1.2.6. map-type decay. 8864 // | alloc | to | from | tofrom | release | delete 8865 // ---------------------------------------------------------- 8866 // alloc | alloc | alloc | alloc | alloc | release | delete 8867 // to | alloc | to | alloc | to | release | delete 8868 // from | alloc | alloc | from | from | release | delete 8869 // tofrom | alloc | to | from | tofrom | release | delete 8870 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 8871 MapType, 8872 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 8873 MappableExprsHandler::OMP_MAP_FROM)); 8874 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 8875 llvm::BasicBlock *AllocElseBB = 8876 MapperCGF.createBasicBlock("omp.type.alloc.else"); 8877 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 8878 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 8879 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 8880 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 8881 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 8882 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 8883 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 8884 MapperCGF.EmitBlock(AllocBB); 8885 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 8886 MemberMapType, 8887 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 8888 MappableExprsHandler::OMP_MAP_FROM))); 8889 MapperCGF.Builder.CreateBr(EndBB); 8890 MapperCGF.EmitBlock(AllocElseBB); 8891 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 8892 LeftToFrom, 8893 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 8894 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 8895 // In case of to, clear OMP_MAP_FROM. 8896 MapperCGF.EmitBlock(ToBB); 8897 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 8898 MemberMapType, 8899 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 8900 MapperCGF.Builder.CreateBr(EndBB); 8901 MapperCGF.EmitBlock(ToElseBB); 8902 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 8903 LeftToFrom, 8904 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 8905 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 8906 // In case of from, clear OMP_MAP_TO. 8907 MapperCGF.EmitBlock(FromBB); 8908 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 8909 MemberMapType, 8910 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 8911 // In case of tofrom, do nothing. 8912 MapperCGF.EmitBlock(EndBB); 8913 llvm::PHINode *CurMapType = 8914 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 8915 CurMapType->addIncoming(AllocMapType, AllocBB); 8916 CurMapType->addIncoming(ToMapType, ToBB); 8917 CurMapType->addIncoming(FromMapType, FromBB); 8918 CurMapType->addIncoming(MemberMapType, ToElseBB); 8919 8920 // TODO: call the corresponding mapper function if a user-defined mapper is 8921 // associated with this map clause. 8922 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 8923 // data structure. 8924 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 8925 CurSizeArg, CurMapType}; 8926 MapperCGF.EmitRuntimeCall( 8927 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 8928 CGM.getModule(), OMPRTL___tgt_push_mapper_component), 8929 OffloadingArgs); 8930 } 8931 8932 // Update the pointer to point to the next element that needs to be mapped, 8933 // and check whether we have mapped all elements. 8934 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 8935 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 8936 PtrPHI->addIncoming(PtrNext, BodyBB); 8937 llvm::Value *IsDone = 8938 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 8939 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 8940 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 8941 8942 MapperCGF.EmitBlock(ExitBB); 8943 // Emit array deletion if this is an array section and \p MapType indicates 8944 // that deletion is required. 8945 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8946 ElementSize, DoneBB, /*IsInit=*/false); 8947 8948 // Emit the function exit block. 8949 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 8950 MapperCGF.FinishFunction(); 8951 UDMMap.try_emplace(D, Fn); 8952 if (CGF) { 8953 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 8954 Decls.second.push_back(D); 8955 } 8956 } 8957 8958 /// Emit the array initialization or deletion portion for user-defined mapper 8959 /// code generation. First, it evaluates whether an array section is mapped and 8960 /// whether the \a MapType instructs to delete this section. If \a IsInit is 8961 /// true, and \a MapType indicates to not delete this array, array 8962 /// initialization code is generated. If \a IsInit is false, and \a MapType 8963 /// indicates to not this array, array deletion code is generated. 8964 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 8965 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 8966 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 8967 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 8968 StringRef Prefix = IsInit ? ".init" : ".del"; 8969 8970 // Evaluate if this is an array section. 8971 llvm::BasicBlock *IsDeleteBB = 8972 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"})); 8973 llvm::BasicBlock *BodyBB = 8974 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 8975 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 8976 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 8977 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 8978 8979 // Evaluate if we are going to delete this section. 8980 MapperCGF.EmitBlock(IsDeleteBB); 8981 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 8982 MapType, 8983 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 8984 llvm::Value *DeleteCond; 8985 if (IsInit) { 8986 DeleteCond = MapperCGF.Builder.CreateIsNull( 8987 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 8988 } else { 8989 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 8990 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 8991 } 8992 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 8993 8994 MapperCGF.EmitBlock(BodyBB); 8995 // Get the array size by multiplying element size and element number (i.e., \p 8996 // Size). 8997 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 8998 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 8999 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9000 // memory allocation/deletion purpose only. 9001 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9002 MapType, 9003 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9004 MappableExprsHandler::OMP_MAP_FROM))); 9005 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9006 // data structure. 9007 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9008 MapperCGF.EmitRuntimeCall( 9009 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 9010 CGM.getModule(), OMPRTL___tgt_push_mapper_component), 9011 OffloadingArgs); 9012 } 9013 9014 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9015 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9016 llvm::Value *DeviceID, 9017 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9018 const OMPLoopDirective &D)> 9019 SizeEmitter) { 9020 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9021 const OMPExecutableDirective *TD = &D; 9022 // Get nested teams distribute kind directive, if any. 9023 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9024 TD = getNestedDistributeDirective(CGM.getContext(), D); 9025 if (!TD) 9026 return; 9027 const auto *LD = cast<OMPLoopDirective>(TD); 9028 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9029 PrePostActionTy &) { 9030 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9031 llvm::Value *Args[] = {DeviceID, NumIterations}; 9032 CGF.EmitRuntimeCall( 9033 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 9034 CGM.getModule(), OMPRTL___kmpc_push_target_tripcount), 9035 Args); 9036 } 9037 }; 9038 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9039 } 9040 9041 void CGOpenMPRuntime::emitTargetCall( 9042 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9043 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9044 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 9045 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9046 const OMPLoopDirective &D)> 9047 SizeEmitter) { 9048 if (!CGF.HaveInsertPoint()) 9049 return; 9050 9051 assert(OutlinedFn && "Invalid outlined function!"); 9052 9053 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9054 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9055 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9056 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9057 PrePostActionTy &) { 9058 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9059 }; 9060 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9061 9062 CodeGenFunction::OMPTargetDataInfo InputInfo; 9063 llvm::Value *MapTypesArray = nullptr; 9064 // Fill up the pointer arrays and transfer execution to the device. 9065 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9066 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9067 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9068 if (Device.getInt() == OMPC_DEVICE_ancestor) { 9069 // Reverse offloading is not supported, so just execute on the host. 9070 if (RequiresOuterTask) { 9071 CapturedVars.clear(); 9072 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9073 } 9074 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9075 return; 9076 } 9077 9078 // On top of the arrays that were filled up, the target offloading call 9079 // takes as arguments the device id as well as the host pointer. The host 9080 // pointer is used by the runtime library to identify the current target 9081 // region, so it only has to be unique and not necessarily point to 9082 // anything. It could be the pointer to the outlined function that 9083 // implements the target region, but we aren't using that so that the 9084 // compiler doesn't need to keep that, and could therefore inline the host 9085 // function if proven worthwhile during optimization. 9086 9087 // From this point on, we need to have an ID of the target region defined. 9088 assert(OutlinedFnID && "Invalid outlined function ID!"); 9089 9090 // Emit device ID if any. 9091 llvm::Value *DeviceID; 9092 if (Device.getPointer()) { 9093 assert((Device.getInt() == OMPC_DEVICE_unknown || 9094 Device.getInt() == OMPC_DEVICE_device_num) && 9095 "Expected device_num modifier."); 9096 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer()); 9097 DeviceID = 9098 CGF.Builder.CreateIntCast(DevVal, CGF.Int64Ty, /*isSigned=*/true); 9099 } else { 9100 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9101 } 9102 9103 // Emit the number of elements in the offloading arrays. 9104 llvm::Value *PointerNum = 9105 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9106 9107 // Return value of the runtime offloading call. 9108 llvm::Value *Return; 9109 9110 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9111 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9112 9113 // Emit tripcount for the target loop-based directive. 9114 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9115 9116 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9117 // The target region is an outlined function launched by the runtime 9118 // via calls __tgt_target() or __tgt_target_teams(). 9119 // 9120 // __tgt_target() launches a target region with one team and one thread, 9121 // executing a serial region. This master thread may in turn launch 9122 // more threads within its team upon encountering a parallel region, 9123 // however, no additional teams can be launched on the device. 9124 // 9125 // __tgt_target_teams() launches a target region with one or more teams, 9126 // each with one or more threads. This call is required for target 9127 // constructs such as: 9128 // 'target teams' 9129 // 'target' / 'teams' 9130 // 'target teams distribute parallel for' 9131 // 'target parallel' 9132 // and so on. 9133 // 9134 // Note that on the host and CPU targets, the runtime implementation of 9135 // these calls simply call the outlined function without forking threads. 9136 // The outlined functions themselves have runtime calls to 9137 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9138 // the compiler in emitTeamsCall() and emitParallelCall(). 9139 // 9140 // In contrast, on the NVPTX target, the implementation of 9141 // __tgt_target_teams() launches a GPU kernel with the requested number 9142 // of teams and threads so no additional calls to the runtime are required. 9143 if (NumTeams) { 9144 // If we have NumTeams defined this means that we have an enclosed teams 9145 // region. Therefore we also expect to have NumThreads defined. These two 9146 // values should be defined in the presence of a teams directive, 9147 // regardless of having any clauses associated. If the user is using teams 9148 // but no clauses, these two values will be the default that should be 9149 // passed to the runtime library - a 32-bit integer with the value zero. 9150 assert(NumThreads && "Thread limit expression should be available along " 9151 "with number of teams."); 9152 llvm::Value *OffloadingArgs[] = {DeviceID, 9153 OutlinedFnID, 9154 PointerNum, 9155 InputInfo.BasePointersArray.getPointer(), 9156 InputInfo.PointersArray.getPointer(), 9157 InputInfo.SizesArray.getPointer(), 9158 MapTypesArray, 9159 NumTeams, 9160 NumThreads}; 9161 Return = CGF.EmitRuntimeCall( 9162 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 9163 CGM.getModule(), HasNowait ? OMPRTL___tgt_target_teams_nowait 9164 : OMPRTL___tgt_target_teams), 9165 OffloadingArgs); 9166 } else { 9167 llvm::Value *OffloadingArgs[] = {DeviceID, 9168 OutlinedFnID, 9169 PointerNum, 9170 InputInfo.BasePointersArray.getPointer(), 9171 InputInfo.PointersArray.getPointer(), 9172 InputInfo.SizesArray.getPointer(), 9173 MapTypesArray}; 9174 Return = CGF.EmitRuntimeCall( 9175 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 9176 CGM.getModule(), 9177 HasNowait ? OMPRTL___tgt_target_nowait : OMPRTL___tgt_target), 9178 OffloadingArgs); 9179 } 9180 9181 // Check the error code and execute the host version if required. 9182 llvm::BasicBlock *OffloadFailedBlock = 9183 CGF.createBasicBlock("omp_offload.failed"); 9184 llvm::BasicBlock *OffloadContBlock = 9185 CGF.createBasicBlock("omp_offload.cont"); 9186 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9187 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9188 9189 CGF.EmitBlock(OffloadFailedBlock); 9190 if (RequiresOuterTask) { 9191 CapturedVars.clear(); 9192 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9193 } 9194 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9195 CGF.EmitBranch(OffloadContBlock); 9196 9197 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9198 }; 9199 9200 // Notify that the host version must be executed. 9201 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9202 RequiresOuterTask](CodeGenFunction &CGF, 9203 PrePostActionTy &) { 9204 if (RequiresOuterTask) { 9205 CapturedVars.clear(); 9206 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9207 } 9208 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9209 }; 9210 9211 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9212 &CapturedVars, RequiresOuterTask, 9213 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9214 // Fill up the arrays with all the captured variables. 9215 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9216 MappableExprsHandler::MapValuesArrayTy Pointers; 9217 MappableExprsHandler::MapValuesArrayTy Sizes; 9218 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9219 9220 // Get mappable expression information. 9221 MappableExprsHandler MEHandler(D, CGF); 9222 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9223 9224 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9225 auto CV = CapturedVars.begin(); 9226 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9227 CE = CS.capture_end(); 9228 CI != CE; ++CI, ++RI, ++CV) { 9229 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9230 MappableExprsHandler::MapValuesArrayTy CurPointers; 9231 MappableExprsHandler::MapValuesArrayTy CurSizes; 9232 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9233 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9234 9235 // VLA sizes are passed to the outlined region by copy and do not have map 9236 // information associated. 9237 if (CI->capturesVariableArrayType()) { 9238 CurBasePointers.push_back(*CV); 9239 CurPointers.push_back(*CV); 9240 CurSizes.push_back(CGF.Builder.CreateIntCast( 9241 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9242 // Copy to the device as an argument. No need to retrieve it. 9243 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9244 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9245 MappableExprsHandler::OMP_MAP_IMPLICIT); 9246 } else { 9247 // If we have any information in the map clause, we use it, otherwise we 9248 // just do a default mapping. 9249 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9250 CurSizes, CurMapTypes, PartialStruct); 9251 if (CurBasePointers.empty()) 9252 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9253 CurPointers, CurSizes, CurMapTypes); 9254 // Generate correct mapping for variables captured by reference in 9255 // lambdas. 9256 if (CI->capturesVariable()) 9257 MEHandler.generateInfoForLambdaCaptures( 9258 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9259 CurMapTypes, LambdaPointers); 9260 } 9261 // We expect to have at least an element of information for this capture. 9262 assert(!CurBasePointers.empty() && 9263 "Non-existing map pointer for capture!"); 9264 assert(CurBasePointers.size() == CurPointers.size() && 9265 CurBasePointers.size() == CurSizes.size() && 9266 CurBasePointers.size() == CurMapTypes.size() && 9267 "Inconsistent map information sizes!"); 9268 9269 // If there is an entry in PartialStruct it means we have a struct with 9270 // individual members mapped. Emit an extra combined entry. 9271 if (PartialStruct.Base.isValid()) 9272 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9273 CurMapTypes, PartialStruct); 9274 9275 // We need to append the results of this capture to what we already have. 9276 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9277 Pointers.append(CurPointers.begin(), CurPointers.end()); 9278 Sizes.append(CurSizes.begin(), CurSizes.end()); 9279 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9280 } 9281 // Adjust MEMBER_OF flags for the lambdas captures. 9282 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9283 Pointers, MapTypes); 9284 // Map other list items in the map clause which are not captured variables 9285 // but "declare target link" global variables. 9286 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9287 MapTypes); 9288 9289 TargetDataInfo Info; 9290 // Fill up the arrays and create the arguments. 9291 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9292 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9293 Info.PointersArray, Info.SizesArray, 9294 Info.MapTypesArray, Info); 9295 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9296 InputInfo.BasePointersArray = 9297 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9298 InputInfo.PointersArray = 9299 Address(Info.PointersArray, CGM.getPointerAlign()); 9300 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9301 MapTypesArray = Info.MapTypesArray; 9302 if (RequiresOuterTask) 9303 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9304 else 9305 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9306 }; 9307 9308 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9309 CodeGenFunction &CGF, PrePostActionTy &) { 9310 if (RequiresOuterTask) { 9311 CodeGenFunction::OMPTargetDataInfo InputInfo; 9312 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9313 } else { 9314 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9315 } 9316 }; 9317 9318 // If we have a target function ID it means that we need to support 9319 // offloading, otherwise, just execute on the host. We need to execute on host 9320 // regardless of the conditional in the if clause if, e.g., the user do not 9321 // specify target triples. 9322 if (OutlinedFnID) { 9323 if (IfCond) { 9324 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9325 } else { 9326 RegionCodeGenTy ThenRCG(TargetThenGen); 9327 ThenRCG(CGF); 9328 } 9329 } else { 9330 RegionCodeGenTy ElseRCG(TargetElseGen); 9331 ElseRCG(CGF); 9332 } 9333 } 9334 9335 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9336 StringRef ParentName) { 9337 if (!S) 9338 return; 9339 9340 // Codegen OMP target directives that offload compute to the device. 9341 bool RequiresDeviceCodegen = 9342 isa<OMPExecutableDirective>(S) && 9343 isOpenMPTargetExecutionDirective( 9344 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9345 9346 if (RequiresDeviceCodegen) { 9347 const auto &E = *cast<OMPExecutableDirective>(S); 9348 unsigned DeviceID; 9349 unsigned FileID; 9350 unsigned Line; 9351 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9352 FileID, Line); 9353 9354 // Is this a target region that should not be emitted as an entry point? If 9355 // so just signal we are done with this target region. 9356 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9357 ParentName, Line)) 9358 return; 9359 9360 switch (E.getDirectiveKind()) { 9361 case OMPD_target: 9362 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9363 cast<OMPTargetDirective>(E)); 9364 break; 9365 case OMPD_target_parallel: 9366 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9367 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9368 break; 9369 case OMPD_target_teams: 9370 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9371 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9372 break; 9373 case OMPD_target_teams_distribute: 9374 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9375 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9376 break; 9377 case OMPD_target_teams_distribute_simd: 9378 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9379 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9380 break; 9381 case OMPD_target_parallel_for: 9382 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9383 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9384 break; 9385 case OMPD_target_parallel_for_simd: 9386 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9387 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9388 break; 9389 case OMPD_target_simd: 9390 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9391 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9392 break; 9393 case OMPD_target_teams_distribute_parallel_for: 9394 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9395 CGM, ParentName, 9396 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9397 break; 9398 case OMPD_target_teams_distribute_parallel_for_simd: 9399 CodeGenFunction:: 9400 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9401 CGM, ParentName, 9402 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9403 break; 9404 case OMPD_parallel: 9405 case OMPD_for: 9406 case OMPD_parallel_for: 9407 case OMPD_parallel_master: 9408 case OMPD_parallel_sections: 9409 case OMPD_for_simd: 9410 case OMPD_parallel_for_simd: 9411 case OMPD_cancel: 9412 case OMPD_cancellation_point: 9413 case OMPD_ordered: 9414 case OMPD_threadprivate: 9415 case OMPD_allocate: 9416 case OMPD_task: 9417 case OMPD_simd: 9418 case OMPD_sections: 9419 case OMPD_section: 9420 case OMPD_single: 9421 case OMPD_master: 9422 case OMPD_critical: 9423 case OMPD_taskyield: 9424 case OMPD_barrier: 9425 case OMPD_taskwait: 9426 case OMPD_taskgroup: 9427 case OMPD_atomic: 9428 case OMPD_flush: 9429 case OMPD_depobj: 9430 case OMPD_scan: 9431 case OMPD_teams: 9432 case OMPD_target_data: 9433 case OMPD_target_exit_data: 9434 case OMPD_target_enter_data: 9435 case OMPD_distribute: 9436 case OMPD_distribute_simd: 9437 case OMPD_distribute_parallel_for: 9438 case OMPD_distribute_parallel_for_simd: 9439 case OMPD_teams_distribute: 9440 case OMPD_teams_distribute_simd: 9441 case OMPD_teams_distribute_parallel_for: 9442 case OMPD_teams_distribute_parallel_for_simd: 9443 case OMPD_target_update: 9444 case OMPD_declare_simd: 9445 case OMPD_declare_variant: 9446 case OMPD_begin_declare_variant: 9447 case OMPD_end_declare_variant: 9448 case OMPD_declare_target: 9449 case OMPD_end_declare_target: 9450 case OMPD_declare_reduction: 9451 case OMPD_declare_mapper: 9452 case OMPD_taskloop: 9453 case OMPD_taskloop_simd: 9454 case OMPD_master_taskloop: 9455 case OMPD_master_taskloop_simd: 9456 case OMPD_parallel_master_taskloop: 9457 case OMPD_parallel_master_taskloop_simd: 9458 case OMPD_requires: 9459 case OMPD_unknown: 9460 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9461 } 9462 return; 9463 } 9464 9465 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9466 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9467 return; 9468 9469 scanForTargetRegionsFunctions( 9470 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9471 return; 9472 } 9473 9474 // If this is a lambda function, look into its body. 9475 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9476 S = L->getBody(); 9477 9478 // Keep looking for target regions recursively. 9479 for (const Stmt *II : S->children()) 9480 scanForTargetRegionsFunctions(II, ParentName); 9481 } 9482 9483 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9484 // If emitting code for the host, we do not process FD here. Instead we do 9485 // the normal code generation. 9486 if (!CGM.getLangOpts().OpenMPIsDevice) { 9487 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9488 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9489 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9490 // Do not emit device_type(nohost) functions for the host. 9491 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9492 return true; 9493 } 9494 return false; 9495 } 9496 9497 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9498 // Try to detect target regions in the function. 9499 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9500 StringRef Name = CGM.getMangledName(GD); 9501 scanForTargetRegionsFunctions(FD->getBody(), Name); 9502 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9503 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9504 // Do not emit device_type(nohost) functions for the host. 9505 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9506 return true; 9507 } 9508 9509 // Do not to emit function if it is not marked as declare target. 9510 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9511 AlreadyEmittedTargetDecls.count(VD) == 0; 9512 } 9513 9514 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9515 if (!CGM.getLangOpts().OpenMPIsDevice) 9516 return false; 9517 9518 // Check if there are Ctors/Dtors in this declaration and look for target 9519 // regions in it. We use the complete variant to produce the kernel name 9520 // mangling. 9521 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9522 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9523 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9524 StringRef ParentName = 9525 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9526 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9527 } 9528 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9529 StringRef ParentName = 9530 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9531 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9532 } 9533 } 9534 9535 // Do not to emit variable if it is not marked as declare target. 9536 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9537 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9538 cast<VarDecl>(GD.getDecl())); 9539 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9540 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9541 HasRequiresUnifiedSharedMemory)) { 9542 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9543 return true; 9544 } 9545 return false; 9546 } 9547 9548 llvm::Constant * 9549 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9550 const VarDecl *VD) { 9551 assert(VD->getType().isConstant(CGM.getContext()) && 9552 "Expected constant variable."); 9553 StringRef VarName; 9554 llvm::Constant *Addr; 9555 llvm::GlobalValue::LinkageTypes Linkage; 9556 QualType Ty = VD->getType(); 9557 SmallString<128> Buffer; 9558 { 9559 unsigned DeviceID; 9560 unsigned FileID; 9561 unsigned Line; 9562 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9563 FileID, Line); 9564 llvm::raw_svector_ostream OS(Buffer); 9565 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9566 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9567 VarName = OS.str(); 9568 } 9569 Linkage = llvm::GlobalValue::InternalLinkage; 9570 Addr = 9571 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9572 getDefaultFirstprivateAddressSpace()); 9573 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9574 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9575 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9576 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9577 VarName, Addr, VarSize, 9578 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9579 return Addr; 9580 } 9581 9582 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9583 llvm::Constant *Addr) { 9584 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9585 !CGM.getLangOpts().OpenMPIsDevice) 9586 return; 9587 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9588 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9589 if (!Res) { 9590 if (CGM.getLangOpts().OpenMPIsDevice) { 9591 // Register non-target variables being emitted in device code (debug info 9592 // may cause this). 9593 StringRef VarName = CGM.getMangledName(VD); 9594 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9595 } 9596 return; 9597 } 9598 // Register declare target variables. 9599 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9600 StringRef VarName; 9601 CharUnits VarSize; 9602 llvm::GlobalValue::LinkageTypes Linkage; 9603 9604 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9605 !HasRequiresUnifiedSharedMemory) { 9606 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9607 VarName = CGM.getMangledName(VD); 9608 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9609 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9610 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9611 } else { 9612 VarSize = CharUnits::Zero(); 9613 } 9614 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9615 // Temp solution to prevent optimizations of the internal variables. 9616 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9617 std::string RefName = getName({VarName, "ref"}); 9618 if (!CGM.GetGlobalValue(RefName)) { 9619 llvm::Constant *AddrRef = 9620 getOrCreateInternalVariable(Addr->getType(), RefName); 9621 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9622 GVAddrRef->setConstant(/*Val=*/true); 9623 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9624 GVAddrRef->setInitializer(Addr); 9625 CGM.addCompilerUsedGlobal(GVAddrRef); 9626 } 9627 } 9628 } else { 9629 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9630 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9631 HasRequiresUnifiedSharedMemory)) && 9632 "Declare target attribute must link or to with unified memory."); 9633 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9634 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9635 else 9636 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9637 9638 if (CGM.getLangOpts().OpenMPIsDevice) { 9639 VarName = Addr->getName(); 9640 Addr = nullptr; 9641 } else { 9642 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9643 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9644 } 9645 VarSize = CGM.getPointerSize(); 9646 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9647 } 9648 9649 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9650 VarName, Addr, VarSize, Flags, Linkage); 9651 } 9652 9653 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9654 if (isa<FunctionDecl>(GD.getDecl()) || 9655 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9656 return emitTargetFunctions(GD); 9657 9658 return emitTargetGlobalVariable(GD); 9659 } 9660 9661 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9662 for (const VarDecl *VD : DeferredGlobalVariables) { 9663 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9664 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9665 if (!Res) 9666 continue; 9667 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9668 !HasRequiresUnifiedSharedMemory) { 9669 CGM.EmitGlobal(VD); 9670 } else { 9671 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9672 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9673 HasRequiresUnifiedSharedMemory)) && 9674 "Expected link clause or to clause with unified memory."); 9675 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9676 } 9677 } 9678 } 9679 9680 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9681 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9682 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9683 " Expected target-based directive."); 9684 } 9685 9686 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 9687 for (const OMPClause *Clause : D->clauselists()) { 9688 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9689 HasRequiresUnifiedSharedMemory = true; 9690 } else if (const auto *AC = 9691 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 9692 switch (AC->getAtomicDefaultMemOrderKind()) { 9693 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 9694 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 9695 break; 9696 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 9697 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 9698 break; 9699 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 9700 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 9701 break; 9702 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 9703 break; 9704 } 9705 } 9706 } 9707 } 9708 9709 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 9710 return RequiresAtomicOrdering; 9711 } 9712 9713 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9714 LangAS &AS) { 9715 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9716 return false; 9717 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9718 switch(A->getAllocatorType()) { 9719 case OMPAllocateDeclAttr::OMPNullMemAlloc: 9720 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9721 // Not supported, fallback to the default mem space. 9722 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9723 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9724 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9725 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9726 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9727 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9728 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9729 AS = LangAS::Default; 9730 return true; 9731 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9732 llvm_unreachable("Expected predefined allocator for the variables with the " 9733 "static storage."); 9734 } 9735 return false; 9736 } 9737 9738 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9739 return HasRequiresUnifiedSharedMemory; 9740 } 9741 9742 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9743 CodeGenModule &CGM) 9744 : CGM(CGM) { 9745 if (CGM.getLangOpts().OpenMPIsDevice) { 9746 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9747 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9748 } 9749 } 9750 9751 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9752 if (CGM.getLangOpts().OpenMPIsDevice) 9753 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9754 } 9755 9756 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9757 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9758 return true; 9759 9760 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9761 // Do not to emit function if it is marked as declare target as it was already 9762 // emitted. 9763 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9764 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 9765 if (auto *F = dyn_cast_or_null<llvm::Function>( 9766 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 9767 return !F->isDeclaration(); 9768 return false; 9769 } 9770 return true; 9771 } 9772 9773 return !AlreadyEmittedTargetDecls.insert(D).second; 9774 } 9775 9776 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9777 // If we don't have entries or if we are emitting code for the device, we 9778 // don't need to do anything. 9779 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9780 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9781 (OffloadEntriesInfoManager.empty() && 9782 !HasEmittedDeclareTargetRegion && 9783 !HasEmittedTargetRegion)) 9784 return nullptr; 9785 9786 // Create and register the function that handles the requires directives. 9787 ASTContext &C = CGM.getContext(); 9788 9789 llvm::Function *RequiresRegFn; 9790 { 9791 CodeGenFunction CGF(CGM); 9792 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9793 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9794 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9795 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9796 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9797 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9798 // TODO: check for other requires clauses. 9799 // The requires directive takes effect only when a target region is 9800 // present in the compilation unit. Otherwise it is ignored and not 9801 // passed to the runtime. This avoids the runtime from throwing an error 9802 // for mismatching requires clauses across compilation units that don't 9803 // contain at least 1 target region. 9804 assert((HasEmittedTargetRegion || 9805 HasEmittedDeclareTargetRegion || 9806 !OffloadEntriesInfoManager.empty()) && 9807 "Target or declare target region expected."); 9808 if (HasRequiresUnifiedSharedMemory) 9809 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9810 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 9811 CGM.getModule(), OMPRTL___tgt_register_requires), 9812 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9813 CGF.FinishFunction(); 9814 } 9815 return RequiresRegFn; 9816 } 9817 9818 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9819 const OMPExecutableDirective &D, 9820 SourceLocation Loc, 9821 llvm::Function *OutlinedFn, 9822 ArrayRef<llvm::Value *> CapturedVars) { 9823 if (!CGF.HaveInsertPoint()) 9824 return; 9825 9826 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9827 CodeGenFunction::RunCleanupsScope Scope(CGF); 9828 9829 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9830 llvm::Value *Args[] = { 9831 RTLoc, 9832 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9833 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9834 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9835 RealArgs.append(std::begin(Args), std::end(Args)); 9836 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9837 9838 llvm::FunctionCallee RTLFn = 9839 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 9840 CGM.getModule(), OMPRTL___kmpc_fork_teams); 9841 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9842 } 9843 9844 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9845 const Expr *NumTeams, 9846 const Expr *ThreadLimit, 9847 SourceLocation Loc) { 9848 if (!CGF.HaveInsertPoint()) 9849 return; 9850 9851 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9852 9853 llvm::Value *NumTeamsVal = 9854 NumTeams 9855 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9856 CGF.CGM.Int32Ty, /* isSigned = */ true) 9857 : CGF.Builder.getInt32(0); 9858 9859 llvm::Value *ThreadLimitVal = 9860 ThreadLimit 9861 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 9862 CGF.CGM.Int32Ty, /* isSigned = */ true) 9863 : CGF.Builder.getInt32(0); 9864 9865 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 9866 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 9867 ThreadLimitVal}; 9868 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 9869 CGM.getModule(), OMPRTL___kmpc_push_num_teams), 9870 PushNumTeamsArgs); 9871 } 9872 9873 void CGOpenMPRuntime::emitTargetDataCalls( 9874 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 9875 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 9876 if (!CGF.HaveInsertPoint()) 9877 return; 9878 9879 // Action used to replace the default codegen action and turn privatization 9880 // off. 9881 PrePostActionTy NoPrivAction; 9882 9883 // Generate the code for the opening of the data environment. Capture all the 9884 // arguments of the runtime call by reference because they are used in the 9885 // closing of the region. 9886 auto &&BeginThenGen = [this, &D, Device, &Info, 9887 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 9888 // Fill up the arrays with all the mapped variables. 9889 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9890 MappableExprsHandler::MapValuesArrayTy Pointers; 9891 MappableExprsHandler::MapValuesArrayTy Sizes; 9892 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9893 9894 // Get map clause information. 9895 MappableExprsHandler MCHandler(D, CGF); 9896 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 9897 9898 // Fill up the arrays and create the arguments. 9899 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9900 9901 llvm::Value *BasePointersArrayArg = nullptr; 9902 llvm::Value *PointersArrayArg = nullptr; 9903 llvm::Value *SizesArrayArg = nullptr; 9904 llvm::Value *MapTypesArrayArg = nullptr; 9905 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 9906 SizesArrayArg, MapTypesArrayArg, Info); 9907 9908 // Emit device ID if any. 9909 llvm::Value *DeviceID = nullptr; 9910 if (Device) { 9911 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9912 CGF.Int64Ty, /*isSigned=*/true); 9913 } else { 9914 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9915 } 9916 9917 // Emit the number of elements in the offloading arrays. 9918 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 9919 9920 llvm::Value *OffloadingArgs[] = { 9921 DeviceID, PointerNum, BasePointersArrayArg, 9922 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 9923 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 9924 CGM.getModule(), OMPRTL___tgt_target_data_begin), 9925 OffloadingArgs); 9926 9927 // If device pointer privatization is required, emit the body of the region 9928 // here. It will have to be duplicated: with and without privatization. 9929 if (!Info.CaptureDeviceAddrMap.empty()) 9930 CodeGen(CGF); 9931 }; 9932 9933 // Generate code for the closing of the data region. 9934 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 9935 PrePostActionTy &) { 9936 assert(Info.isValid() && "Invalid data environment closing arguments."); 9937 9938 llvm::Value *BasePointersArrayArg = nullptr; 9939 llvm::Value *PointersArrayArg = nullptr; 9940 llvm::Value *SizesArrayArg = nullptr; 9941 llvm::Value *MapTypesArrayArg = nullptr; 9942 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 9943 SizesArrayArg, MapTypesArrayArg, Info); 9944 9945 // Emit device ID if any. 9946 llvm::Value *DeviceID = nullptr; 9947 if (Device) { 9948 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9949 CGF.Int64Ty, /*isSigned=*/true); 9950 } else { 9951 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9952 } 9953 9954 // Emit the number of elements in the offloading arrays. 9955 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 9956 9957 llvm::Value *OffloadingArgs[] = { 9958 DeviceID, PointerNum, BasePointersArrayArg, 9959 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 9960 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 9961 CGM.getModule(), OMPRTL___tgt_target_data_end), 9962 OffloadingArgs); 9963 }; 9964 9965 // If we need device pointer privatization, we need to emit the body of the 9966 // region with no privatization in the 'else' branch of the conditional. 9967 // Otherwise, we don't have to do anything. 9968 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 9969 PrePostActionTy &) { 9970 if (!Info.CaptureDeviceAddrMap.empty()) { 9971 CodeGen.setAction(NoPrivAction); 9972 CodeGen(CGF); 9973 } 9974 }; 9975 9976 // We don't have to do anything to close the region if the if clause evaluates 9977 // to false. 9978 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 9979 9980 if (IfCond) { 9981 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 9982 } else { 9983 RegionCodeGenTy RCG(BeginThenGen); 9984 RCG(CGF); 9985 } 9986 9987 // If we don't require privatization of device pointers, we emit the body in 9988 // between the runtime calls. This avoids duplicating the body code. 9989 if (Info.CaptureDeviceAddrMap.empty()) { 9990 CodeGen.setAction(NoPrivAction); 9991 CodeGen(CGF); 9992 } 9993 9994 if (IfCond) { 9995 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 9996 } else { 9997 RegionCodeGenTy RCG(EndThenGen); 9998 RCG(CGF); 9999 } 10000 } 10001 10002 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10003 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10004 const Expr *Device) { 10005 if (!CGF.HaveInsertPoint()) 10006 return; 10007 10008 assert((isa<OMPTargetEnterDataDirective>(D) || 10009 isa<OMPTargetExitDataDirective>(D) || 10010 isa<OMPTargetUpdateDirective>(D)) && 10011 "Expecting either target enter, exit data, or update directives."); 10012 10013 CodeGenFunction::OMPTargetDataInfo InputInfo; 10014 llvm::Value *MapTypesArray = nullptr; 10015 // Generate the code for the opening of the data environment. 10016 auto &&ThenGen = [this, &D, Device, &InputInfo, 10017 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10018 // Emit device ID if any. 10019 llvm::Value *DeviceID = nullptr; 10020 if (Device) { 10021 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10022 CGF.Int64Ty, /*isSigned=*/true); 10023 } else { 10024 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10025 } 10026 10027 // Emit the number of elements in the offloading arrays. 10028 llvm::Constant *PointerNum = 10029 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10030 10031 llvm::Value *OffloadingArgs[] = {DeviceID, 10032 PointerNum, 10033 InputInfo.BasePointersArray.getPointer(), 10034 InputInfo.PointersArray.getPointer(), 10035 InputInfo.SizesArray.getPointer(), 10036 MapTypesArray}; 10037 10038 // Select the right runtime function call for each expected standalone 10039 // directive. 10040 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10041 RuntimeFunction RTLFn; 10042 switch (D.getDirectiveKind()) { 10043 case OMPD_target_enter_data: 10044 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait 10045 : OMPRTL___tgt_target_data_begin; 10046 break; 10047 case OMPD_target_exit_data: 10048 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait 10049 : OMPRTL___tgt_target_data_end; 10050 break; 10051 case OMPD_target_update: 10052 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait 10053 : OMPRTL___tgt_target_data_update; 10054 break; 10055 case OMPD_parallel: 10056 case OMPD_for: 10057 case OMPD_parallel_for: 10058 case OMPD_parallel_master: 10059 case OMPD_parallel_sections: 10060 case OMPD_for_simd: 10061 case OMPD_parallel_for_simd: 10062 case OMPD_cancel: 10063 case OMPD_cancellation_point: 10064 case OMPD_ordered: 10065 case OMPD_threadprivate: 10066 case OMPD_allocate: 10067 case OMPD_task: 10068 case OMPD_simd: 10069 case OMPD_sections: 10070 case OMPD_section: 10071 case OMPD_single: 10072 case OMPD_master: 10073 case OMPD_critical: 10074 case OMPD_taskyield: 10075 case OMPD_barrier: 10076 case OMPD_taskwait: 10077 case OMPD_taskgroup: 10078 case OMPD_atomic: 10079 case OMPD_flush: 10080 case OMPD_depobj: 10081 case OMPD_scan: 10082 case OMPD_teams: 10083 case OMPD_target_data: 10084 case OMPD_distribute: 10085 case OMPD_distribute_simd: 10086 case OMPD_distribute_parallel_for: 10087 case OMPD_distribute_parallel_for_simd: 10088 case OMPD_teams_distribute: 10089 case OMPD_teams_distribute_simd: 10090 case OMPD_teams_distribute_parallel_for: 10091 case OMPD_teams_distribute_parallel_for_simd: 10092 case OMPD_declare_simd: 10093 case OMPD_declare_variant: 10094 case OMPD_begin_declare_variant: 10095 case OMPD_end_declare_variant: 10096 case OMPD_declare_target: 10097 case OMPD_end_declare_target: 10098 case OMPD_declare_reduction: 10099 case OMPD_declare_mapper: 10100 case OMPD_taskloop: 10101 case OMPD_taskloop_simd: 10102 case OMPD_master_taskloop: 10103 case OMPD_master_taskloop_simd: 10104 case OMPD_parallel_master_taskloop: 10105 case OMPD_parallel_master_taskloop_simd: 10106 case OMPD_target: 10107 case OMPD_target_simd: 10108 case OMPD_target_teams_distribute: 10109 case OMPD_target_teams_distribute_simd: 10110 case OMPD_target_teams_distribute_parallel_for: 10111 case OMPD_target_teams_distribute_parallel_for_simd: 10112 case OMPD_target_teams: 10113 case OMPD_target_parallel: 10114 case OMPD_target_parallel_for: 10115 case OMPD_target_parallel_for_simd: 10116 case OMPD_requires: 10117 case OMPD_unknown: 10118 llvm_unreachable("Unexpected standalone target data directive."); 10119 break; 10120 } 10121 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 10122 CGM.getModule(), RTLFn), 10123 OffloadingArgs); 10124 }; 10125 10126 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10127 CodeGenFunction &CGF, PrePostActionTy &) { 10128 // Fill up the arrays with all the mapped variables. 10129 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10130 MappableExprsHandler::MapValuesArrayTy Pointers; 10131 MappableExprsHandler::MapValuesArrayTy Sizes; 10132 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10133 10134 // Get map clause information. 10135 MappableExprsHandler MEHandler(D, CGF); 10136 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10137 10138 TargetDataInfo Info; 10139 // Fill up the arrays and create the arguments. 10140 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10141 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10142 Info.PointersArray, Info.SizesArray, 10143 Info.MapTypesArray, Info); 10144 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10145 InputInfo.BasePointersArray = 10146 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10147 InputInfo.PointersArray = 10148 Address(Info.PointersArray, CGM.getPointerAlign()); 10149 InputInfo.SizesArray = 10150 Address(Info.SizesArray, CGM.getPointerAlign()); 10151 MapTypesArray = Info.MapTypesArray; 10152 if (D.hasClausesOfKind<OMPDependClause>()) 10153 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10154 else 10155 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10156 }; 10157 10158 if (IfCond) { 10159 emitIfClause(CGF, IfCond, TargetThenGen, 10160 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10161 } else { 10162 RegionCodeGenTy ThenRCG(TargetThenGen); 10163 ThenRCG(CGF); 10164 } 10165 } 10166 10167 namespace { 10168 /// Kind of parameter in a function with 'declare simd' directive. 10169 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10170 /// Attribute set of the parameter. 10171 struct ParamAttrTy { 10172 ParamKindTy Kind = Vector; 10173 llvm::APSInt StrideOrArg; 10174 llvm::APSInt Alignment; 10175 }; 10176 } // namespace 10177 10178 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10179 ArrayRef<ParamAttrTy> ParamAttrs) { 10180 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10181 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10182 // of that clause. The VLEN value must be power of 2. 10183 // In other case the notion of the function`s "characteristic data type" (CDT) 10184 // is used to compute the vector length. 10185 // CDT is defined in the following order: 10186 // a) For non-void function, the CDT is the return type. 10187 // b) If the function has any non-uniform, non-linear parameters, then the 10188 // CDT is the type of the first such parameter. 10189 // c) If the CDT determined by a) or b) above is struct, union, or class 10190 // type which is pass-by-value (except for the type that maps to the 10191 // built-in complex data type), the characteristic data type is int. 10192 // d) If none of the above three cases is applicable, the CDT is int. 10193 // The VLEN is then determined based on the CDT and the size of vector 10194 // register of that ISA for which current vector version is generated. The 10195 // VLEN is computed using the formula below: 10196 // VLEN = sizeof(vector_register) / sizeof(CDT), 10197 // where vector register size specified in section 3.2.1 Registers and the 10198 // Stack Frame of original AMD64 ABI document. 10199 QualType RetType = FD->getReturnType(); 10200 if (RetType.isNull()) 10201 return 0; 10202 ASTContext &C = FD->getASTContext(); 10203 QualType CDT; 10204 if (!RetType.isNull() && !RetType->isVoidType()) { 10205 CDT = RetType; 10206 } else { 10207 unsigned Offset = 0; 10208 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10209 if (ParamAttrs[Offset].Kind == Vector) 10210 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10211 ++Offset; 10212 } 10213 if (CDT.isNull()) { 10214 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10215 if (ParamAttrs[I + Offset].Kind == Vector) { 10216 CDT = FD->getParamDecl(I)->getType(); 10217 break; 10218 } 10219 } 10220 } 10221 } 10222 if (CDT.isNull()) 10223 CDT = C.IntTy; 10224 CDT = CDT->getCanonicalTypeUnqualified(); 10225 if (CDT->isRecordType() || CDT->isUnionType()) 10226 CDT = C.IntTy; 10227 return C.getTypeSize(CDT); 10228 } 10229 10230 static void 10231 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10232 const llvm::APSInt &VLENVal, 10233 ArrayRef<ParamAttrTy> ParamAttrs, 10234 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10235 struct ISADataTy { 10236 char ISA; 10237 unsigned VecRegSize; 10238 }; 10239 ISADataTy ISAData[] = { 10240 { 10241 'b', 128 10242 }, // SSE 10243 { 10244 'c', 256 10245 }, // AVX 10246 { 10247 'd', 256 10248 }, // AVX2 10249 { 10250 'e', 512 10251 }, // AVX512 10252 }; 10253 llvm::SmallVector<char, 2> Masked; 10254 switch (State) { 10255 case OMPDeclareSimdDeclAttr::BS_Undefined: 10256 Masked.push_back('N'); 10257 Masked.push_back('M'); 10258 break; 10259 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10260 Masked.push_back('N'); 10261 break; 10262 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10263 Masked.push_back('M'); 10264 break; 10265 } 10266 for (char Mask : Masked) { 10267 for (const ISADataTy &Data : ISAData) { 10268 SmallString<256> Buffer; 10269 llvm::raw_svector_ostream Out(Buffer); 10270 Out << "_ZGV" << Data.ISA << Mask; 10271 if (!VLENVal) { 10272 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10273 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10274 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10275 } else { 10276 Out << VLENVal; 10277 } 10278 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10279 switch (ParamAttr.Kind){ 10280 case LinearWithVarStride: 10281 Out << 's' << ParamAttr.StrideOrArg; 10282 break; 10283 case Linear: 10284 Out << 'l'; 10285 if (ParamAttr.StrideOrArg != 1) 10286 Out << ParamAttr.StrideOrArg; 10287 break; 10288 case Uniform: 10289 Out << 'u'; 10290 break; 10291 case Vector: 10292 Out << 'v'; 10293 break; 10294 } 10295 if (!!ParamAttr.Alignment) 10296 Out << 'a' << ParamAttr.Alignment; 10297 } 10298 Out << '_' << Fn->getName(); 10299 Fn->addFnAttr(Out.str()); 10300 } 10301 } 10302 } 10303 10304 // This are the Functions that are needed to mangle the name of the 10305 // vector functions generated by the compiler, according to the rules 10306 // defined in the "Vector Function ABI specifications for AArch64", 10307 // available at 10308 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10309 10310 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10311 /// 10312 /// TODO: Need to implement the behavior for reference marked with a 10313 /// var or no linear modifiers (1.b in the section). For this, we 10314 /// need to extend ParamKindTy to support the linear modifiers. 10315 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10316 QT = QT.getCanonicalType(); 10317 10318 if (QT->isVoidType()) 10319 return false; 10320 10321 if (Kind == ParamKindTy::Uniform) 10322 return false; 10323 10324 if (Kind == ParamKindTy::Linear) 10325 return false; 10326 10327 // TODO: Handle linear references with modifiers 10328 10329 if (Kind == ParamKindTy::LinearWithVarStride) 10330 return false; 10331 10332 return true; 10333 } 10334 10335 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10336 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10337 QT = QT.getCanonicalType(); 10338 unsigned Size = C.getTypeSize(QT); 10339 10340 // Only scalars and complex within 16 bytes wide set PVB to true. 10341 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10342 return false; 10343 10344 if (QT->isFloatingType()) 10345 return true; 10346 10347 if (QT->isIntegerType()) 10348 return true; 10349 10350 if (QT->isPointerType()) 10351 return true; 10352 10353 // TODO: Add support for complex types (section 3.1.2, item 2). 10354 10355 return false; 10356 } 10357 10358 /// Computes the lane size (LS) of a return type or of an input parameter, 10359 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10360 /// TODO: Add support for references, section 3.2.1, item 1. 10361 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10362 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10363 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10364 if (getAArch64PBV(PTy, C)) 10365 return C.getTypeSize(PTy); 10366 } 10367 if (getAArch64PBV(QT, C)) 10368 return C.getTypeSize(QT); 10369 10370 return C.getTypeSize(C.getUIntPtrType()); 10371 } 10372 10373 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10374 // signature of the scalar function, as defined in 3.2.2 of the 10375 // AAVFABI. 10376 static std::tuple<unsigned, unsigned, bool> 10377 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10378 QualType RetType = FD->getReturnType().getCanonicalType(); 10379 10380 ASTContext &C = FD->getASTContext(); 10381 10382 bool OutputBecomesInput = false; 10383 10384 llvm::SmallVector<unsigned, 8> Sizes; 10385 if (!RetType->isVoidType()) { 10386 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10387 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10388 OutputBecomesInput = true; 10389 } 10390 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10391 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10392 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10393 } 10394 10395 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10396 // The LS of a function parameter / return value can only be a power 10397 // of 2, starting from 8 bits, up to 128. 10398 assert(std::all_of(Sizes.begin(), Sizes.end(), 10399 [](unsigned Size) { 10400 return Size == 8 || Size == 16 || Size == 32 || 10401 Size == 64 || Size == 128; 10402 }) && 10403 "Invalid size"); 10404 10405 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10406 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10407 OutputBecomesInput); 10408 } 10409 10410 /// Mangle the parameter part of the vector function name according to 10411 /// their OpenMP classification. The mangling function is defined in 10412 /// section 3.5 of the AAVFABI. 10413 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10414 SmallString<256> Buffer; 10415 llvm::raw_svector_ostream Out(Buffer); 10416 for (const auto &ParamAttr : ParamAttrs) { 10417 switch (ParamAttr.Kind) { 10418 case LinearWithVarStride: 10419 Out << "ls" << ParamAttr.StrideOrArg; 10420 break; 10421 case Linear: 10422 Out << 'l'; 10423 // Don't print the step value if it is not present or if it is 10424 // equal to 1. 10425 if (ParamAttr.StrideOrArg != 1) 10426 Out << ParamAttr.StrideOrArg; 10427 break; 10428 case Uniform: 10429 Out << 'u'; 10430 break; 10431 case Vector: 10432 Out << 'v'; 10433 break; 10434 } 10435 10436 if (!!ParamAttr.Alignment) 10437 Out << 'a' << ParamAttr.Alignment; 10438 } 10439 10440 return std::string(Out.str()); 10441 } 10442 10443 // Function used to add the attribute. The parameter `VLEN` is 10444 // templated to allow the use of "x" when targeting scalable functions 10445 // for SVE. 10446 template <typename T> 10447 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10448 char ISA, StringRef ParSeq, 10449 StringRef MangledName, bool OutputBecomesInput, 10450 llvm::Function *Fn) { 10451 SmallString<256> Buffer; 10452 llvm::raw_svector_ostream Out(Buffer); 10453 Out << Prefix << ISA << LMask << VLEN; 10454 if (OutputBecomesInput) 10455 Out << "v"; 10456 Out << ParSeq << "_" << MangledName; 10457 Fn->addFnAttr(Out.str()); 10458 } 10459 10460 // Helper function to generate the Advanced SIMD names depending on 10461 // the value of the NDS when simdlen is not present. 10462 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10463 StringRef Prefix, char ISA, 10464 StringRef ParSeq, StringRef MangledName, 10465 bool OutputBecomesInput, 10466 llvm::Function *Fn) { 10467 switch (NDS) { 10468 case 8: 10469 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10470 OutputBecomesInput, Fn); 10471 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10472 OutputBecomesInput, Fn); 10473 break; 10474 case 16: 10475 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10476 OutputBecomesInput, Fn); 10477 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10478 OutputBecomesInput, Fn); 10479 break; 10480 case 32: 10481 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10482 OutputBecomesInput, Fn); 10483 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10484 OutputBecomesInput, Fn); 10485 break; 10486 case 64: 10487 case 128: 10488 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10489 OutputBecomesInput, Fn); 10490 break; 10491 default: 10492 llvm_unreachable("Scalar type is too wide."); 10493 } 10494 } 10495 10496 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10497 static void emitAArch64DeclareSimdFunction( 10498 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10499 ArrayRef<ParamAttrTy> ParamAttrs, 10500 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10501 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10502 10503 // Get basic data for building the vector signature. 10504 const auto Data = getNDSWDS(FD, ParamAttrs); 10505 const unsigned NDS = std::get<0>(Data); 10506 const unsigned WDS = std::get<1>(Data); 10507 const bool OutputBecomesInput = std::get<2>(Data); 10508 10509 // Check the values provided via `simdlen` by the user. 10510 // 1. A `simdlen(1)` doesn't produce vector signatures, 10511 if (UserVLEN == 1) { 10512 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10513 DiagnosticsEngine::Warning, 10514 "The clause simdlen(1) has no effect when targeting aarch64."); 10515 CGM.getDiags().Report(SLoc, DiagID); 10516 return; 10517 } 10518 10519 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10520 // Advanced SIMD output. 10521 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10522 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10523 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10524 "power of 2 when targeting Advanced SIMD."); 10525 CGM.getDiags().Report(SLoc, DiagID); 10526 return; 10527 } 10528 10529 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10530 // limits. 10531 if (ISA == 's' && UserVLEN != 0) { 10532 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10533 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10534 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10535 "lanes in the architectural constraints " 10536 "for SVE (min is 128-bit, max is " 10537 "2048-bit, by steps of 128-bit)"); 10538 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10539 return; 10540 } 10541 } 10542 10543 // Sort out parameter sequence. 10544 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10545 StringRef Prefix = "_ZGV"; 10546 // Generate simdlen from user input (if any). 10547 if (UserVLEN) { 10548 if (ISA == 's') { 10549 // SVE generates only a masked function. 10550 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10551 OutputBecomesInput, Fn); 10552 } else { 10553 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10554 // Advanced SIMD generates one or two functions, depending on 10555 // the `[not]inbranch` clause. 10556 switch (State) { 10557 case OMPDeclareSimdDeclAttr::BS_Undefined: 10558 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10559 OutputBecomesInput, Fn); 10560 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10561 OutputBecomesInput, Fn); 10562 break; 10563 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10564 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10565 OutputBecomesInput, Fn); 10566 break; 10567 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10568 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10569 OutputBecomesInput, Fn); 10570 break; 10571 } 10572 } 10573 } else { 10574 // If no user simdlen is provided, follow the AAVFABI rules for 10575 // generating the vector length. 10576 if (ISA == 's') { 10577 // SVE, section 3.4.1, item 1. 10578 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10579 OutputBecomesInput, Fn); 10580 } else { 10581 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10582 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10583 // two vector names depending on the use of the clause 10584 // `[not]inbranch`. 10585 switch (State) { 10586 case OMPDeclareSimdDeclAttr::BS_Undefined: 10587 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10588 OutputBecomesInput, Fn); 10589 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10590 OutputBecomesInput, Fn); 10591 break; 10592 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10593 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10594 OutputBecomesInput, Fn); 10595 break; 10596 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10597 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10598 OutputBecomesInput, Fn); 10599 break; 10600 } 10601 } 10602 } 10603 } 10604 10605 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10606 llvm::Function *Fn) { 10607 ASTContext &C = CGM.getContext(); 10608 FD = FD->getMostRecentDecl(); 10609 // Map params to their positions in function decl. 10610 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10611 if (isa<CXXMethodDecl>(FD)) 10612 ParamPositions.try_emplace(FD, 0); 10613 unsigned ParamPos = ParamPositions.size(); 10614 for (const ParmVarDecl *P : FD->parameters()) { 10615 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10616 ++ParamPos; 10617 } 10618 while (FD) { 10619 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10620 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10621 // Mark uniform parameters. 10622 for (const Expr *E : Attr->uniforms()) { 10623 E = E->IgnoreParenImpCasts(); 10624 unsigned Pos; 10625 if (isa<CXXThisExpr>(E)) { 10626 Pos = ParamPositions[FD]; 10627 } else { 10628 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10629 ->getCanonicalDecl(); 10630 Pos = ParamPositions[PVD]; 10631 } 10632 ParamAttrs[Pos].Kind = Uniform; 10633 } 10634 // Get alignment info. 10635 auto NI = Attr->alignments_begin(); 10636 for (const Expr *E : Attr->aligneds()) { 10637 E = E->IgnoreParenImpCasts(); 10638 unsigned Pos; 10639 QualType ParmTy; 10640 if (isa<CXXThisExpr>(E)) { 10641 Pos = ParamPositions[FD]; 10642 ParmTy = E->getType(); 10643 } else { 10644 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10645 ->getCanonicalDecl(); 10646 Pos = ParamPositions[PVD]; 10647 ParmTy = PVD->getType(); 10648 } 10649 ParamAttrs[Pos].Alignment = 10650 (*NI) 10651 ? (*NI)->EvaluateKnownConstInt(C) 10652 : llvm::APSInt::getUnsigned( 10653 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10654 .getQuantity()); 10655 ++NI; 10656 } 10657 // Mark linear parameters. 10658 auto SI = Attr->steps_begin(); 10659 auto MI = Attr->modifiers_begin(); 10660 for (const Expr *E : Attr->linears()) { 10661 E = E->IgnoreParenImpCasts(); 10662 unsigned Pos; 10663 // Rescaling factor needed to compute the linear parameter 10664 // value in the mangled name. 10665 unsigned PtrRescalingFactor = 1; 10666 if (isa<CXXThisExpr>(E)) { 10667 Pos = ParamPositions[FD]; 10668 } else { 10669 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10670 ->getCanonicalDecl(); 10671 Pos = ParamPositions[PVD]; 10672 if (auto *P = dyn_cast<PointerType>(PVD->getType())) 10673 PtrRescalingFactor = CGM.getContext() 10674 .getTypeSizeInChars(P->getPointeeType()) 10675 .getQuantity(); 10676 } 10677 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10678 ParamAttr.Kind = Linear; 10679 // Assuming a stride of 1, for `linear` without modifiers. 10680 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1); 10681 if (*SI) { 10682 Expr::EvalResult Result; 10683 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10684 if (const auto *DRE = 10685 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10686 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10687 ParamAttr.Kind = LinearWithVarStride; 10688 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10689 ParamPositions[StridePVD->getCanonicalDecl()]); 10690 } 10691 } 10692 } else { 10693 ParamAttr.StrideOrArg = Result.Val.getInt(); 10694 } 10695 } 10696 // If we are using a linear clause on a pointer, we need to 10697 // rescale the value of linear_step with the byte size of the 10698 // pointee type. 10699 if (Linear == ParamAttr.Kind) 10700 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor; 10701 ++SI; 10702 ++MI; 10703 } 10704 llvm::APSInt VLENVal; 10705 SourceLocation ExprLoc; 10706 const Expr *VLENExpr = Attr->getSimdlen(); 10707 if (VLENExpr) { 10708 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10709 ExprLoc = VLENExpr->getExprLoc(); 10710 } 10711 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10712 if (CGM.getTriple().isX86()) { 10713 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10714 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10715 unsigned VLEN = VLENVal.getExtValue(); 10716 StringRef MangledName = Fn->getName(); 10717 if (CGM.getTarget().hasFeature("sve")) 10718 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10719 MangledName, 's', 128, Fn, ExprLoc); 10720 if (CGM.getTarget().hasFeature("neon")) 10721 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10722 MangledName, 'n', 128, Fn, ExprLoc); 10723 } 10724 } 10725 FD = FD->getPreviousDecl(); 10726 } 10727 } 10728 10729 namespace { 10730 /// Cleanup action for doacross support. 10731 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10732 public: 10733 static const int DoacrossFinArgs = 2; 10734 10735 private: 10736 llvm::FunctionCallee RTLFn; 10737 llvm::Value *Args[DoacrossFinArgs]; 10738 10739 public: 10740 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10741 ArrayRef<llvm::Value *> CallArgs) 10742 : RTLFn(RTLFn) { 10743 assert(CallArgs.size() == DoacrossFinArgs); 10744 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10745 } 10746 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10747 if (!CGF.HaveInsertPoint()) 10748 return; 10749 CGF.EmitRuntimeCall(RTLFn, Args); 10750 } 10751 }; 10752 } // namespace 10753 10754 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10755 const OMPLoopDirective &D, 10756 ArrayRef<Expr *> NumIterations) { 10757 if (!CGF.HaveInsertPoint()) 10758 return; 10759 10760 ASTContext &C = CGM.getContext(); 10761 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10762 RecordDecl *RD; 10763 if (KmpDimTy.isNull()) { 10764 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10765 // kmp_int64 lo; // lower 10766 // kmp_int64 up; // upper 10767 // kmp_int64 st; // stride 10768 // }; 10769 RD = C.buildImplicitRecord("kmp_dim"); 10770 RD->startDefinition(); 10771 addFieldToRecordDecl(C, RD, Int64Ty); 10772 addFieldToRecordDecl(C, RD, Int64Ty); 10773 addFieldToRecordDecl(C, RD, Int64Ty); 10774 RD->completeDefinition(); 10775 KmpDimTy = C.getRecordType(RD); 10776 } else { 10777 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10778 } 10779 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10780 QualType ArrayTy = 10781 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 10782 10783 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10784 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10785 enum { LowerFD = 0, UpperFD, StrideFD }; 10786 // Fill dims with data. 10787 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10788 LValue DimsLVal = CGF.MakeAddrLValue( 10789 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10790 // dims.upper = num_iterations; 10791 LValue UpperLVal = CGF.EmitLValueForField( 10792 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10793 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 10794 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(), 10795 Int64Ty, NumIterations[I]->getExprLoc()); 10796 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10797 // dims.stride = 1; 10798 LValue StrideLVal = CGF.EmitLValueForField( 10799 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10800 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10801 StrideLVal); 10802 } 10803 10804 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10805 // kmp_int32 num_dims, struct kmp_dim * dims); 10806 llvm::Value *Args[] = { 10807 emitUpdateLocation(CGF, D.getBeginLoc()), 10808 getThreadID(CGF, D.getBeginLoc()), 10809 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10810 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10811 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10812 CGM.VoidPtrTy)}; 10813 10814 llvm::FunctionCallee RTLFn = 10815 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 10816 CGM.getModule(), OMPRTL___kmpc_doacross_init); 10817 CGF.EmitRuntimeCall(RTLFn, Args); 10818 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10819 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10820 llvm::FunctionCallee FiniRTLFn = 10821 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 10822 CGM.getModule(), OMPRTL___kmpc_doacross_fini); 10823 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10824 llvm::makeArrayRef(FiniArgs)); 10825 } 10826 10827 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10828 const OMPDependClause *C) { 10829 QualType Int64Ty = 10830 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10831 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10832 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10833 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 10834 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10835 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10836 const Expr *CounterVal = C->getLoopData(I); 10837 assert(CounterVal); 10838 llvm::Value *CntVal = CGF.EmitScalarConversion( 10839 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10840 CounterVal->getExprLoc()); 10841 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10842 /*Volatile=*/false, Int64Ty); 10843 } 10844 llvm::Value *Args[] = { 10845 emitUpdateLocation(CGF, C->getBeginLoc()), 10846 getThreadID(CGF, C->getBeginLoc()), 10847 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10848 llvm::FunctionCallee RTLFn; 10849 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10850 RTLFn = llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 10851 CGM.getModule(), OMPRTL___kmpc_doacross_post); 10852 } else { 10853 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10854 RTLFn = llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 10855 CGM.getModule(), OMPRTL___kmpc_doacross_wait); 10856 } 10857 CGF.EmitRuntimeCall(RTLFn, Args); 10858 } 10859 10860 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10861 llvm::FunctionCallee Callee, 10862 ArrayRef<llvm::Value *> Args) const { 10863 assert(Loc.isValid() && "Outlined function call location must be valid."); 10864 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10865 10866 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10867 if (Fn->doesNotThrow()) { 10868 CGF.EmitNounwindRuntimeCall(Fn, Args); 10869 return; 10870 } 10871 } 10872 CGF.EmitRuntimeCall(Callee, Args); 10873 } 10874 10875 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10876 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10877 ArrayRef<llvm::Value *> Args) const { 10878 emitCall(CGF, Loc, OutlinedFn, Args); 10879 } 10880 10881 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10882 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 10883 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 10884 HasEmittedDeclareTargetRegion = true; 10885 } 10886 10887 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 10888 const VarDecl *NativeParam, 10889 const VarDecl *TargetParam) const { 10890 return CGF.GetAddrOfLocalVar(NativeParam); 10891 } 10892 10893 namespace { 10894 /// Cleanup action for allocate support. 10895 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 10896 public: 10897 static const int CleanupArgs = 3; 10898 10899 private: 10900 llvm::FunctionCallee RTLFn; 10901 llvm::Value *Args[CleanupArgs]; 10902 10903 public: 10904 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 10905 ArrayRef<llvm::Value *> CallArgs) 10906 : RTLFn(RTLFn) { 10907 assert(CallArgs.size() == CleanupArgs && 10908 "Size of arguments does not match."); 10909 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10910 } 10911 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10912 if (!CGF.HaveInsertPoint()) 10913 return; 10914 CGF.EmitRuntimeCall(RTLFn, Args); 10915 } 10916 }; 10917 } // namespace 10918 10919 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 10920 const VarDecl *VD) { 10921 if (!VD) 10922 return Address::invalid(); 10923 const VarDecl *CVD = VD->getCanonicalDecl(); 10924 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 10925 return Address::invalid(); 10926 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 10927 // Use the default allocation. 10928 if ((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc || 10929 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) && 10930 !AA->getAllocator()) 10931 return Address::invalid(); 10932 llvm::Value *Size; 10933 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 10934 if (CVD->getType()->isVariablyModifiedType()) { 10935 Size = CGF.getTypeSize(CVD->getType()); 10936 // Align the size: ((size + align - 1) / align) * align 10937 Size = CGF.Builder.CreateNUWAdd( 10938 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 10939 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 10940 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 10941 } else { 10942 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 10943 Size = CGM.getSize(Sz.alignTo(Align)); 10944 } 10945 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 10946 assert(AA->getAllocator() && 10947 "Expected allocator expression for non-default allocator."); 10948 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 10949 // According to the standard, the original allocator type is a enum (integer). 10950 // Convert to pointer type, if required. 10951 if (Allocator->getType()->isIntegerTy()) 10952 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 10953 else if (Allocator->getType()->isPointerTy()) 10954 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 10955 CGM.VoidPtrTy); 10956 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 10957 10958 llvm::Value *Addr = 10959 CGF.EmitRuntimeCall(llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction( 10960 CGM.getModule(), OMPRTL___kmpc_alloc), 10961 Args, getName({CVD->getName(), ".void.addr"})); 10962 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 10963 Allocator}; 10964 llvm::FunctionCallee FiniRTLFn = 10965 llvm::OpenMPIRBuilder::getOrCreateRuntimeFunction(CGM.getModule(), 10966 OMPRTL___kmpc_free); 10967 10968 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10969 llvm::makeArrayRef(FiniArgs)); 10970 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10971 Addr, 10972 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 10973 getName({CVD->getName(), ".addr"})); 10974 return Address(Addr, Align); 10975 } 10976 10977 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 10978 CodeGenModule &CGM, const OMPLoopDirective &S) 10979 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 10980 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 10981 if (!NeedToPush) 10982 return; 10983 NontemporalDeclsSet &DS = 10984 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 10985 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 10986 for (const Stmt *Ref : C->private_refs()) { 10987 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 10988 const ValueDecl *VD; 10989 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 10990 VD = DRE->getDecl(); 10991 } else { 10992 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 10993 assert((ME->isImplicitCXXThis() || 10994 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 10995 "Expected member of current class."); 10996 VD = ME->getMemberDecl(); 10997 } 10998 DS.insert(VD); 10999 } 11000 } 11001 } 11002 11003 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 11004 if (!NeedToPush) 11005 return; 11006 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 11007 } 11008 11009 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 11010 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11011 11012 return llvm::any_of( 11013 CGM.getOpenMPRuntime().NontemporalDeclsStack, 11014 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 11015 } 11016 11017 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 11018 const OMPExecutableDirective &S, 11019 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 11020 const { 11021 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 11022 // Vars in target/task regions must be excluded completely. 11023 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 11024 isOpenMPTaskingDirective(S.getDirectiveKind())) { 11025 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11026 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 11027 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 11028 for (const CapturedStmt::Capture &Cap : CS->captures()) { 11029 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 11030 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 11031 } 11032 } 11033 // Exclude vars in private clauses. 11034 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 11035 for (const Expr *Ref : C->varlists()) { 11036 if (!Ref->getType()->isScalarType()) 11037 continue; 11038 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11039 if (!DRE) 11040 continue; 11041 NeedToCheckForLPCs.insert(DRE->getDecl()); 11042 } 11043 } 11044 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 11045 for (const Expr *Ref : C->varlists()) { 11046 if (!Ref->getType()->isScalarType()) 11047 continue; 11048 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11049 if (!DRE) 11050 continue; 11051 NeedToCheckForLPCs.insert(DRE->getDecl()); 11052 } 11053 } 11054 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11055 for (const Expr *Ref : C->varlists()) { 11056 if (!Ref->getType()->isScalarType()) 11057 continue; 11058 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11059 if (!DRE) 11060 continue; 11061 NeedToCheckForLPCs.insert(DRE->getDecl()); 11062 } 11063 } 11064 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 11065 for (const Expr *Ref : C->varlists()) { 11066 if (!Ref->getType()->isScalarType()) 11067 continue; 11068 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11069 if (!DRE) 11070 continue; 11071 NeedToCheckForLPCs.insert(DRE->getDecl()); 11072 } 11073 } 11074 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 11075 for (const Expr *Ref : C->varlists()) { 11076 if (!Ref->getType()->isScalarType()) 11077 continue; 11078 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11079 if (!DRE) 11080 continue; 11081 NeedToCheckForLPCs.insert(DRE->getDecl()); 11082 } 11083 } 11084 for (const Decl *VD : NeedToCheckForLPCs) { 11085 for (const LastprivateConditionalData &Data : 11086 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 11087 if (Data.DeclToUniqueName.count(VD) > 0) { 11088 if (!Data.Disabled) 11089 NeedToAddForLPCsAsDisabled.insert(VD); 11090 break; 11091 } 11092 } 11093 } 11094 } 11095 11096 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11097 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 11098 : CGM(CGF.CGM), 11099 Action((CGM.getLangOpts().OpenMP >= 50 && 11100 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 11101 [](const OMPLastprivateClause *C) { 11102 return C->getKind() == 11103 OMPC_LASTPRIVATE_conditional; 11104 })) 11105 ? ActionToDo::PushAsLastprivateConditional 11106 : ActionToDo::DoNotPush) { 11107 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11108 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 11109 return; 11110 assert(Action == ActionToDo::PushAsLastprivateConditional && 11111 "Expected a push action."); 11112 LastprivateConditionalData &Data = 11113 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11114 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11115 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 11116 continue; 11117 11118 for (const Expr *Ref : C->varlists()) { 11119 Data.DeclToUniqueName.insert(std::make_pair( 11120 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 11121 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 11122 } 11123 } 11124 Data.IVLVal = IVLVal; 11125 Data.Fn = CGF.CurFn; 11126 } 11127 11128 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11129 CodeGenFunction &CGF, const OMPExecutableDirective &S) 11130 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 11131 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11132 if (CGM.getLangOpts().OpenMP < 50) 11133 return; 11134 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 11135 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 11136 if (!NeedToAddForLPCsAsDisabled.empty()) { 11137 Action = ActionToDo::DisableLastprivateConditional; 11138 LastprivateConditionalData &Data = 11139 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11140 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 11141 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 11142 Data.Fn = CGF.CurFn; 11143 Data.Disabled = true; 11144 } 11145 } 11146 11147 CGOpenMPRuntime::LastprivateConditionalRAII 11148 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 11149 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 11150 return LastprivateConditionalRAII(CGF, S); 11151 } 11152 11153 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 11154 if (CGM.getLangOpts().OpenMP < 50) 11155 return; 11156 if (Action == ActionToDo::DisableLastprivateConditional) { 11157 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11158 "Expected list of disabled private vars."); 11159 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11160 } 11161 if (Action == ActionToDo::PushAsLastprivateConditional) { 11162 assert( 11163 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11164 "Expected list of lastprivate conditional vars."); 11165 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11166 } 11167 } 11168 11169 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 11170 const VarDecl *VD) { 11171 ASTContext &C = CGM.getContext(); 11172 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 11173 if (I == LastprivateConditionalToTypes.end()) 11174 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 11175 QualType NewType; 11176 const FieldDecl *VDField; 11177 const FieldDecl *FiredField; 11178 LValue BaseLVal; 11179 auto VI = I->getSecond().find(VD); 11180 if (VI == I->getSecond().end()) { 11181 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 11182 RD->startDefinition(); 11183 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 11184 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 11185 RD->completeDefinition(); 11186 NewType = C.getRecordType(RD); 11187 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 11188 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 11189 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 11190 } else { 11191 NewType = std::get<0>(VI->getSecond()); 11192 VDField = std::get<1>(VI->getSecond()); 11193 FiredField = std::get<2>(VI->getSecond()); 11194 BaseLVal = std::get<3>(VI->getSecond()); 11195 } 11196 LValue FiredLVal = 11197 CGF.EmitLValueForField(BaseLVal, FiredField); 11198 CGF.EmitStoreOfScalar( 11199 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 11200 FiredLVal); 11201 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 11202 } 11203 11204 namespace { 11205 /// Checks if the lastprivate conditional variable is referenced in LHS. 11206 class LastprivateConditionalRefChecker final 11207 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 11208 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 11209 const Expr *FoundE = nullptr; 11210 const Decl *FoundD = nullptr; 11211 StringRef UniqueDeclName; 11212 LValue IVLVal; 11213 llvm::Function *FoundFn = nullptr; 11214 SourceLocation Loc; 11215 11216 public: 11217 bool VisitDeclRefExpr(const DeclRefExpr *E) { 11218 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11219 llvm::reverse(LPM)) { 11220 auto It = D.DeclToUniqueName.find(E->getDecl()); 11221 if (It == D.DeclToUniqueName.end()) 11222 continue; 11223 if (D.Disabled) 11224 return false; 11225 FoundE = E; 11226 FoundD = E->getDecl()->getCanonicalDecl(); 11227 UniqueDeclName = It->second; 11228 IVLVal = D.IVLVal; 11229 FoundFn = D.Fn; 11230 break; 11231 } 11232 return FoundE == E; 11233 } 11234 bool VisitMemberExpr(const MemberExpr *E) { 11235 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 11236 return false; 11237 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11238 llvm::reverse(LPM)) { 11239 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 11240 if (It == D.DeclToUniqueName.end()) 11241 continue; 11242 if (D.Disabled) 11243 return false; 11244 FoundE = E; 11245 FoundD = E->getMemberDecl()->getCanonicalDecl(); 11246 UniqueDeclName = It->second; 11247 IVLVal = D.IVLVal; 11248 FoundFn = D.Fn; 11249 break; 11250 } 11251 return FoundE == E; 11252 } 11253 bool VisitStmt(const Stmt *S) { 11254 for (const Stmt *Child : S->children()) { 11255 if (!Child) 11256 continue; 11257 if (const auto *E = dyn_cast<Expr>(Child)) 11258 if (!E->isGLValue()) 11259 continue; 11260 if (Visit(Child)) 11261 return true; 11262 } 11263 return false; 11264 } 11265 explicit LastprivateConditionalRefChecker( 11266 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 11267 : LPM(LPM) {} 11268 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 11269 getFoundData() const { 11270 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 11271 } 11272 }; 11273 } // namespace 11274 11275 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 11276 LValue IVLVal, 11277 StringRef UniqueDeclName, 11278 LValue LVal, 11279 SourceLocation Loc) { 11280 // Last updated loop counter for the lastprivate conditional var. 11281 // int<xx> last_iv = 0; 11282 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 11283 llvm::Constant *LastIV = 11284 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 11285 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 11286 IVLVal.getAlignment().getAsAlign()); 11287 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 11288 11289 // Last value of the lastprivate conditional. 11290 // decltype(priv_a) last_a; 11291 llvm::Constant *Last = getOrCreateInternalVariable( 11292 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 11293 cast<llvm::GlobalVariable>(Last)->setAlignment( 11294 LVal.getAlignment().getAsAlign()); 11295 LValue LastLVal = 11296 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 11297 11298 // Global loop counter. Required to handle inner parallel-for regions. 11299 // iv 11300 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 11301 11302 // #pragma omp critical(a) 11303 // if (last_iv <= iv) { 11304 // last_iv = iv; 11305 // last_a = priv_a; 11306 // } 11307 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 11308 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 11309 Action.Enter(CGF); 11310 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 11311 // (last_iv <= iv) ? Check if the variable is updated and store new 11312 // value in global var. 11313 llvm::Value *CmpRes; 11314 if (IVLVal.getType()->isSignedIntegerType()) { 11315 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 11316 } else { 11317 assert(IVLVal.getType()->isUnsignedIntegerType() && 11318 "Loop iteration variable must be integer."); 11319 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 11320 } 11321 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 11322 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 11323 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 11324 // { 11325 CGF.EmitBlock(ThenBB); 11326 11327 // last_iv = iv; 11328 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 11329 11330 // last_a = priv_a; 11331 switch (CGF.getEvaluationKind(LVal.getType())) { 11332 case TEK_Scalar: { 11333 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 11334 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 11335 break; 11336 } 11337 case TEK_Complex: { 11338 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 11339 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 11340 break; 11341 } 11342 case TEK_Aggregate: 11343 llvm_unreachable( 11344 "Aggregates are not supported in lastprivate conditional."); 11345 } 11346 // } 11347 CGF.EmitBranch(ExitBB); 11348 // There is no need to emit line number for unconditional branch. 11349 (void)ApplyDebugLocation::CreateEmpty(CGF); 11350 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 11351 }; 11352 11353 if (CGM.getLangOpts().OpenMPSimd) { 11354 // Do not emit as a critical region as no parallel region could be emitted. 11355 RegionCodeGenTy ThenRCG(CodeGen); 11356 ThenRCG(CGF); 11357 } else { 11358 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 11359 } 11360 } 11361 11362 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 11363 const Expr *LHS) { 11364 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11365 return; 11366 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 11367 if (!Checker.Visit(LHS)) 11368 return; 11369 const Expr *FoundE; 11370 const Decl *FoundD; 11371 StringRef UniqueDeclName; 11372 LValue IVLVal; 11373 llvm::Function *FoundFn; 11374 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 11375 Checker.getFoundData(); 11376 if (FoundFn != CGF.CurFn) { 11377 // Special codegen for inner parallel regions. 11378 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 11379 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 11380 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 11381 "Lastprivate conditional is not found in outer region."); 11382 QualType StructTy = std::get<0>(It->getSecond()); 11383 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 11384 LValue PrivLVal = CGF.EmitLValue(FoundE); 11385 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11386 PrivLVal.getAddress(CGF), 11387 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 11388 LValue BaseLVal = 11389 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 11390 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 11391 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 11392 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 11393 FiredLVal, llvm::AtomicOrdering::Unordered, 11394 /*IsVolatile=*/true, /*isInit=*/false); 11395 return; 11396 } 11397 11398 // Private address of the lastprivate conditional in the current context. 11399 // priv_a 11400 LValue LVal = CGF.EmitLValue(FoundE); 11401 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 11402 FoundE->getExprLoc()); 11403 } 11404 11405 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 11406 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11407 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 11408 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11409 return; 11410 auto Range = llvm::reverse(LastprivateConditionalStack); 11411 auto It = llvm::find_if( 11412 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 11413 if (It == Range.end() || It->Fn != CGF.CurFn) 11414 return; 11415 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 11416 assert(LPCI != LastprivateConditionalToTypes.end() && 11417 "Lastprivates must be registered already."); 11418 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11419 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 11420 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 11421 for (const auto &Pair : It->DeclToUniqueName) { 11422 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 11423 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 11424 continue; 11425 auto I = LPCI->getSecond().find(Pair.first); 11426 assert(I != LPCI->getSecond().end() && 11427 "Lastprivate must be rehistered already."); 11428 // bool Cmp = priv_a.Fired != 0; 11429 LValue BaseLVal = std::get<3>(I->getSecond()); 11430 LValue FiredLVal = 11431 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 11432 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 11433 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 11434 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 11435 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 11436 // if (Cmp) { 11437 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 11438 CGF.EmitBlock(ThenBB); 11439 Address Addr = CGF.GetAddrOfLocalVar(VD); 11440 LValue LVal; 11441 if (VD->getType()->isReferenceType()) 11442 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 11443 AlignmentSource::Decl); 11444 else 11445 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 11446 AlignmentSource::Decl); 11447 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 11448 D.getBeginLoc()); 11449 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 11450 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 11451 // } 11452 } 11453 } 11454 11455 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 11456 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 11457 SourceLocation Loc) { 11458 if (CGF.getLangOpts().OpenMP < 50) 11459 return; 11460 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 11461 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 11462 "Unknown lastprivate conditional variable."); 11463 StringRef UniqueName = It->second; 11464 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 11465 // The variable was not updated in the region - exit. 11466 if (!GV) 11467 return; 11468 LValue LPLVal = CGF.MakeAddrLValue( 11469 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 11470 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 11471 CGF.EmitStoreOfScalar(Res, PrivLVal); 11472 } 11473 11474 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11475 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11476 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11477 llvm_unreachable("Not supported in SIMD-only mode"); 11478 } 11479 11480 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11481 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11482 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11483 llvm_unreachable("Not supported in SIMD-only mode"); 11484 } 11485 11486 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11487 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11488 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11489 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11490 bool Tied, unsigned &NumberOfParts) { 11491 llvm_unreachable("Not supported in SIMD-only mode"); 11492 } 11493 11494 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11495 SourceLocation Loc, 11496 llvm::Function *OutlinedFn, 11497 ArrayRef<llvm::Value *> CapturedVars, 11498 const Expr *IfCond) { 11499 llvm_unreachable("Not supported in SIMD-only mode"); 11500 } 11501 11502 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11503 CodeGenFunction &CGF, StringRef CriticalName, 11504 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11505 const Expr *Hint) { 11506 llvm_unreachable("Not supported in SIMD-only mode"); 11507 } 11508 11509 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11510 const RegionCodeGenTy &MasterOpGen, 11511 SourceLocation Loc) { 11512 llvm_unreachable("Not supported in SIMD-only mode"); 11513 } 11514 11515 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11516 SourceLocation Loc) { 11517 llvm_unreachable("Not supported in SIMD-only mode"); 11518 } 11519 11520 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11521 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11522 SourceLocation Loc) { 11523 llvm_unreachable("Not supported in SIMD-only mode"); 11524 } 11525 11526 void CGOpenMPSIMDRuntime::emitSingleRegion( 11527 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11528 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11529 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11530 ArrayRef<const Expr *> AssignmentOps) { 11531 llvm_unreachable("Not supported in SIMD-only mode"); 11532 } 11533 11534 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11535 const RegionCodeGenTy &OrderedOpGen, 11536 SourceLocation Loc, 11537 bool IsThreads) { 11538 llvm_unreachable("Not supported in SIMD-only mode"); 11539 } 11540 11541 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11542 SourceLocation Loc, 11543 OpenMPDirectiveKind Kind, 11544 bool EmitChecks, 11545 bool ForceSimpleCall) { 11546 llvm_unreachable("Not supported in SIMD-only mode"); 11547 } 11548 11549 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11550 CodeGenFunction &CGF, SourceLocation Loc, 11551 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11552 bool Ordered, const DispatchRTInput &DispatchValues) { 11553 llvm_unreachable("Not supported in SIMD-only mode"); 11554 } 11555 11556 void CGOpenMPSIMDRuntime::emitForStaticInit( 11557 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11558 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11559 llvm_unreachable("Not supported in SIMD-only mode"); 11560 } 11561 11562 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11563 CodeGenFunction &CGF, SourceLocation Loc, 11564 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11565 llvm_unreachable("Not supported in SIMD-only mode"); 11566 } 11567 11568 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11569 SourceLocation Loc, 11570 unsigned IVSize, 11571 bool IVSigned) { 11572 llvm_unreachable("Not supported in SIMD-only mode"); 11573 } 11574 11575 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11576 SourceLocation Loc, 11577 OpenMPDirectiveKind DKind) { 11578 llvm_unreachable("Not supported in SIMD-only mode"); 11579 } 11580 11581 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11582 SourceLocation Loc, 11583 unsigned IVSize, bool IVSigned, 11584 Address IL, Address LB, 11585 Address UB, Address ST) { 11586 llvm_unreachable("Not supported in SIMD-only mode"); 11587 } 11588 11589 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11590 llvm::Value *NumThreads, 11591 SourceLocation Loc) { 11592 llvm_unreachable("Not supported in SIMD-only mode"); 11593 } 11594 11595 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11596 ProcBindKind ProcBind, 11597 SourceLocation Loc) { 11598 llvm_unreachable("Not supported in SIMD-only mode"); 11599 } 11600 11601 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11602 const VarDecl *VD, 11603 Address VDAddr, 11604 SourceLocation Loc) { 11605 llvm_unreachable("Not supported in SIMD-only mode"); 11606 } 11607 11608 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11609 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11610 CodeGenFunction *CGF) { 11611 llvm_unreachable("Not supported in SIMD-only mode"); 11612 } 11613 11614 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11615 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11616 llvm_unreachable("Not supported in SIMD-only mode"); 11617 } 11618 11619 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11620 ArrayRef<const Expr *> Vars, 11621 SourceLocation Loc, 11622 llvm::AtomicOrdering AO) { 11623 llvm_unreachable("Not supported in SIMD-only mode"); 11624 } 11625 11626 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11627 const OMPExecutableDirective &D, 11628 llvm::Function *TaskFunction, 11629 QualType SharedsTy, Address Shareds, 11630 const Expr *IfCond, 11631 const OMPTaskDataTy &Data) { 11632 llvm_unreachable("Not supported in SIMD-only mode"); 11633 } 11634 11635 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11636 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11637 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11638 const Expr *IfCond, const OMPTaskDataTy &Data) { 11639 llvm_unreachable("Not supported in SIMD-only mode"); 11640 } 11641 11642 void CGOpenMPSIMDRuntime::emitReduction( 11643 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11644 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11645 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11646 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11647 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 11648 ReductionOps, Options); 11649 } 11650 11651 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 11652 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 11653 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 11654 llvm_unreachable("Not supported in SIMD-only mode"); 11655 } 11656 11657 void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 11658 SourceLocation Loc, 11659 bool IsWorksharingReduction) { 11660 llvm_unreachable("Not supported in SIMD-only mode"); 11661 } 11662 11663 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 11664 SourceLocation Loc, 11665 ReductionCodeGen &RCG, 11666 unsigned N) { 11667 llvm_unreachable("Not supported in SIMD-only mode"); 11668 } 11669 11670 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 11671 SourceLocation Loc, 11672 llvm::Value *ReductionsPtr, 11673 LValue SharedLVal) { 11674 llvm_unreachable("Not supported in SIMD-only mode"); 11675 } 11676 11677 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 11678 SourceLocation Loc) { 11679 llvm_unreachable("Not supported in SIMD-only mode"); 11680 } 11681 11682 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 11683 CodeGenFunction &CGF, SourceLocation Loc, 11684 OpenMPDirectiveKind CancelRegion) { 11685 llvm_unreachable("Not supported in SIMD-only mode"); 11686 } 11687 11688 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 11689 SourceLocation Loc, const Expr *IfCond, 11690 OpenMPDirectiveKind CancelRegion) { 11691 llvm_unreachable("Not supported in SIMD-only mode"); 11692 } 11693 11694 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 11695 const OMPExecutableDirective &D, StringRef ParentName, 11696 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 11697 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 11698 llvm_unreachable("Not supported in SIMD-only mode"); 11699 } 11700 11701 void CGOpenMPSIMDRuntime::emitTargetCall( 11702 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11703 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 11704 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 11705 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 11706 const OMPLoopDirective &D)> 11707 SizeEmitter) { 11708 llvm_unreachable("Not supported in SIMD-only mode"); 11709 } 11710 11711 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 11712 llvm_unreachable("Not supported in SIMD-only mode"); 11713 } 11714 11715 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 11716 llvm_unreachable("Not supported in SIMD-only mode"); 11717 } 11718 11719 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 11720 return false; 11721 } 11722 11723 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 11724 const OMPExecutableDirective &D, 11725 SourceLocation Loc, 11726 llvm::Function *OutlinedFn, 11727 ArrayRef<llvm::Value *> CapturedVars) { 11728 llvm_unreachable("Not supported in SIMD-only mode"); 11729 } 11730 11731 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11732 const Expr *NumTeams, 11733 const Expr *ThreadLimit, 11734 SourceLocation Loc) { 11735 llvm_unreachable("Not supported in SIMD-only mode"); 11736 } 11737 11738 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 11739 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11740 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11741 llvm_unreachable("Not supported in SIMD-only mode"); 11742 } 11743 11744 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 11745 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11746 const Expr *Device) { 11747 llvm_unreachable("Not supported in SIMD-only mode"); 11748 } 11749 11750 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11751 const OMPLoopDirective &D, 11752 ArrayRef<Expr *> NumIterations) { 11753 llvm_unreachable("Not supported in SIMD-only mode"); 11754 } 11755 11756 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11757 const OMPDependClause *C) { 11758 llvm_unreachable("Not supported in SIMD-only mode"); 11759 } 11760 11761 const VarDecl * 11762 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 11763 const VarDecl *NativeParam) const { 11764 llvm_unreachable("Not supported in SIMD-only mode"); 11765 } 11766 11767 Address 11768 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 11769 const VarDecl *NativeParam, 11770 const VarDecl *TargetParam) const { 11771 llvm_unreachable("Not supported in SIMD-only mode"); 11772 } 11773