1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides a class for OpenMP runtime code generation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGOpenMPRuntime.h" 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/AST/Attr.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/OpenMPClause.h" 21 #include "clang/AST/StmtOpenMP.h" 22 #include "clang/AST/StmtVisitor.h" 23 #include "clang/Basic/BitmaskEnum.h" 24 #include "clang/Basic/FileManager.h" 25 #include "clang/Basic/OpenMPKinds.h" 26 #include "clang/Basic/SourceManager.h" 27 #include "clang/CodeGen/ConstantInitBuilder.h" 28 #include "llvm/ADT/ArrayRef.h" 29 #include "llvm/ADT/SetOperations.h" 30 #include "llvm/ADT/StringExtras.h" 31 #include "llvm/Bitcode/BitcodeReader.h" 32 #include "llvm/IR/Constants.h" 33 #include "llvm/IR/DerivedTypes.h" 34 #include "llvm/IR/GlobalValue.h" 35 #include "llvm/IR/Value.h" 36 #include "llvm/Support/AtomicOrdering.h" 37 #include "llvm/Support/Format.h" 38 #include "llvm/Support/raw_ostream.h" 39 #include <cassert> 40 #include <numeric> 41 42 using namespace clang; 43 using namespace CodeGen; 44 using namespace llvm::omp; 45 46 namespace { 47 /// Base class for handling code generation inside OpenMP regions. 48 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 49 public: 50 /// Kinds of OpenMP regions used in codegen. 51 enum CGOpenMPRegionKind { 52 /// Region with outlined function for standalone 'parallel' 53 /// directive. 54 ParallelOutlinedRegion, 55 /// Region with outlined function for standalone 'task' directive. 56 TaskOutlinedRegion, 57 /// Region for constructs that do not require function outlining, 58 /// like 'for', 'sections', 'atomic' etc. directives. 59 InlinedRegion, 60 /// Region with outlined function for standalone 'target' directive. 61 TargetRegion, 62 }; 63 64 CGOpenMPRegionInfo(const CapturedStmt &CS, 65 const CGOpenMPRegionKind RegionKind, 66 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 67 bool HasCancel) 68 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 69 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 70 71 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 72 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 73 bool HasCancel) 74 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 75 Kind(Kind), HasCancel(HasCancel) {} 76 77 /// Get a variable or parameter for storing global thread id 78 /// inside OpenMP construct. 79 virtual const VarDecl *getThreadIDVariable() const = 0; 80 81 /// Emit the captured statement body. 82 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 83 84 /// Get an LValue for the current ThreadID variable. 85 /// \return LValue for thread id variable. This LValue always has type int32*. 86 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 87 88 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 89 90 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 91 92 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 93 94 bool hasCancel() const { return HasCancel; } 95 96 static bool classof(const CGCapturedStmtInfo *Info) { 97 return Info->getKind() == CR_OpenMP; 98 } 99 100 ~CGOpenMPRegionInfo() override = default; 101 102 protected: 103 CGOpenMPRegionKind RegionKind; 104 RegionCodeGenTy CodeGen; 105 OpenMPDirectiveKind Kind; 106 bool HasCancel; 107 }; 108 109 /// API for captured statement code generation in OpenMP constructs. 110 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 111 public: 112 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 113 const RegionCodeGenTy &CodeGen, 114 OpenMPDirectiveKind Kind, bool HasCancel, 115 StringRef HelperName) 116 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 117 HasCancel), 118 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 119 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 120 } 121 122 /// Get a variable or parameter for storing global thread id 123 /// inside OpenMP construct. 124 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 125 126 /// Get the name of the capture helper. 127 StringRef getHelperName() const override { return HelperName; } 128 129 static bool classof(const CGCapturedStmtInfo *Info) { 130 return CGOpenMPRegionInfo::classof(Info) && 131 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 132 ParallelOutlinedRegion; 133 } 134 135 private: 136 /// A variable or parameter storing global thread id for OpenMP 137 /// constructs. 138 const VarDecl *ThreadIDVar; 139 StringRef HelperName; 140 }; 141 142 /// API for captured statement code generation in OpenMP constructs. 143 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 144 public: 145 class UntiedTaskActionTy final : public PrePostActionTy { 146 bool Untied; 147 const VarDecl *PartIDVar; 148 const RegionCodeGenTy UntiedCodeGen; 149 llvm::SwitchInst *UntiedSwitch = nullptr; 150 151 public: 152 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 153 const RegionCodeGenTy &UntiedCodeGen) 154 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 155 void Enter(CodeGenFunction &CGF) override { 156 if (Untied) { 157 // Emit task switching point. 158 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 159 CGF.GetAddrOfLocalVar(PartIDVar), 160 PartIDVar->getType()->castAs<PointerType>()); 161 llvm::Value *Res = 162 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 163 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 164 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 165 CGF.EmitBlock(DoneBB); 166 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 167 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 168 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 169 CGF.Builder.GetInsertBlock()); 170 emitUntiedSwitch(CGF); 171 } 172 } 173 void emitUntiedSwitch(CodeGenFunction &CGF) const { 174 if (Untied) { 175 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 176 CGF.GetAddrOfLocalVar(PartIDVar), 177 PartIDVar->getType()->castAs<PointerType>()); 178 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 179 PartIdLVal); 180 UntiedCodeGen(CGF); 181 CodeGenFunction::JumpDest CurPoint = 182 CGF.getJumpDestInCurrentScope(".untied.next."); 183 CGF.EmitBranch(CGF.ReturnBlock.getBlock()); 184 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 185 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 186 CGF.Builder.GetInsertBlock()); 187 CGF.EmitBranchThroughCleanup(CurPoint); 188 CGF.EmitBlock(CurPoint.getBlock()); 189 } 190 } 191 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 192 }; 193 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 194 const VarDecl *ThreadIDVar, 195 const RegionCodeGenTy &CodeGen, 196 OpenMPDirectiveKind Kind, bool HasCancel, 197 const UntiedTaskActionTy &Action) 198 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 199 ThreadIDVar(ThreadIDVar), Action(Action) { 200 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 201 } 202 203 /// Get a variable or parameter for storing global thread id 204 /// inside OpenMP construct. 205 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 206 207 /// Get an LValue for the current ThreadID variable. 208 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 209 210 /// Get the name of the capture helper. 211 StringRef getHelperName() const override { return ".omp_outlined."; } 212 213 void emitUntiedSwitch(CodeGenFunction &CGF) override { 214 Action.emitUntiedSwitch(CGF); 215 } 216 217 static bool classof(const CGCapturedStmtInfo *Info) { 218 return CGOpenMPRegionInfo::classof(Info) && 219 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 220 TaskOutlinedRegion; 221 } 222 223 private: 224 /// A variable or parameter storing global thread id for OpenMP 225 /// constructs. 226 const VarDecl *ThreadIDVar; 227 /// Action for emitting code for untied tasks. 228 const UntiedTaskActionTy &Action; 229 }; 230 231 /// API for inlined captured statement code generation in OpenMP 232 /// constructs. 233 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 234 public: 235 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 236 const RegionCodeGenTy &CodeGen, 237 OpenMPDirectiveKind Kind, bool HasCancel) 238 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 239 OldCSI(OldCSI), 240 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 241 242 // Retrieve the value of the context parameter. 243 llvm::Value *getContextValue() const override { 244 if (OuterRegionInfo) 245 return OuterRegionInfo->getContextValue(); 246 llvm_unreachable("No context value for inlined OpenMP region"); 247 } 248 249 void setContextValue(llvm::Value *V) override { 250 if (OuterRegionInfo) { 251 OuterRegionInfo->setContextValue(V); 252 return; 253 } 254 llvm_unreachable("No context value for inlined OpenMP region"); 255 } 256 257 /// Lookup the captured field decl for a variable. 258 const FieldDecl *lookup(const VarDecl *VD) const override { 259 if (OuterRegionInfo) 260 return OuterRegionInfo->lookup(VD); 261 // If there is no outer outlined region,no need to lookup in a list of 262 // captured variables, we can use the original one. 263 return nullptr; 264 } 265 266 FieldDecl *getThisFieldDecl() const override { 267 if (OuterRegionInfo) 268 return OuterRegionInfo->getThisFieldDecl(); 269 return nullptr; 270 } 271 272 /// Get a variable or parameter for storing global thread id 273 /// inside OpenMP construct. 274 const VarDecl *getThreadIDVariable() const override { 275 if (OuterRegionInfo) 276 return OuterRegionInfo->getThreadIDVariable(); 277 return nullptr; 278 } 279 280 /// Get an LValue for the current ThreadID variable. 281 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 282 if (OuterRegionInfo) 283 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 284 llvm_unreachable("No LValue for inlined OpenMP construct"); 285 } 286 287 /// Get the name of the capture helper. 288 StringRef getHelperName() const override { 289 if (auto *OuterRegionInfo = getOldCSI()) 290 return OuterRegionInfo->getHelperName(); 291 llvm_unreachable("No helper name for inlined OpenMP construct"); 292 } 293 294 void emitUntiedSwitch(CodeGenFunction &CGF) override { 295 if (OuterRegionInfo) 296 OuterRegionInfo->emitUntiedSwitch(CGF); 297 } 298 299 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 300 301 static bool classof(const CGCapturedStmtInfo *Info) { 302 return CGOpenMPRegionInfo::classof(Info) && 303 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 304 } 305 306 ~CGOpenMPInlinedRegionInfo() override = default; 307 308 private: 309 /// CodeGen info about outer OpenMP region. 310 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 311 CGOpenMPRegionInfo *OuterRegionInfo; 312 }; 313 314 /// API for captured statement code generation in OpenMP target 315 /// constructs. For this captures, implicit parameters are used instead of the 316 /// captured fields. The name of the target region has to be unique in a given 317 /// application so it is provided by the client, because only the client has 318 /// the information to generate that. 319 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 320 public: 321 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 322 const RegionCodeGenTy &CodeGen, StringRef HelperName) 323 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 324 /*HasCancel=*/false), 325 HelperName(HelperName) {} 326 327 /// This is unused for target regions because each starts executing 328 /// with a single thread. 329 const VarDecl *getThreadIDVariable() const override { return nullptr; } 330 331 /// Get the name of the capture helper. 332 StringRef getHelperName() const override { return HelperName; } 333 334 static bool classof(const CGCapturedStmtInfo *Info) { 335 return CGOpenMPRegionInfo::classof(Info) && 336 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 337 } 338 339 private: 340 StringRef HelperName; 341 }; 342 343 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 344 llvm_unreachable("No codegen for expressions"); 345 } 346 /// API for generation of expressions captured in a innermost OpenMP 347 /// region. 348 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 349 public: 350 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 351 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 352 OMPD_unknown, 353 /*HasCancel=*/false), 354 PrivScope(CGF) { 355 // Make sure the globals captured in the provided statement are local by 356 // using the privatization logic. We assume the same variable is not 357 // captured more than once. 358 for (const auto &C : CS.captures()) { 359 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 360 continue; 361 362 const VarDecl *VD = C.getCapturedVar(); 363 if (VD->isLocalVarDeclOrParm()) 364 continue; 365 366 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 367 /*RefersToEnclosingVariableOrCapture=*/false, 368 VD->getType().getNonReferenceType(), VK_LValue, 369 C.getLocation()); 370 PrivScope.addPrivate( 371 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 372 } 373 (void)PrivScope.Privatize(); 374 } 375 376 /// Lookup the captured field decl for a variable. 377 const FieldDecl *lookup(const VarDecl *VD) const override { 378 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 379 return FD; 380 return nullptr; 381 } 382 383 /// Emit the captured statement body. 384 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 385 llvm_unreachable("No body for expressions"); 386 } 387 388 /// Get a variable or parameter for storing global thread id 389 /// inside OpenMP construct. 390 const VarDecl *getThreadIDVariable() const override { 391 llvm_unreachable("No thread id for expressions"); 392 } 393 394 /// Get the name of the capture helper. 395 StringRef getHelperName() const override { 396 llvm_unreachable("No helper name for expressions"); 397 } 398 399 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 400 401 private: 402 /// Private scope to capture global variables. 403 CodeGenFunction::OMPPrivateScope PrivScope; 404 }; 405 406 /// RAII for emitting code of OpenMP constructs. 407 class InlinedOpenMPRegionRAII { 408 CodeGenFunction &CGF; 409 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 410 FieldDecl *LambdaThisCaptureField = nullptr; 411 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 412 413 public: 414 /// Constructs region for combined constructs. 415 /// \param CodeGen Code generation sequence for combined directives. Includes 416 /// a list of functions used for code generation of implicitly inlined 417 /// regions. 418 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 419 OpenMPDirectiveKind Kind, bool HasCancel) 420 : CGF(CGF) { 421 // Start emission for the construct. 422 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 423 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 424 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 425 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 426 CGF.LambdaThisCaptureField = nullptr; 427 BlockInfo = CGF.BlockInfo; 428 CGF.BlockInfo = nullptr; 429 } 430 431 ~InlinedOpenMPRegionRAII() { 432 // Restore original CapturedStmtInfo only if we're done with code emission. 433 auto *OldCSI = 434 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 435 delete CGF.CapturedStmtInfo; 436 CGF.CapturedStmtInfo = OldCSI; 437 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 438 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 439 CGF.BlockInfo = BlockInfo; 440 } 441 }; 442 443 /// Values for bit flags used in the ident_t to describe the fields. 444 /// All enumeric elements are named and described in accordance with the code 445 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 446 enum OpenMPLocationFlags : unsigned { 447 /// Use trampoline for internal microtask. 448 OMP_IDENT_IMD = 0x01, 449 /// Use c-style ident structure. 450 OMP_IDENT_KMPC = 0x02, 451 /// Atomic reduction option for kmpc_reduce. 452 OMP_ATOMIC_REDUCE = 0x10, 453 /// Explicit 'barrier' directive. 454 OMP_IDENT_BARRIER_EXPL = 0x20, 455 /// Implicit barrier in code. 456 OMP_IDENT_BARRIER_IMPL = 0x40, 457 /// Implicit barrier in 'for' directive. 458 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 459 /// Implicit barrier in 'sections' directive. 460 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 461 /// Implicit barrier in 'single' directive. 462 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 463 /// Call of __kmp_for_static_init for static loop. 464 OMP_IDENT_WORK_LOOP = 0x200, 465 /// Call of __kmp_for_static_init for sections. 466 OMP_IDENT_WORK_SECTIONS = 0x400, 467 /// Call of __kmp_for_static_init for distribute. 468 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 469 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 470 }; 471 472 namespace { 473 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 474 /// Values for bit flags for marking which requires clauses have been used. 475 enum OpenMPOffloadingRequiresDirFlags : int64_t { 476 /// flag undefined. 477 OMP_REQ_UNDEFINED = 0x000, 478 /// no requires clause present. 479 OMP_REQ_NONE = 0x001, 480 /// reverse_offload clause. 481 OMP_REQ_REVERSE_OFFLOAD = 0x002, 482 /// unified_address clause. 483 OMP_REQ_UNIFIED_ADDRESS = 0x004, 484 /// unified_shared_memory clause. 485 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 486 /// dynamic_allocators clause. 487 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 488 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 489 }; 490 491 enum OpenMPOffloadingReservedDeviceIDs { 492 /// Device ID if the device was not defined, runtime should get it 493 /// from environment variables in the spec. 494 OMP_DEVICEID_UNDEF = -1, 495 }; 496 } // anonymous namespace 497 498 /// Describes ident structure that describes a source location. 499 /// All descriptions are taken from 500 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 501 /// Original structure: 502 /// typedef struct ident { 503 /// kmp_int32 reserved_1; /**< might be used in Fortran; 504 /// see above */ 505 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 506 /// KMP_IDENT_KMPC identifies this union 507 /// member */ 508 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 509 /// see above */ 510 ///#if USE_ITT_BUILD 511 /// /* but currently used for storing 512 /// region-specific ITT */ 513 /// /* contextual information. */ 514 ///#endif /* USE_ITT_BUILD */ 515 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 516 /// C++ */ 517 /// char const *psource; /**< String describing the source location. 518 /// The string is composed of semi-colon separated 519 // fields which describe the source file, 520 /// the function and a pair of line numbers that 521 /// delimit the construct. 522 /// */ 523 /// } ident_t; 524 enum IdentFieldIndex { 525 /// might be used in Fortran 526 IdentField_Reserved_1, 527 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 528 IdentField_Flags, 529 /// Not really used in Fortran any more 530 IdentField_Reserved_2, 531 /// Source[4] in Fortran, do not use for C++ 532 IdentField_Reserved_3, 533 /// String describing the source location. The string is composed of 534 /// semi-colon separated fields which describe the source file, the function 535 /// and a pair of line numbers that delimit the construct. 536 IdentField_PSource 537 }; 538 539 /// Schedule types for 'omp for' loops (these enumerators are taken from 540 /// the enum sched_type in kmp.h). 541 enum OpenMPSchedType { 542 /// Lower bound for default (unordered) versions. 543 OMP_sch_lower = 32, 544 OMP_sch_static_chunked = 33, 545 OMP_sch_static = 34, 546 OMP_sch_dynamic_chunked = 35, 547 OMP_sch_guided_chunked = 36, 548 OMP_sch_runtime = 37, 549 OMP_sch_auto = 38, 550 /// static with chunk adjustment (e.g., simd) 551 OMP_sch_static_balanced_chunked = 45, 552 /// Lower bound for 'ordered' versions. 553 OMP_ord_lower = 64, 554 OMP_ord_static_chunked = 65, 555 OMP_ord_static = 66, 556 OMP_ord_dynamic_chunked = 67, 557 OMP_ord_guided_chunked = 68, 558 OMP_ord_runtime = 69, 559 OMP_ord_auto = 70, 560 OMP_sch_default = OMP_sch_static, 561 /// dist_schedule types 562 OMP_dist_sch_static_chunked = 91, 563 OMP_dist_sch_static = 92, 564 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 565 /// Set if the monotonic schedule modifier was present. 566 OMP_sch_modifier_monotonic = (1 << 29), 567 /// Set if the nonmonotonic schedule modifier was present. 568 OMP_sch_modifier_nonmonotonic = (1 << 30), 569 }; 570 571 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 572 /// region. 573 class CleanupTy final : public EHScopeStack::Cleanup { 574 PrePostActionTy *Action; 575 576 public: 577 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 578 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 579 if (!CGF.HaveInsertPoint()) 580 return; 581 Action->Exit(CGF); 582 } 583 }; 584 585 } // anonymous namespace 586 587 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 588 CodeGenFunction::RunCleanupsScope Scope(CGF); 589 if (PrePostAction) { 590 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 591 Callback(CodeGen, CGF, *PrePostAction); 592 } else { 593 PrePostActionTy Action; 594 Callback(CodeGen, CGF, Action); 595 } 596 } 597 598 /// Check if the combiner is a call to UDR combiner and if it is so return the 599 /// UDR decl used for reduction. 600 static const OMPDeclareReductionDecl * 601 getReductionInit(const Expr *ReductionOp) { 602 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 603 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 604 if (const auto *DRE = 605 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 606 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 607 return DRD; 608 return nullptr; 609 } 610 611 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 612 const OMPDeclareReductionDecl *DRD, 613 const Expr *InitOp, 614 Address Private, Address Original, 615 QualType Ty) { 616 if (DRD->getInitializer()) { 617 std::pair<llvm::Function *, llvm::Function *> Reduction = 618 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 619 const auto *CE = cast<CallExpr>(InitOp); 620 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 621 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 622 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 623 const auto *LHSDRE = 624 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 625 const auto *RHSDRE = 626 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 627 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 628 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 629 [=]() { return Private; }); 630 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 631 [=]() { return Original; }); 632 (void)PrivateScope.Privatize(); 633 RValue Func = RValue::get(Reduction.second); 634 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 635 CGF.EmitIgnoredExpr(InitOp); 636 } else { 637 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 638 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 639 auto *GV = new llvm::GlobalVariable( 640 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 641 llvm::GlobalValue::PrivateLinkage, Init, Name); 642 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 643 RValue InitRVal; 644 switch (CGF.getEvaluationKind(Ty)) { 645 case TEK_Scalar: 646 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 647 break; 648 case TEK_Complex: 649 InitRVal = 650 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 651 break; 652 case TEK_Aggregate: 653 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 654 break; 655 } 656 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 657 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 658 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 659 /*IsInitializer=*/false); 660 } 661 } 662 663 /// Emit initialization of arrays of complex types. 664 /// \param DestAddr Address of the array. 665 /// \param Type Type of array. 666 /// \param Init Initial expression of array. 667 /// \param SrcAddr Address of the original array. 668 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 669 QualType Type, bool EmitDeclareReductionInit, 670 const Expr *Init, 671 const OMPDeclareReductionDecl *DRD, 672 Address SrcAddr = Address::invalid()) { 673 // Perform element-by-element initialization. 674 QualType ElementTy; 675 676 // Drill down to the base element type on both arrays. 677 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 678 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 679 DestAddr = 680 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 681 if (DRD) 682 SrcAddr = 683 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 684 685 llvm::Value *SrcBegin = nullptr; 686 if (DRD) 687 SrcBegin = SrcAddr.getPointer(); 688 llvm::Value *DestBegin = DestAddr.getPointer(); 689 // Cast from pointer to array type to pointer to single element. 690 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 691 // The basic structure here is a while-do loop. 692 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 693 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 694 llvm::Value *IsEmpty = 695 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 696 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 697 698 // Enter the loop body, making that address the current address. 699 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 700 CGF.EmitBlock(BodyBB); 701 702 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 703 704 llvm::PHINode *SrcElementPHI = nullptr; 705 Address SrcElementCurrent = Address::invalid(); 706 if (DRD) { 707 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 708 "omp.arraycpy.srcElementPast"); 709 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 710 SrcElementCurrent = 711 Address(SrcElementPHI, 712 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 713 } 714 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 715 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 716 DestElementPHI->addIncoming(DestBegin, EntryBB); 717 Address DestElementCurrent = 718 Address(DestElementPHI, 719 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 720 721 // Emit copy. 722 { 723 CodeGenFunction::RunCleanupsScope InitScope(CGF); 724 if (EmitDeclareReductionInit) { 725 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 726 SrcElementCurrent, ElementTy); 727 } else 728 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 729 /*IsInitializer=*/false); 730 } 731 732 if (DRD) { 733 // Shift the address forward by one element. 734 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 735 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 736 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 737 } 738 739 // Shift the address forward by one element. 740 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 741 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 742 // Check whether we've reached the end. 743 llvm::Value *Done = 744 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 745 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 746 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 747 748 // Done. 749 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 750 } 751 752 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 753 return CGF.EmitOMPSharedLValue(E); 754 } 755 756 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 757 const Expr *E) { 758 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 759 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 760 return LValue(); 761 } 762 763 void ReductionCodeGen::emitAggregateInitialization( 764 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 765 const OMPDeclareReductionDecl *DRD) { 766 // Emit VarDecl with copy init for arrays. 767 // Get the address of the original variable captured in current 768 // captured region. 769 const auto *PrivateVD = 770 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 771 bool EmitDeclareReductionInit = 772 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 773 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 774 EmitDeclareReductionInit, 775 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 776 : PrivateVD->getInit(), 777 DRD, SharedLVal.getAddress(CGF)); 778 } 779 780 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 781 ArrayRef<const Expr *> Origs, 782 ArrayRef<const Expr *> Privates, 783 ArrayRef<const Expr *> ReductionOps) { 784 ClausesData.reserve(Shareds.size()); 785 SharedAddresses.reserve(Shareds.size()); 786 Sizes.reserve(Shareds.size()); 787 BaseDecls.reserve(Shareds.size()); 788 const auto *IOrig = Origs.begin(); 789 const auto *IPriv = Privates.begin(); 790 const auto *IRed = ReductionOps.begin(); 791 for (const Expr *Ref : Shareds) { 792 ClausesData.emplace_back(Ref, *IOrig, *IPriv, *IRed); 793 std::advance(IOrig, 1); 794 std::advance(IPriv, 1); 795 std::advance(IRed, 1); 796 } 797 } 798 799 void ReductionCodeGen::emitSharedOrigLValue(CodeGenFunction &CGF, unsigned N) { 800 assert(SharedAddresses.size() == N && OrigAddresses.size() == N && 801 "Number of generated lvalues must be exactly N."); 802 LValue First = emitSharedLValue(CGF, ClausesData[N].Shared); 803 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Shared); 804 SharedAddresses.emplace_back(First, Second); 805 if (ClausesData[N].Shared == ClausesData[N].Ref) { 806 OrigAddresses.emplace_back(First, Second); 807 } else { 808 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 809 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 810 OrigAddresses.emplace_back(First, Second); 811 } 812 } 813 814 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 815 const auto *PrivateVD = 816 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 817 QualType PrivateType = PrivateVD->getType(); 818 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 819 if (!PrivateType->isVariablyModifiedType()) { 820 Sizes.emplace_back( 821 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()), 822 nullptr); 823 return; 824 } 825 llvm::Value *Size; 826 llvm::Value *SizeInChars; 827 auto *ElemType = 828 cast<llvm::PointerType>(OrigAddresses[N].first.getPointer(CGF)->getType()) 829 ->getElementType(); 830 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 831 if (AsArraySection) { 832 Size = CGF.Builder.CreatePtrDiff(OrigAddresses[N].second.getPointer(CGF), 833 OrigAddresses[N].first.getPointer(CGF)); 834 Size = CGF.Builder.CreateNUWAdd( 835 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 836 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 837 } else { 838 SizeInChars = 839 CGF.getTypeSize(OrigAddresses[N].first.getType().getNonReferenceType()); 840 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 841 } 842 Sizes.emplace_back(SizeInChars, Size); 843 CodeGenFunction::OpaqueValueMapping OpaqueMap( 844 CGF, 845 cast<OpaqueValueExpr>( 846 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 847 RValue::get(Size)); 848 CGF.EmitVariablyModifiedType(PrivateType); 849 } 850 851 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 852 llvm::Value *Size) { 853 const auto *PrivateVD = 854 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 855 QualType PrivateType = PrivateVD->getType(); 856 if (!PrivateType->isVariablyModifiedType()) { 857 assert(!Size && !Sizes[N].second && 858 "Size should be nullptr for non-variably modified reduction " 859 "items."); 860 return; 861 } 862 CodeGenFunction::OpaqueValueMapping OpaqueMap( 863 CGF, 864 cast<OpaqueValueExpr>( 865 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 866 RValue::get(Size)); 867 CGF.EmitVariablyModifiedType(PrivateType); 868 } 869 870 void ReductionCodeGen::emitInitialization( 871 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 872 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 873 assert(SharedAddresses.size() > N && "No variable was generated"); 874 const auto *PrivateVD = 875 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 876 const OMPDeclareReductionDecl *DRD = 877 getReductionInit(ClausesData[N].ReductionOp); 878 QualType PrivateType = PrivateVD->getType(); 879 PrivateAddr = CGF.Builder.CreateElementBitCast( 880 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 881 QualType SharedType = SharedAddresses[N].first.getType(); 882 SharedLVal = CGF.MakeAddrLValue( 883 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 884 CGF.ConvertTypeForMem(SharedType)), 885 SharedType, SharedAddresses[N].first.getBaseInfo(), 886 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 887 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 888 if (DRD && DRD->getInitializer()) 889 (void)DefaultInit(CGF); 890 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 891 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 892 (void)DefaultInit(CGF); 893 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 894 PrivateAddr, SharedLVal.getAddress(CGF), 895 SharedLVal.getType()); 896 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 897 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 898 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 899 PrivateVD->getType().getQualifiers(), 900 /*IsInitializer=*/false); 901 } 902 } 903 904 bool ReductionCodeGen::needCleanups(unsigned N) { 905 const auto *PrivateVD = 906 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 907 QualType PrivateType = PrivateVD->getType(); 908 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 909 return DTorKind != QualType::DK_none; 910 } 911 912 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 913 Address PrivateAddr) { 914 const auto *PrivateVD = 915 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 916 QualType PrivateType = PrivateVD->getType(); 917 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 918 if (needCleanups(N)) { 919 PrivateAddr = CGF.Builder.CreateElementBitCast( 920 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 921 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 922 } 923 } 924 925 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 926 LValue BaseLV) { 927 BaseTy = BaseTy.getNonReferenceType(); 928 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 929 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 930 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 931 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 932 } else { 933 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 934 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 935 } 936 BaseTy = BaseTy->getPointeeType(); 937 } 938 return CGF.MakeAddrLValue( 939 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 940 CGF.ConvertTypeForMem(ElTy)), 941 BaseLV.getType(), BaseLV.getBaseInfo(), 942 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 943 } 944 945 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 946 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 947 llvm::Value *Addr) { 948 Address Tmp = Address::invalid(); 949 Address TopTmp = Address::invalid(); 950 Address MostTopTmp = Address::invalid(); 951 BaseTy = BaseTy.getNonReferenceType(); 952 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 953 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 954 Tmp = CGF.CreateMemTemp(BaseTy); 955 if (TopTmp.isValid()) 956 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 957 else 958 MostTopTmp = Tmp; 959 TopTmp = Tmp; 960 BaseTy = BaseTy->getPointeeType(); 961 } 962 llvm::Type *Ty = BaseLVType; 963 if (Tmp.isValid()) 964 Ty = Tmp.getElementType(); 965 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 966 if (Tmp.isValid()) { 967 CGF.Builder.CreateStore(Addr, Tmp); 968 return MostTopTmp; 969 } 970 return Address(Addr, BaseLVAlignment); 971 } 972 973 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 974 const VarDecl *OrigVD = nullptr; 975 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 976 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 977 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 978 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 979 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 980 Base = TempASE->getBase()->IgnoreParenImpCasts(); 981 DE = cast<DeclRefExpr>(Base); 982 OrigVD = cast<VarDecl>(DE->getDecl()); 983 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 984 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 985 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 986 Base = TempASE->getBase()->IgnoreParenImpCasts(); 987 DE = cast<DeclRefExpr>(Base); 988 OrigVD = cast<VarDecl>(DE->getDecl()); 989 } 990 return OrigVD; 991 } 992 993 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 994 Address PrivateAddr) { 995 const DeclRefExpr *DE; 996 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 997 BaseDecls.emplace_back(OrigVD); 998 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 999 LValue BaseLValue = 1000 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1001 OriginalBaseLValue); 1002 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1003 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1004 llvm::Value *PrivatePointer = 1005 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1006 PrivateAddr.getPointer(), 1007 SharedAddresses[N].first.getAddress(CGF).getType()); 1008 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1009 return castToBase(CGF, OrigVD->getType(), 1010 SharedAddresses[N].first.getType(), 1011 OriginalBaseLValue.getAddress(CGF).getType(), 1012 OriginalBaseLValue.getAlignment(), Ptr); 1013 } 1014 BaseDecls.emplace_back( 1015 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1016 return PrivateAddr; 1017 } 1018 1019 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1020 const OMPDeclareReductionDecl *DRD = 1021 getReductionInit(ClausesData[N].ReductionOp); 1022 return DRD && DRD->getInitializer(); 1023 } 1024 1025 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1026 return CGF.EmitLoadOfPointerLValue( 1027 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1028 getThreadIDVariable()->getType()->castAs<PointerType>()); 1029 } 1030 1031 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1032 if (!CGF.HaveInsertPoint()) 1033 return; 1034 // 1.2.2 OpenMP Language Terminology 1035 // Structured block - An executable statement with a single entry at the 1036 // top and a single exit at the bottom. 1037 // The point of exit cannot be a branch out of the structured block. 1038 // longjmp() and throw() must not violate the entry/exit criteria. 1039 CGF.EHStack.pushTerminate(); 1040 CodeGen(CGF); 1041 CGF.EHStack.popTerminate(); 1042 } 1043 1044 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1045 CodeGenFunction &CGF) { 1046 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1047 getThreadIDVariable()->getType(), 1048 AlignmentSource::Decl); 1049 } 1050 1051 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1052 QualType FieldTy) { 1053 auto *Field = FieldDecl::Create( 1054 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1055 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1056 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1057 Field->setAccess(AS_public); 1058 DC->addDecl(Field); 1059 return Field; 1060 } 1061 1062 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1063 StringRef Separator) 1064 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1065 OMPBuilder(CGM.getModule()), OffloadEntriesInfoManager(CGM) { 1066 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1067 1068 // Initialize Types used in OpenMPIRBuilder from OMPKinds.def 1069 OMPBuilder.initialize(); 1070 loadOffloadInfoMetadata(); 1071 } 1072 1073 void CGOpenMPRuntime::clear() { 1074 InternalVars.clear(); 1075 // Clean non-target variable declarations possibly used only in debug info. 1076 for (const auto &Data : EmittedNonTargetVariables) { 1077 if (!Data.getValue().pointsToAliveValue()) 1078 continue; 1079 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1080 if (!GV) 1081 continue; 1082 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1083 continue; 1084 GV->eraseFromParent(); 1085 } 1086 } 1087 1088 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1089 SmallString<128> Buffer; 1090 llvm::raw_svector_ostream OS(Buffer); 1091 StringRef Sep = FirstSeparator; 1092 for (StringRef Part : Parts) { 1093 OS << Sep << Part; 1094 Sep = Separator; 1095 } 1096 return std::string(OS.str()); 1097 } 1098 1099 static llvm::Function * 1100 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1101 const Expr *CombinerInitializer, const VarDecl *In, 1102 const VarDecl *Out, bool IsCombiner) { 1103 // void .omp_combiner.(Ty *in, Ty *out); 1104 ASTContext &C = CGM.getContext(); 1105 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1106 FunctionArgList Args; 1107 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1108 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1109 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1110 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1111 Args.push_back(&OmpOutParm); 1112 Args.push_back(&OmpInParm); 1113 const CGFunctionInfo &FnInfo = 1114 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1115 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1116 std::string Name = CGM.getOpenMPRuntime().getName( 1117 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1118 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1119 Name, &CGM.getModule()); 1120 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1121 if (CGM.getLangOpts().Optimize) { 1122 Fn->removeFnAttr(llvm::Attribute::NoInline); 1123 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1124 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1125 } 1126 CodeGenFunction CGF(CGM); 1127 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1128 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1129 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1130 Out->getLocation()); 1131 CodeGenFunction::OMPPrivateScope Scope(CGF); 1132 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1133 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1134 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1135 .getAddress(CGF); 1136 }); 1137 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1138 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1139 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1140 .getAddress(CGF); 1141 }); 1142 (void)Scope.Privatize(); 1143 if (!IsCombiner && Out->hasInit() && 1144 !CGF.isTrivialInitializer(Out->getInit())) { 1145 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1146 Out->getType().getQualifiers(), 1147 /*IsInitializer=*/true); 1148 } 1149 if (CombinerInitializer) 1150 CGF.EmitIgnoredExpr(CombinerInitializer); 1151 Scope.ForceCleanup(); 1152 CGF.FinishFunction(); 1153 return Fn; 1154 } 1155 1156 void CGOpenMPRuntime::emitUserDefinedReduction( 1157 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1158 if (UDRMap.count(D) > 0) 1159 return; 1160 llvm::Function *Combiner = emitCombinerOrInitializer( 1161 CGM, D->getType(), D->getCombiner(), 1162 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1163 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1164 /*IsCombiner=*/true); 1165 llvm::Function *Initializer = nullptr; 1166 if (const Expr *Init = D->getInitializer()) { 1167 Initializer = emitCombinerOrInitializer( 1168 CGM, D->getType(), 1169 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1170 : nullptr, 1171 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1172 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1173 /*IsCombiner=*/false); 1174 } 1175 UDRMap.try_emplace(D, Combiner, Initializer); 1176 if (CGF) { 1177 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1178 Decls.second.push_back(D); 1179 } 1180 } 1181 1182 std::pair<llvm::Function *, llvm::Function *> 1183 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1184 auto I = UDRMap.find(D); 1185 if (I != UDRMap.end()) 1186 return I->second; 1187 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1188 return UDRMap.lookup(D); 1189 } 1190 1191 namespace { 1192 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1193 // Builder if one is present. 1194 struct PushAndPopStackRAII { 1195 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1196 bool HasCancel) 1197 : OMPBuilder(OMPBuilder) { 1198 if (!OMPBuilder) 1199 return; 1200 1201 // The following callback is the crucial part of clangs cleanup process. 1202 // 1203 // NOTE: 1204 // Once the OpenMPIRBuilder is used to create parallel regions (and 1205 // similar), the cancellation destination (Dest below) is determined via 1206 // IP. That means if we have variables to finalize we split the block at IP, 1207 // use the new block (=BB) as destination to build a JumpDest (via 1208 // getJumpDestInCurrentScope(BB)) which then is fed to 1209 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1210 // to push & pop an FinalizationInfo object. 1211 // The FiniCB will still be needed but at the point where the 1212 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1213 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1214 assert(IP.getBlock()->end() == IP.getPoint() && 1215 "Clang CG should cause non-terminated block!"); 1216 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1217 CGF.Builder.restoreIP(IP); 1218 CodeGenFunction::JumpDest Dest = 1219 CGF.getOMPCancelDestination(OMPD_parallel); 1220 CGF.EmitBranchThroughCleanup(Dest); 1221 }; 1222 1223 // TODO: Remove this once we emit parallel regions through the 1224 // OpenMPIRBuilder as it can do this setup internally. 1225 llvm::OpenMPIRBuilder::FinalizationInfo FI( 1226 {FiniCB, OMPD_parallel, HasCancel}); 1227 OMPBuilder->pushFinalizationCB(std::move(FI)); 1228 } 1229 ~PushAndPopStackRAII() { 1230 if (OMPBuilder) 1231 OMPBuilder->popFinalizationCB(); 1232 } 1233 llvm::OpenMPIRBuilder *OMPBuilder; 1234 }; 1235 } // namespace 1236 1237 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1238 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1239 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1240 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1241 assert(ThreadIDVar->getType()->isPointerType() && 1242 "thread id variable must be of type kmp_int32 *"); 1243 CodeGenFunction CGF(CGM, true); 1244 bool HasCancel = false; 1245 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1246 HasCancel = OPD->hasCancel(); 1247 else if (const auto *OPD = dyn_cast<OMPTargetParallelDirective>(&D)) 1248 HasCancel = OPD->hasCancel(); 1249 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1250 HasCancel = OPSD->hasCancel(); 1251 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1252 HasCancel = OPFD->hasCancel(); 1253 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1254 HasCancel = OPFD->hasCancel(); 1255 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1256 HasCancel = OPFD->hasCancel(); 1257 else if (const auto *OPFD = 1258 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1259 HasCancel = OPFD->hasCancel(); 1260 else if (const auto *OPFD = 1261 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1262 HasCancel = OPFD->hasCancel(); 1263 1264 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1265 // parallel region to make cancellation barriers work properly. 1266 llvm::OpenMPIRBuilder &OMPBuilder = CGM.getOpenMPRuntime().getOMPBuilder(); 1267 PushAndPopStackRAII PSR(&OMPBuilder, CGF, HasCancel); 1268 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1269 HasCancel, OutlinedHelperName); 1270 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1271 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1272 } 1273 1274 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1275 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1276 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1277 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1278 return emitParallelOrTeamsOutlinedFunction( 1279 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1280 } 1281 1282 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1283 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1284 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1285 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1286 return emitParallelOrTeamsOutlinedFunction( 1287 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1288 } 1289 1290 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1291 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1292 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1293 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1294 bool Tied, unsigned &NumberOfParts) { 1295 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1296 PrePostActionTy &) { 1297 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1298 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1299 llvm::Value *TaskArgs[] = { 1300 UpLoc, ThreadID, 1301 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1302 TaskTVar->getType()->castAs<PointerType>()) 1303 .getPointer(CGF)}; 1304 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1305 CGM.getModule(), OMPRTL___kmpc_omp_task), 1306 TaskArgs); 1307 }; 1308 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1309 UntiedCodeGen); 1310 CodeGen.setAction(Action); 1311 assert(!ThreadIDVar->getType()->isPointerType() && 1312 "thread id variable must be of type kmp_int32 for tasks"); 1313 const OpenMPDirectiveKind Region = 1314 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1315 : OMPD_task; 1316 const CapturedStmt *CS = D.getCapturedStmt(Region); 1317 bool HasCancel = false; 1318 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1319 HasCancel = TD->hasCancel(); 1320 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1321 HasCancel = TD->hasCancel(); 1322 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1323 HasCancel = TD->hasCancel(); 1324 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1325 HasCancel = TD->hasCancel(); 1326 1327 CodeGenFunction CGF(CGM, true); 1328 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1329 InnermostKind, HasCancel, Action); 1330 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1331 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1332 if (!Tied) 1333 NumberOfParts = Action.getNumberOfParts(); 1334 return Res; 1335 } 1336 1337 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1338 const RecordDecl *RD, const CGRecordLayout &RL, 1339 ArrayRef<llvm::Constant *> Data) { 1340 llvm::StructType *StructTy = RL.getLLVMType(); 1341 unsigned PrevIdx = 0; 1342 ConstantInitBuilder CIBuilder(CGM); 1343 auto DI = Data.begin(); 1344 for (const FieldDecl *FD : RD->fields()) { 1345 unsigned Idx = RL.getLLVMFieldNo(FD); 1346 // Fill the alignment. 1347 for (unsigned I = PrevIdx; I < Idx; ++I) 1348 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1349 PrevIdx = Idx + 1; 1350 Fields.add(*DI); 1351 ++DI; 1352 } 1353 } 1354 1355 template <class... As> 1356 static llvm::GlobalVariable * 1357 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1358 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1359 As &&... Args) { 1360 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1361 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1362 ConstantInitBuilder CIBuilder(CGM); 1363 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1364 buildStructValue(Fields, CGM, RD, RL, Data); 1365 return Fields.finishAndCreateGlobal( 1366 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1367 std::forward<As>(Args)...); 1368 } 1369 1370 template <typename T> 1371 static void 1372 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1373 ArrayRef<llvm::Constant *> Data, 1374 T &Parent) { 1375 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1376 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1377 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1378 buildStructValue(Fields, CGM, RD, RL, Data); 1379 Fields.finishAndAddTo(Parent); 1380 } 1381 1382 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1383 bool AtCurrentPoint) { 1384 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1385 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1386 1387 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1388 if (AtCurrentPoint) { 1389 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1390 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1391 } else { 1392 Elem.second.ServiceInsertPt = 1393 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1394 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1395 } 1396 } 1397 1398 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1399 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1400 if (Elem.second.ServiceInsertPt) { 1401 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1402 Elem.second.ServiceInsertPt = nullptr; 1403 Ptr->eraseFromParent(); 1404 } 1405 } 1406 1407 static StringRef getIdentStringFromSourceLocation(CodeGenFunction &CGF, 1408 SourceLocation Loc, 1409 SmallString<128> &Buffer) { 1410 llvm::raw_svector_ostream OS(Buffer); 1411 // Build debug location 1412 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1413 OS << ";" << PLoc.getFilename() << ";"; 1414 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1415 OS << FD->getQualifiedNameAsString(); 1416 OS << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1417 return OS.str(); 1418 } 1419 1420 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1421 SourceLocation Loc, 1422 unsigned Flags) { 1423 llvm::Constant *SrcLocStr; 1424 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1425 Loc.isInvalid()) { 1426 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(); 1427 } else { 1428 std::string FunctionName = ""; 1429 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1430 FunctionName = FD->getQualifiedNameAsString(); 1431 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1432 const char *FileName = PLoc.getFilename(); 1433 unsigned Line = PLoc.getLine(); 1434 unsigned Column = PLoc.getColumn(); 1435 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FunctionName.c_str(), FileName, 1436 Line, Column); 1437 } 1438 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1439 return OMPBuilder.getOrCreateIdent(SrcLocStr, llvm::omp::IdentFlag(Flags), 1440 Reserved2Flags); 1441 } 1442 1443 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1444 SourceLocation Loc) { 1445 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1446 // If the OpenMPIRBuilder is used we need to use it for all thread id calls as 1447 // the clang invariants used below might be broken. 1448 if (CGM.getLangOpts().OpenMPIRBuilder) { 1449 SmallString<128> Buffer; 1450 OMPBuilder.updateToLocation(CGF.Builder.saveIP()); 1451 auto *SrcLocStr = OMPBuilder.getOrCreateSrcLocStr( 1452 getIdentStringFromSourceLocation(CGF, Loc, Buffer)); 1453 return OMPBuilder.getOrCreateThreadID( 1454 OMPBuilder.getOrCreateIdent(SrcLocStr)); 1455 } 1456 1457 llvm::Value *ThreadID = nullptr; 1458 // Check whether we've already cached a load of the thread id in this 1459 // function. 1460 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1461 if (I != OpenMPLocThreadIDMap.end()) { 1462 ThreadID = I->second.ThreadID; 1463 if (ThreadID != nullptr) 1464 return ThreadID; 1465 } 1466 // If exceptions are enabled, do not use parameter to avoid possible crash. 1467 if (auto *OMPRegionInfo = 1468 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1469 if (OMPRegionInfo->getThreadIDVariable()) { 1470 // Check if this an outlined function with thread id passed as argument. 1471 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1472 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1473 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1474 !CGF.getLangOpts().CXXExceptions || 1475 CGF.Builder.GetInsertBlock() == TopBlock || 1476 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1477 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1478 TopBlock || 1479 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1480 CGF.Builder.GetInsertBlock()) { 1481 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1482 // If value loaded in entry block, cache it and use it everywhere in 1483 // function. 1484 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1485 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1486 Elem.second.ThreadID = ThreadID; 1487 } 1488 return ThreadID; 1489 } 1490 } 1491 } 1492 1493 // This is not an outlined function region - need to call __kmpc_int32 1494 // kmpc_global_thread_num(ident_t *loc). 1495 // Generate thread id value and cache this value for use across the 1496 // function. 1497 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1498 if (!Elem.second.ServiceInsertPt) 1499 setLocThreadIdInsertPt(CGF); 1500 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1501 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1502 llvm::CallInst *Call = CGF.Builder.CreateCall( 1503 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 1504 OMPRTL___kmpc_global_thread_num), 1505 emitUpdateLocation(CGF, Loc)); 1506 Call->setCallingConv(CGF.getRuntimeCC()); 1507 Elem.second.ThreadID = Call; 1508 return Call; 1509 } 1510 1511 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1512 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1513 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1514 clearLocThreadIdInsertPt(CGF); 1515 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1516 } 1517 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1518 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1519 UDRMap.erase(D); 1520 FunctionUDRMap.erase(CGF.CurFn); 1521 } 1522 auto I = FunctionUDMMap.find(CGF.CurFn); 1523 if (I != FunctionUDMMap.end()) { 1524 for(const auto *D : I->second) 1525 UDMMap.erase(D); 1526 FunctionUDMMap.erase(I); 1527 } 1528 LastprivateConditionalToTypes.erase(CGF.CurFn); 1529 FunctionToUntiedTaskStackMap.erase(CGF.CurFn); 1530 } 1531 1532 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1533 return OMPBuilder.IdentPtr; 1534 } 1535 1536 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1537 if (!Kmpc_MicroTy) { 1538 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1539 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1540 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1541 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1542 } 1543 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1544 } 1545 1546 llvm::FunctionCallee 1547 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 1548 assert((IVSize == 32 || IVSize == 64) && 1549 "IV size is not compatible with the omp runtime"); 1550 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 1551 : "__kmpc_for_static_init_4u") 1552 : (IVSigned ? "__kmpc_for_static_init_8" 1553 : "__kmpc_for_static_init_8u"); 1554 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1555 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1556 llvm::Type *TypeParams[] = { 1557 getIdentTyPointerTy(), // loc 1558 CGM.Int32Ty, // tid 1559 CGM.Int32Ty, // schedtype 1560 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1561 PtrTy, // p_lower 1562 PtrTy, // p_upper 1563 PtrTy, // p_stride 1564 ITy, // incr 1565 ITy // chunk 1566 }; 1567 auto *FnTy = 1568 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1569 return CGM.CreateRuntimeFunction(FnTy, Name); 1570 } 1571 1572 llvm::FunctionCallee 1573 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 1574 assert((IVSize == 32 || IVSize == 64) && 1575 "IV size is not compatible with the omp runtime"); 1576 StringRef Name = 1577 IVSize == 32 1578 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 1579 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 1580 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1581 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 1582 CGM.Int32Ty, // tid 1583 CGM.Int32Ty, // schedtype 1584 ITy, // lower 1585 ITy, // upper 1586 ITy, // stride 1587 ITy // chunk 1588 }; 1589 auto *FnTy = 1590 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1591 return CGM.CreateRuntimeFunction(FnTy, Name); 1592 } 1593 1594 llvm::FunctionCallee 1595 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 1596 assert((IVSize == 32 || IVSize == 64) && 1597 "IV size is not compatible with the omp runtime"); 1598 StringRef Name = 1599 IVSize == 32 1600 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 1601 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 1602 llvm::Type *TypeParams[] = { 1603 getIdentTyPointerTy(), // loc 1604 CGM.Int32Ty, // tid 1605 }; 1606 auto *FnTy = 1607 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1608 return CGM.CreateRuntimeFunction(FnTy, Name); 1609 } 1610 1611 llvm::FunctionCallee 1612 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 1613 assert((IVSize == 32 || IVSize == 64) && 1614 "IV size is not compatible with the omp runtime"); 1615 StringRef Name = 1616 IVSize == 32 1617 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 1618 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 1619 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 1620 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 1621 llvm::Type *TypeParams[] = { 1622 getIdentTyPointerTy(), // loc 1623 CGM.Int32Ty, // tid 1624 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 1625 PtrTy, // p_lower 1626 PtrTy, // p_upper 1627 PtrTy // p_stride 1628 }; 1629 auto *FnTy = 1630 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1631 return CGM.CreateRuntimeFunction(FnTy, Name); 1632 } 1633 1634 /// Obtain information that uniquely identifies a target entry. This 1635 /// consists of the file and device IDs as well as line number associated with 1636 /// the relevant entry source location. 1637 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 1638 unsigned &DeviceID, unsigned &FileID, 1639 unsigned &LineNum) { 1640 SourceManager &SM = C.getSourceManager(); 1641 1642 // The loc should be always valid and have a file ID (the user cannot use 1643 // #pragma directives in macros) 1644 1645 assert(Loc.isValid() && "Source location is expected to be always valid."); 1646 1647 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 1648 assert(PLoc.isValid() && "Source location is expected to be always valid."); 1649 1650 llvm::sys::fs::UniqueID ID; 1651 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 1652 SM.getDiagnostics().Report(diag::err_cannot_open_file) 1653 << PLoc.getFilename() << EC.message(); 1654 1655 DeviceID = ID.getDevice(); 1656 FileID = ID.getFile(); 1657 LineNum = PLoc.getLine(); 1658 } 1659 1660 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 1661 if (CGM.getLangOpts().OpenMPSimd) 1662 return Address::invalid(); 1663 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1664 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1665 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 1666 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1667 HasRequiresUnifiedSharedMemory))) { 1668 SmallString<64> PtrName; 1669 { 1670 llvm::raw_svector_ostream OS(PtrName); 1671 OS << CGM.getMangledName(GlobalDecl(VD)); 1672 if (!VD->isExternallyVisible()) { 1673 unsigned DeviceID, FileID, Line; 1674 getTargetEntryUniqueInfo(CGM.getContext(), 1675 VD->getCanonicalDecl()->getBeginLoc(), 1676 DeviceID, FileID, Line); 1677 OS << llvm::format("_%x", FileID); 1678 } 1679 OS << "_decl_tgt_ref_ptr"; 1680 } 1681 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 1682 if (!Ptr) { 1683 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 1684 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 1685 PtrName); 1686 1687 auto *GV = cast<llvm::GlobalVariable>(Ptr); 1688 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 1689 1690 if (!CGM.getLangOpts().OpenMPIsDevice) 1691 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 1692 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 1693 } 1694 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 1695 } 1696 return Address::invalid(); 1697 } 1698 1699 llvm::Constant * 1700 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 1701 assert(!CGM.getLangOpts().OpenMPUseTLS || 1702 !CGM.getContext().getTargetInfo().isTLSSupported()); 1703 // Lookup the entry, lazily creating it if necessary. 1704 std::string Suffix = getName({"cache", ""}); 1705 return getOrCreateInternalVariable( 1706 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 1707 } 1708 1709 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 1710 const VarDecl *VD, 1711 Address VDAddr, 1712 SourceLocation Loc) { 1713 if (CGM.getLangOpts().OpenMPUseTLS && 1714 CGM.getContext().getTargetInfo().isTLSSupported()) 1715 return VDAddr; 1716 1717 llvm::Type *VarTy = VDAddr.getElementType(); 1718 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 1719 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 1720 CGM.Int8PtrTy), 1721 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 1722 getOrCreateThreadPrivateCache(VD)}; 1723 return Address(CGF.EmitRuntimeCall( 1724 OMPBuilder.getOrCreateRuntimeFunction( 1725 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 1726 Args), 1727 VDAddr.getAlignment()); 1728 } 1729 1730 void CGOpenMPRuntime::emitThreadPrivateVarInit( 1731 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 1732 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 1733 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 1734 // library. 1735 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 1736 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 1737 CGM.getModule(), OMPRTL___kmpc_global_thread_num), 1738 OMPLoc); 1739 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 1740 // to register constructor/destructor for variable. 1741 llvm::Value *Args[] = { 1742 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 1743 Ctor, CopyCtor, Dtor}; 1744 CGF.EmitRuntimeCall( 1745 OMPBuilder.getOrCreateRuntimeFunction( 1746 CGM.getModule(), OMPRTL___kmpc_threadprivate_register), 1747 Args); 1748 } 1749 1750 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 1751 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 1752 bool PerformInit, CodeGenFunction *CGF) { 1753 if (CGM.getLangOpts().OpenMPUseTLS && 1754 CGM.getContext().getTargetInfo().isTLSSupported()) 1755 return nullptr; 1756 1757 VD = VD->getDefinition(CGM.getContext()); 1758 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 1759 QualType ASTTy = VD->getType(); 1760 1761 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 1762 const Expr *Init = VD->getAnyInitializer(); 1763 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1764 // Generate function that re-emits the declaration's initializer into the 1765 // threadprivate copy of the variable VD 1766 CodeGenFunction CtorCGF(CGM); 1767 FunctionArgList Args; 1768 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1769 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1770 ImplicitParamDecl::Other); 1771 Args.push_back(&Dst); 1772 1773 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1774 CGM.getContext().VoidPtrTy, Args); 1775 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1776 std::string Name = getName({"__kmpc_global_ctor_", ""}); 1777 llvm::Function *Fn = 1778 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1779 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 1780 Args, Loc, Loc); 1781 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 1782 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1783 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1784 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 1785 Arg = CtorCGF.Builder.CreateElementBitCast( 1786 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 1787 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 1788 /*IsInitializer=*/true); 1789 ArgVal = CtorCGF.EmitLoadOfScalar( 1790 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 1791 CGM.getContext().VoidPtrTy, Dst.getLocation()); 1792 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 1793 CtorCGF.FinishFunction(); 1794 Ctor = Fn; 1795 } 1796 if (VD->getType().isDestructedType() != QualType::DK_none) { 1797 // Generate function that emits destructor call for the threadprivate copy 1798 // of the variable VD 1799 CodeGenFunction DtorCGF(CGM); 1800 FunctionArgList Args; 1801 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 1802 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 1803 ImplicitParamDecl::Other); 1804 Args.push_back(&Dst); 1805 1806 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 1807 CGM.getContext().VoidTy, Args); 1808 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1809 std::string Name = getName({"__kmpc_global_dtor_", ""}); 1810 llvm::Function *Fn = 1811 CGM.CreateGlobalInitOrCleanUpFunction(FTy, Name, FI, Loc); 1812 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1813 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 1814 Loc, Loc); 1815 // Create a scope with an artificial location for the body of this function. 1816 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1817 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 1818 DtorCGF.GetAddrOfLocalVar(&Dst), 1819 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 1820 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 1821 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1822 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1823 DtorCGF.FinishFunction(); 1824 Dtor = Fn; 1825 } 1826 // Do not emit init function if it is not required. 1827 if (!Ctor && !Dtor) 1828 return nullptr; 1829 1830 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1831 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 1832 /*isVarArg=*/false) 1833 ->getPointerTo(); 1834 // Copying constructor for the threadprivate variable. 1835 // Must be NULL - reserved by runtime, but currently it requires that this 1836 // parameter is always NULL. Otherwise it fires assertion. 1837 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 1838 if (Ctor == nullptr) { 1839 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1840 /*isVarArg=*/false) 1841 ->getPointerTo(); 1842 Ctor = llvm::Constant::getNullValue(CtorTy); 1843 } 1844 if (Dtor == nullptr) { 1845 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 1846 /*isVarArg=*/false) 1847 ->getPointerTo(); 1848 Dtor = llvm::Constant::getNullValue(DtorTy); 1849 } 1850 if (!CGF) { 1851 auto *InitFunctionTy = 1852 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 1853 std::string Name = getName({"__omp_threadprivate_init_", ""}); 1854 llvm::Function *InitFunction = CGM.CreateGlobalInitOrCleanUpFunction( 1855 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 1856 CodeGenFunction InitCGF(CGM); 1857 FunctionArgList ArgList; 1858 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 1859 CGM.getTypes().arrangeNullaryFunction(), ArgList, 1860 Loc, Loc); 1861 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1862 InitCGF.FinishFunction(); 1863 return InitFunction; 1864 } 1865 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 1866 } 1867 return nullptr; 1868 } 1869 1870 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 1871 llvm::GlobalVariable *Addr, 1872 bool PerformInit) { 1873 if (CGM.getLangOpts().OMPTargetTriples.empty() && 1874 !CGM.getLangOpts().OpenMPIsDevice) 1875 return false; 1876 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 1877 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 1878 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 1879 (*Res == OMPDeclareTargetDeclAttr::MT_To && 1880 HasRequiresUnifiedSharedMemory)) 1881 return CGM.getLangOpts().OpenMPIsDevice; 1882 VD = VD->getDefinition(CGM.getContext()); 1883 assert(VD && "Unknown VarDecl"); 1884 1885 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 1886 return CGM.getLangOpts().OpenMPIsDevice; 1887 1888 QualType ASTTy = VD->getType(); 1889 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 1890 1891 // Produce the unique prefix to identify the new target regions. We use 1892 // the source location of the variable declaration which we know to not 1893 // conflict with any target region. 1894 unsigned DeviceID; 1895 unsigned FileID; 1896 unsigned Line; 1897 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 1898 SmallString<128> Buffer, Out; 1899 { 1900 llvm::raw_svector_ostream OS(Buffer); 1901 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 1902 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 1903 } 1904 1905 const Expr *Init = VD->getAnyInitializer(); 1906 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 1907 llvm::Constant *Ctor; 1908 llvm::Constant *ID; 1909 if (CGM.getLangOpts().OpenMPIsDevice) { 1910 // Generate function that re-emits the declaration's initializer into 1911 // the threadprivate copy of the variable VD 1912 CodeGenFunction CtorCGF(CGM); 1913 1914 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1915 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1916 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1917 FTy, Twine(Buffer, "_ctor"), FI, Loc); 1918 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 1919 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1920 FunctionArgList(), Loc, Loc); 1921 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 1922 CtorCGF.EmitAnyExprToMem(Init, 1923 Address(Addr, CGM.getContext().getDeclAlign(VD)), 1924 Init->getType().getQualifiers(), 1925 /*IsInitializer=*/true); 1926 CtorCGF.FinishFunction(); 1927 Ctor = Fn; 1928 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1929 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 1930 } else { 1931 Ctor = new llvm::GlobalVariable( 1932 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1933 llvm::GlobalValue::PrivateLinkage, 1934 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 1935 ID = Ctor; 1936 } 1937 1938 // Register the information for the entry associated with the constructor. 1939 Out.clear(); 1940 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 1941 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 1942 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 1943 } 1944 if (VD->getType().isDestructedType() != QualType::DK_none) { 1945 llvm::Constant *Dtor; 1946 llvm::Constant *ID; 1947 if (CGM.getLangOpts().OpenMPIsDevice) { 1948 // Generate function that emits destructor call for the threadprivate 1949 // copy of the variable VD 1950 CodeGenFunction DtorCGF(CGM); 1951 1952 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 1953 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 1954 llvm::Function *Fn = CGM.CreateGlobalInitOrCleanUpFunction( 1955 FTy, Twine(Buffer, "_dtor"), FI, Loc); 1956 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 1957 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 1958 FunctionArgList(), Loc, Loc); 1959 // Create a scope with an artificial location for the body of this 1960 // function. 1961 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 1962 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 1963 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 1964 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 1965 DtorCGF.FinishFunction(); 1966 Dtor = Fn; 1967 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 1968 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 1969 } else { 1970 Dtor = new llvm::GlobalVariable( 1971 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 1972 llvm::GlobalValue::PrivateLinkage, 1973 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 1974 ID = Dtor; 1975 } 1976 // Register the information for the entry associated with the destructor. 1977 Out.clear(); 1978 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 1979 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 1980 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 1981 } 1982 return CGM.getLangOpts().OpenMPIsDevice; 1983 } 1984 1985 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 1986 QualType VarType, 1987 StringRef Name) { 1988 std::string Suffix = getName({"artificial", ""}); 1989 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 1990 llvm::Value *GAddr = 1991 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 1992 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 1993 CGM.getTarget().isTLSSupported()) { 1994 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 1995 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 1996 } 1997 std::string CacheSuffix = getName({"cache", ""}); 1998 llvm::Value *Args[] = { 1999 emitUpdateLocation(CGF, SourceLocation()), 2000 getThreadID(CGF, SourceLocation()), 2001 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2002 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2003 /*isSigned=*/false), 2004 getOrCreateInternalVariable( 2005 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2006 return Address( 2007 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2008 CGF.EmitRuntimeCall( 2009 OMPBuilder.getOrCreateRuntimeFunction( 2010 CGM.getModule(), OMPRTL___kmpc_threadprivate_cached), 2011 Args), 2012 VarLVType->getPointerTo(/*AddrSpace=*/0)), 2013 CGM.getContext().getTypeAlignInChars(VarType)); 2014 } 2015 2016 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 2017 const RegionCodeGenTy &ThenGen, 2018 const RegionCodeGenTy &ElseGen) { 2019 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 2020 2021 // If the condition constant folds and can be elided, try to avoid emitting 2022 // the condition and the dead arm of the if/else. 2023 bool CondConstant; 2024 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 2025 if (CondConstant) 2026 ThenGen(CGF); 2027 else 2028 ElseGen(CGF); 2029 return; 2030 } 2031 2032 // Otherwise, the condition did not fold, or we couldn't elide it. Just 2033 // emit the conditional branch. 2034 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2035 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 2036 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 2037 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 2038 2039 // Emit the 'then' code. 2040 CGF.EmitBlock(ThenBlock); 2041 ThenGen(CGF); 2042 CGF.EmitBranch(ContBlock); 2043 // Emit the 'else' code if present. 2044 // There is no need to emit line number for unconditional branch. 2045 (void)ApplyDebugLocation::CreateEmpty(CGF); 2046 CGF.EmitBlock(ElseBlock); 2047 ElseGen(CGF); 2048 // There is no need to emit line number for unconditional branch. 2049 (void)ApplyDebugLocation::CreateEmpty(CGF); 2050 CGF.EmitBranch(ContBlock); 2051 // Emit the continuation block for code after the if. 2052 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 2053 } 2054 2055 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 2056 llvm::Function *OutlinedFn, 2057 ArrayRef<llvm::Value *> CapturedVars, 2058 const Expr *IfCond) { 2059 if (!CGF.HaveInsertPoint()) 2060 return; 2061 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 2062 auto &M = CGM.getModule(); 2063 auto &&ThenGen = [&M, OutlinedFn, CapturedVars, RTLoc, 2064 this](CodeGenFunction &CGF, PrePostActionTy &) { 2065 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 2066 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2067 llvm::Value *Args[] = { 2068 RTLoc, 2069 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 2070 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 2071 llvm::SmallVector<llvm::Value *, 16> RealArgs; 2072 RealArgs.append(std::begin(Args), std::end(Args)); 2073 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 2074 2075 llvm::FunctionCallee RTLFn = 2076 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_fork_call); 2077 CGF.EmitRuntimeCall(RTLFn, RealArgs); 2078 }; 2079 auto &&ElseGen = [&M, OutlinedFn, CapturedVars, RTLoc, Loc, 2080 this](CodeGenFunction &CGF, PrePostActionTy &) { 2081 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 2082 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 2083 // Build calls: 2084 // __kmpc_serialized_parallel(&Loc, GTid); 2085 llvm::Value *Args[] = {RTLoc, ThreadID}; 2086 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2087 M, OMPRTL___kmpc_serialized_parallel), 2088 Args); 2089 2090 // OutlinedFn(>id, &zero_bound, CapturedStruct); 2091 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 2092 Address ZeroAddrBound = 2093 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 2094 /*Name=*/".bound.zero.addr"); 2095 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 2096 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 2097 // ThreadId for serialized parallels is 0. 2098 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 2099 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 2100 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 2101 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 2102 2103 // __kmpc_end_serialized_parallel(&Loc, GTid); 2104 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 2105 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2106 M, OMPRTL___kmpc_end_serialized_parallel), 2107 EndArgs); 2108 }; 2109 if (IfCond) { 2110 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 2111 } else { 2112 RegionCodeGenTy ThenRCG(ThenGen); 2113 ThenRCG(CGF); 2114 } 2115 } 2116 2117 // If we're inside an (outlined) parallel region, use the region info's 2118 // thread-ID variable (it is passed in a first argument of the outlined function 2119 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 2120 // regular serial code region, get thread ID by calling kmp_int32 2121 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 2122 // return the address of that temp. 2123 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 2124 SourceLocation Loc) { 2125 if (auto *OMPRegionInfo = 2126 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2127 if (OMPRegionInfo->getThreadIDVariable()) 2128 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 2129 2130 llvm::Value *ThreadID = getThreadID(CGF, Loc); 2131 QualType Int32Ty = 2132 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 2133 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 2134 CGF.EmitStoreOfScalar(ThreadID, 2135 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 2136 2137 return ThreadIDTemp; 2138 } 2139 2140 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 2141 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 2142 SmallString<256> Buffer; 2143 llvm::raw_svector_ostream Out(Buffer); 2144 Out << Name; 2145 StringRef RuntimeName = Out.str(); 2146 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 2147 if (Elem.second) { 2148 assert(Elem.second->getType()->getPointerElementType() == Ty && 2149 "OMP internal variable has different type than requested"); 2150 return &*Elem.second; 2151 } 2152 2153 return Elem.second = new llvm::GlobalVariable( 2154 CGM.getModule(), Ty, /*IsConstant*/ false, 2155 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 2156 Elem.first(), /*InsertBefore=*/nullptr, 2157 llvm::GlobalValue::NotThreadLocal, AddressSpace); 2158 } 2159 2160 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 2161 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 2162 std::string Name = getName({Prefix, "var"}); 2163 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 2164 } 2165 2166 namespace { 2167 /// Common pre(post)-action for different OpenMP constructs. 2168 class CommonActionTy final : public PrePostActionTy { 2169 llvm::FunctionCallee EnterCallee; 2170 ArrayRef<llvm::Value *> EnterArgs; 2171 llvm::FunctionCallee ExitCallee; 2172 ArrayRef<llvm::Value *> ExitArgs; 2173 bool Conditional; 2174 llvm::BasicBlock *ContBlock = nullptr; 2175 2176 public: 2177 CommonActionTy(llvm::FunctionCallee EnterCallee, 2178 ArrayRef<llvm::Value *> EnterArgs, 2179 llvm::FunctionCallee ExitCallee, 2180 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 2181 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 2182 ExitArgs(ExitArgs), Conditional(Conditional) {} 2183 void Enter(CodeGenFunction &CGF) override { 2184 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 2185 if (Conditional) { 2186 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 2187 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2188 ContBlock = CGF.createBasicBlock("omp_if.end"); 2189 // Generate the branch (If-stmt) 2190 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 2191 CGF.EmitBlock(ThenBlock); 2192 } 2193 } 2194 void Done(CodeGenFunction &CGF) { 2195 // Emit the rest of blocks/branches 2196 CGF.EmitBranch(ContBlock); 2197 CGF.EmitBlock(ContBlock, true); 2198 } 2199 void Exit(CodeGenFunction &CGF) override { 2200 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 2201 } 2202 }; 2203 } // anonymous namespace 2204 2205 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 2206 StringRef CriticalName, 2207 const RegionCodeGenTy &CriticalOpGen, 2208 SourceLocation Loc, const Expr *Hint) { 2209 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 2210 // CriticalOpGen(); 2211 // __kmpc_end_critical(ident_t *, gtid, Lock); 2212 // Prepare arguments and build a call to __kmpc_critical 2213 if (!CGF.HaveInsertPoint()) 2214 return; 2215 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2216 getCriticalRegionLock(CriticalName)}; 2217 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 2218 std::end(Args)); 2219 if (Hint) { 2220 EnterArgs.push_back(CGF.Builder.CreateIntCast( 2221 CGF.EmitScalarExpr(Hint), CGM.Int32Ty, /*isSigned=*/false)); 2222 } 2223 CommonActionTy Action( 2224 OMPBuilder.getOrCreateRuntimeFunction( 2225 CGM.getModule(), 2226 Hint ? OMPRTL___kmpc_critical_with_hint : OMPRTL___kmpc_critical), 2227 EnterArgs, 2228 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2229 OMPRTL___kmpc_end_critical), 2230 Args); 2231 CriticalOpGen.setAction(Action); 2232 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 2233 } 2234 2235 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 2236 const RegionCodeGenTy &MasterOpGen, 2237 SourceLocation Loc) { 2238 if (!CGF.HaveInsertPoint()) 2239 return; 2240 // if(__kmpc_master(ident_t *, gtid)) { 2241 // MasterOpGen(); 2242 // __kmpc_end_master(ident_t *, gtid); 2243 // } 2244 // Prepare arguments and build a call to __kmpc_master 2245 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2246 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2247 CGM.getModule(), OMPRTL___kmpc_master), 2248 Args, 2249 OMPBuilder.getOrCreateRuntimeFunction( 2250 CGM.getModule(), OMPRTL___kmpc_end_master), 2251 Args, 2252 /*Conditional=*/true); 2253 MasterOpGen.setAction(Action); 2254 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 2255 Action.Done(CGF); 2256 } 2257 2258 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 2259 SourceLocation Loc) { 2260 if (!CGF.HaveInsertPoint()) 2261 return; 2262 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2263 OMPBuilder.createTaskyield(CGF.Builder); 2264 } else { 2265 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 2266 llvm::Value *Args[] = { 2267 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2268 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 2269 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2270 CGM.getModule(), OMPRTL___kmpc_omp_taskyield), 2271 Args); 2272 } 2273 2274 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 2275 Region->emitUntiedSwitch(CGF); 2276 } 2277 2278 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 2279 const RegionCodeGenTy &TaskgroupOpGen, 2280 SourceLocation Loc) { 2281 if (!CGF.HaveInsertPoint()) 2282 return; 2283 // __kmpc_taskgroup(ident_t *, gtid); 2284 // TaskgroupOpGen(); 2285 // __kmpc_end_taskgroup(ident_t *, gtid); 2286 // Prepare arguments and build a call to __kmpc_taskgroup 2287 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2288 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2289 CGM.getModule(), OMPRTL___kmpc_taskgroup), 2290 Args, 2291 OMPBuilder.getOrCreateRuntimeFunction( 2292 CGM.getModule(), OMPRTL___kmpc_end_taskgroup), 2293 Args); 2294 TaskgroupOpGen.setAction(Action); 2295 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 2296 } 2297 2298 /// Given an array of pointers to variables, project the address of a 2299 /// given variable. 2300 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 2301 unsigned Index, const VarDecl *Var) { 2302 // Pull out the pointer to the variable. 2303 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 2304 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 2305 2306 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 2307 Addr = CGF.Builder.CreateElementBitCast( 2308 Addr, CGF.ConvertTypeForMem(Var->getType())); 2309 return Addr; 2310 } 2311 2312 static llvm::Value *emitCopyprivateCopyFunction( 2313 CodeGenModule &CGM, llvm::Type *ArgsType, 2314 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 2315 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 2316 SourceLocation Loc) { 2317 ASTContext &C = CGM.getContext(); 2318 // void copy_func(void *LHSArg, void *RHSArg); 2319 FunctionArgList Args; 2320 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2321 ImplicitParamDecl::Other); 2322 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 2323 ImplicitParamDecl::Other); 2324 Args.push_back(&LHSArg); 2325 Args.push_back(&RHSArg); 2326 const auto &CGFI = 2327 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 2328 std::string Name = 2329 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 2330 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 2331 llvm::GlobalValue::InternalLinkage, Name, 2332 &CGM.getModule()); 2333 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 2334 Fn->setDoesNotRecurse(); 2335 CodeGenFunction CGF(CGM); 2336 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 2337 // Dest = (void*[n])(LHSArg); 2338 // Src = (void*[n])(RHSArg); 2339 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2340 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 2341 ArgsType), CGF.getPointerAlign()); 2342 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2343 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 2344 ArgsType), CGF.getPointerAlign()); 2345 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 2346 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 2347 // ... 2348 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 2349 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 2350 const auto *DestVar = 2351 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 2352 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 2353 2354 const auto *SrcVar = 2355 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 2356 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 2357 2358 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 2359 QualType Type = VD->getType(); 2360 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 2361 } 2362 CGF.FinishFunction(); 2363 return Fn; 2364 } 2365 2366 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 2367 const RegionCodeGenTy &SingleOpGen, 2368 SourceLocation Loc, 2369 ArrayRef<const Expr *> CopyprivateVars, 2370 ArrayRef<const Expr *> SrcExprs, 2371 ArrayRef<const Expr *> DstExprs, 2372 ArrayRef<const Expr *> AssignmentOps) { 2373 if (!CGF.HaveInsertPoint()) 2374 return; 2375 assert(CopyprivateVars.size() == SrcExprs.size() && 2376 CopyprivateVars.size() == DstExprs.size() && 2377 CopyprivateVars.size() == AssignmentOps.size()); 2378 ASTContext &C = CGM.getContext(); 2379 // int32 did_it = 0; 2380 // if(__kmpc_single(ident_t *, gtid)) { 2381 // SingleOpGen(); 2382 // __kmpc_end_single(ident_t *, gtid); 2383 // did_it = 1; 2384 // } 2385 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2386 // <copy_func>, did_it); 2387 2388 Address DidIt = Address::invalid(); 2389 if (!CopyprivateVars.empty()) { 2390 // int32 did_it = 0; 2391 QualType KmpInt32Ty = 2392 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 2393 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 2394 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 2395 } 2396 // Prepare arguments and build a call to __kmpc_single 2397 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2398 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2399 CGM.getModule(), OMPRTL___kmpc_single), 2400 Args, 2401 OMPBuilder.getOrCreateRuntimeFunction( 2402 CGM.getModule(), OMPRTL___kmpc_end_single), 2403 Args, 2404 /*Conditional=*/true); 2405 SingleOpGen.setAction(Action); 2406 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 2407 if (DidIt.isValid()) { 2408 // did_it = 1; 2409 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 2410 } 2411 Action.Done(CGF); 2412 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 2413 // <copy_func>, did_it); 2414 if (DidIt.isValid()) { 2415 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 2416 QualType CopyprivateArrayTy = C.getConstantArrayType( 2417 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 2418 /*IndexTypeQuals=*/0); 2419 // Create a list of all private variables for copyprivate. 2420 Address CopyprivateList = 2421 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 2422 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 2423 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 2424 CGF.Builder.CreateStore( 2425 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2426 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 2427 CGF.VoidPtrTy), 2428 Elem); 2429 } 2430 // Build function that copies private values from single region to all other 2431 // threads in the corresponding parallel region. 2432 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 2433 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 2434 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 2435 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 2436 Address CL = 2437 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 2438 CGF.VoidPtrTy); 2439 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 2440 llvm::Value *Args[] = { 2441 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 2442 getThreadID(CGF, Loc), // i32 <gtid> 2443 BufSize, // size_t <buf_size> 2444 CL.getPointer(), // void *<copyprivate list> 2445 CpyFn, // void (*) (void *, void *) <copy_func> 2446 DidItVal // i32 did_it 2447 }; 2448 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2449 CGM.getModule(), OMPRTL___kmpc_copyprivate), 2450 Args); 2451 } 2452 } 2453 2454 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 2455 const RegionCodeGenTy &OrderedOpGen, 2456 SourceLocation Loc, bool IsThreads) { 2457 if (!CGF.HaveInsertPoint()) 2458 return; 2459 // __kmpc_ordered(ident_t *, gtid); 2460 // OrderedOpGen(); 2461 // __kmpc_end_ordered(ident_t *, gtid); 2462 // Prepare arguments and build a call to __kmpc_ordered 2463 if (IsThreads) { 2464 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2465 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 2466 CGM.getModule(), OMPRTL___kmpc_ordered), 2467 Args, 2468 OMPBuilder.getOrCreateRuntimeFunction( 2469 CGM.getModule(), OMPRTL___kmpc_end_ordered), 2470 Args); 2471 OrderedOpGen.setAction(Action); 2472 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2473 return; 2474 } 2475 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 2476 } 2477 2478 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 2479 unsigned Flags; 2480 if (Kind == OMPD_for) 2481 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 2482 else if (Kind == OMPD_sections) 2483 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 2484 else if (Kind == OMPD_single) 2485 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 2486 else if (Kind == OMPD_barrier) 2487 Flags = OMP_IDENT_BARRIER_EXPL; 2488 else 2489 Flags = OMP_IDENT_BARRIER_IMPL; 2490 return Flags; 2491 } 2492 2493 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 2494 CodeGenFunction &CGF, const OMPLoopDirective &S, 2495 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 2496 // Check if the loop directive is actually a doacross loop directive. In this 2497 // case choose static, 1 schedule. 2498 if (llvm::any_of( 2499 S.getClausesOfKind<OMPOrderedClause>(), 2500 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 2501 ScheduleKind = OMPC_SCHEDULE_static; 2502 // Chunk size is 1 in this case. 2503 llvm::APInt ChunkSize(32, 1); 2504 ChunkExpr = IntegerLiteral::Create( 2505 CGF.getContext(), ChunkSize, 2506 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 2507 SourceLocation()); 2508 } 2509 } 2510 2511 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 2512 OpenMPDirectiveKind Kind, bool EmitChecks, 2513 bool ForceSimpleCall) { 2514 // Check if we should use the OMPBuilder 2515 auto *OMPRegionInfo = 2516 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 2517 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2518 CGF.Builder.restoreIP(OMPBuilder.createBarrier( 2519 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 2520 return; 2521 } 2522 2523 if (!CGF.HaveInsertPoint()) 2524 return; 2525 // Build call __kmpc_cancel_barrier(loc, thread_id); 2526 // Build call __kmpc_barrier(loc, thread_id); 2527 unsigned Flags = getDefaultFlagsForBarriers(Kind); 2528 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 2529 // thread_id); 2530 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 2531 getThreadID(CGF, Loc)}; 2532 if (OMPRegionInfo) { 2533 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 2534 llvm::Value *Result = CGF.EmitRuntimeCall( 2535 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 2536 OMPRTL___kmpc_cancel_barrier), 2537 Args); 2538 if (EmitChecks) { 2539 // if (__kmpc_cancel_barrier()) { 2540 // exit from construct; 2541 // } 2542 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 2543 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 2544 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 2545 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 2546 CGF.EmitBlock(ExitBB); 2547 // exit from construct; 2548 CodeGenFunction::JumpDest CancelDestination = 2549 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 2550 CGF.EmitBranchThroughCleanup(CancelDestination); 2551 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 2552 } 2553 return; 2554 } 2555 } 2556 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2557 CGM.getModule(), OMPRTL___kmpc_barrier), 2558 Args); 2559 } 2560 2561 /// Map the OpenMP loop schedule to the runtime enumeration. 2562 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 2563 bool Chunked, bool Ordered) { 2564 switch (ScheduleKind) { 2565 case OMPC_SCHEDULE_static: 2566 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 2567 : (Ordered ? OMP_ord_static : OMP_sch_static); 2568 case OMPC_SCHEDULE_dynamic: 2569 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 2570 case OMPC_SCHEDULE_guided: 2571 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 2572 case OMPC_SCHEDULE_runtime: 2573 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 2574 case OMPC_SCHEDULE_auto: 2575 return Ordered ? OMP_ord_auto : OMP_sch_auto; 2576 case OMPC_SCHEDULE_unknown: 2577 assert(!Chunked && "chunk was specified but schedule kind not known"); 2578 return Ordered ? OMP_ord_static : OMP_sch_static; 2579 } 2580 llvm_unreachable("Unexpected runtime schedule"); 2581 } 2582 2583 /// Map the OpenMP distribute schedule to the runtime enumeration. 2584 static OpenMPSchedType 2585 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 2586 // only static is allowed for dist_schedule 2587 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 2588 } 2589 2590 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 2591 bool Chunked) const { 2592 OpenMPSchedType Schedule = 2593 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2594 return Schedule == OMP_sch_static; 2595 } 2596 2597 bool CGOpenMPRuntime::isStaticNonchunked( 2598 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2599 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2600 return Schedule == OMP_dist_sch_static; 2601 } 2602 2603 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 2604 bool Chunked) const { 2605 OpenMPSchedType Schedule = 2606 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 2607 return Schedule == OMP_sch_static_chunked; 2608 } 2609 2610 bool CGOpenMPRuntime::isStaticChunked( 2611 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 2612 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 2613 return Schedule == OMP_dist_sch_static_chunked; 2614 } 2615 2616 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 2617 OpenMPSchedType Schedule = 2618 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 2619 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 2620 return Schedule != OMP_sch_static; 2621 } 2622 2623 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 2624 OpenMPScheduleClauseModifier M1, 2625 OpenMPScheduleClauseModifier M2) { 2626 int Modifier = 0; 2627 switch (M1) { 2628 case OMPC_SCHEDULE_MODIFIER_monotonic: 2629 Modifier = OMP_sch_modifier_monotonic; 2630 break; 2631 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2632 Modifier = OMP_sch_modifier_nonmonotonic; 2633 break; 2634 case OMPC_SCHEDULE_MODIFIER_simd: 2635 if (Schedule == OMP_sch_static_chunked) 2636 Schedule = OMP_sch_static_balanced_chunked; 2637 break; 2638 case OMPC_SCHEDULE_MODIFIER_last: 2639 case OMPC_SCHEDULE_MODIFIER_unknown: 2640 break; 2641 } 2642 switch (M2) { 2643 case OMPC_SCHEDULE_MODIFIER_monotonic: 2644 Modifier = OMP_sch_modifier_monotonic; 2645 break; 2646 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 2647 Modifier = OMP_sch_modifier_nonmonotonic; 2648 break; 2649 case OMPC_SCHEDULE_MODIFIER_simd: 2650 if (Schedule == OMP_sch_static_chunked) 2651 Schedule = OMP_sch_static_balanced_chunked; 2652 break; 2653 case OMPC_SCHEDULE_MODIFIER_last: 2654 case OMPC_SCHEDULE_MODIFIER_unknown: 2655 break; 2656 } 2657 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 2658 // If the static schedule kind is specified or if the ordered clause is 2659 // specified, and if the nonmonotonic modifier is not specified, the effect is 2660 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 2661 // modifier is specified, the effect is as if the nonmonotonic modifier is 2662 // specified. 2663 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 2664 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 2665 Schedule == OMP_sch_static_balanced_chunked || 2666 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 2667 Schedule == OMP_dist_sch_static_chunked || 2668 Schedule == OMP_dist_sch_static)) 2669 Modifier = OMP_sch_modifier_nonmonotonic; 2670 } 2671 return Schedule | Modifier; 2672 } 2673 2674 void CGOpenMPRuntime::emitForDispatchInit( 2675 CodeGenFunction &CGF, SourceLocation Loc, 2676 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 2677 bool Ordered, const DispatchRTInput &DispatchValues) { 2678 if (!CGF.HaveInsertPoint()) 2679 return; 2680 OpenMPSchedType Schedule = getRuntimeSchedule( 2681 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 2682 assert(Ordered || 2683 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 2684 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 2685 Schedule != OMP_sch_static_balanced_chunked)); 2686 // Call __kmpc_dispatch_init( 2687 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 2688 // kmp_int[32|64] lower, kmp_int[32|64] upper, 2689 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 2690 2691 // If the Chunk was not specified in the clause - use default value 1. 2692 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 2693 : CGF.Builder.getIntN(IVSize, 1); 2694 llvm::Value *Args[] = { 2695 emitUpdateLocation(CGF, Loc), 2696 getThreadID(CGF, Loc), 2697 CGF.Builder.getInt32(addMonoNonMonoModifier( 2698 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 2699 DispatchValues.LB, // Lower 2700 DispatchValues.UB, // Upper 2701 CGF.Builder.getIntN(IVSize, 1), // Stride 2702 Chunk // Chunk 2703 }; 2704 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 2705 } 2706 2707 static void emitForStaticInitCall( 2708 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 2709 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 2710 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 2711 const CGOpenMPRuntime::StaticRTInput &Values) { 2712 if (!CGF.HaveInsertPoint()) 2713 return; 2714 2715 assert(!Values.Ordered); 2716 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 2717 Schedule == OMP_sch_static_balanced_chunked || 2718 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 2719 Schedule == OMP_dist_sch_static || 2720 Schedule == OMP_dist_sch_static_chunked); 2721 2722 // Call __kmpc_for_static_init( 2723 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 2724 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 2725 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 2726 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 2727 llvm::Value *Chunk = Values.Chunk; 2728 if (Chunk == nullptr) { 2729 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 2730 Schedule == OMP_dist_sch_static) && 2731 "expected static non-chunked schedule"); 2732 // If the Chunk was not specified in the clause - use default value 1. 2733 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 2734 } else { 2735 assert((Schedule == OMP_sch_static_chunked || 2736 Schedule == OMP_sch_static_balanced_chunked || 2737 Schedule == OMP_ord_static_chunked || 2738 Schedule == OMP_dist_sch_static_chunked) && 2739 "expected static chunked schedule"); 2740 } 2741 llvm::Value *Args[] = { 2742 UpdateLocation, 2743 ThreadId, 2744 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 2745 M2)), // Schedule type 2746 Values.IL.getPointer(), // &isLastIter 2747 Values.LB.getPointer(), // &LB 2748 Values.UB.getPointer(), // &UB 2749 Values.ST.getPointer(), // &Stride 2750 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 2751 Chunk // Chunk 2752 }; 2753 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 2754 } 2755 2756 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 2757 SourceLocation Loc, 2758 OpenMPDirectiveKind DKind, 2759 const OpenMPScheduleTy &ScheduleKind, 2760 const StaticRTInput &Values) { 2761 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 2762 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 2763 assert(isOpenMPWorksharingDirective(DKind) && 2764 "Expected loop-based or sections-based directive."); 2765 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 2766 isOpenMPLoopDirective(DKind) 2767 ? OMP_IDENT_WORK_LOOP 2768 : OMP_IDENT_WORK_SECTIONS); 2769 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2770 llvm::FunctionCallee StaticInitFunction = 2771 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 2772 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2773 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2774 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 2775 } 2776 2777 void CGOpenMPRuntime::emitDistributeStaticInit( 2778 CodeGenFunction &CGF, SourceLocation Loc, 2779 OpenMPDistScheduleClauseKind SchedKind, 2780 const CGOpenMPRuntime::StaticRTInput &Values) { 2781 OpenMPSchedType ScheduleNum = 2782 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 2783 llvm::Value *UpdatedLocation = 2784 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 2785 llvm::Value *ThreadId = getThreadID(CGF, Loc); 2786 llvm::FunctionCallee StaticInitFunction = 2787 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 2788 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 2789 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 2790 OMPC_SCHEDULE_MODIFIER_unknown, Values); 2791 } 2792 2793 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 2794 SourceLocation Loc, 2795 OpenMPDirectiveKind DKind) { 2796 if (!CGF.HaveInsertPoint()) 2797 return; 2798 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 2799 llvm::Value *Args[] = { 2800 emitUpdateLocation(CGF, Loc, 2801 isOpenMPDistributeDirective(DKind) 2802 ? OMP_IDENT_WORK_DISTRIBUTE 2803 : isOpenMPLoopDirective(DKind) 2804 ? OMP_IDENT_WORK_LOOP 2805 : OMP_IDENT_WORK_SECTIONS), 2806 getThreadID(CGF, Loc)}; 2807 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 2808 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2809 CGM.getModule(), OMPRTL___kmpc_for_static_fini), 2810 Args); 2811 } 2812 2813 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 2814 SourceLocation Loc, 2815 unsigned IVSize, 2816 bool IVSigned) { 2817 if (!CGF.HaveInsertPoint()) 2818 return; 2819 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 2820 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 2821 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 2822 } 2823 2824 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 2825 SourceLocation Loc, unsigned IVSize, 2826 bool IVSigned, Address IL, 2827 Address LB, Address UB, 2828 Address ST) { 2829 // Call __kmpc_dispatch_next( 2830 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 2831 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 2832 // kmp_int[32|64] *p_stride); 2833 llvm::Value *Args[] = { 2834 emitUpdateLocation(CGF, Loc), 2835 getThreadID(CGF, Loc), 2836 IL.getPointer(), // &isLastIter 2837 LB.getPointer(), // &Lower 2838 UB.getPointer(), // &Upper 2839 ST.getPointer() // &Stride 2840 }; 2841 llvm::Value *Call = 2842 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 2843 return CGF.EmitScalarConversion( 2844 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 2845 CGF.getContext().BoolTy, Loc); 2846 } 2847 2848 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 2849 llvm::Value *NumThreads, 2850 SourceLocation Loc) { 2851 if (!CGF.HaveInsertPoint()) 2852 return; 2853 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 2854 llvm::Value *Args[] = { 2855 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2856 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 2857 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2858 CGM.getModule(), OMPRTL___kmpc_push_num_threads), 2859 Args); 2860 } 2861 2862 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 2863 ProcBindKind ProcBind, 2864 SourceLocation Loc) { 2865 if (!CGF.HaveInsertPoint()) 2866 return; 2867 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 2868 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 2869 llvm::Value *Args[] = { 2870 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2871 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 2872 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2873 CGM.getModule(), OMPRTL___kmpc_push_proc_bind), 2874 Args); 2875 } 2876 2877 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 2878 SourceLocation Loc, llvm::AtomicOrdering AO) { 2879 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 2880 OMPBuilder.createFlush(CGF.Builder); 2881 } else { 2882 if (!CGF.HaveInsertPoint()) 2883 return; 2884 // Build call void __kmpc_flush(ident_t *loc) 2885 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 2886 CGM.getModule(), OMPRTL___kmpc_flush), 2887 emitUpdateLocation(CGF, Loc)); 2888 } 2889 } 2890 2891 namespace { 2892 /// Indexes of fields for type kmp_task_t. 2893 enum KmpTaskTFields { 2894 /// List of shared variables. 2895 KmpTaskTShareds, 2896 /// Task routine. 2897 KmpTaskTRoutine, 2898 /// Partition id for the untied tasks. 2899 KmpTaskTPartId, 2900 /// Function with call of destructors for private variables. 2901 Data1, 2902 /// Task priority. 2903 Data2, 2904 /// (Taskloops only) Lower bound. 2905 KmpTaskTLowerBound, 2906 /// (Taskloops only) Upper bound. 2907 KmpTaskTUpperBound, 2908 /// (Taskloops only) Stride. 2909 KmpTaskTStride, 2910 /// (Taskloops only) Is last iteration flag. 2911 KmpTaskTLastIter, 2912 /// (Taskloops only) Reduction data. 2913 KmpTaskTReductions, 2914 }; 2915 } // anonymous namespace 2916 2917 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 2918 return OffloadEntriesTargetRegion.empty() && 2919 OffloadEntriesDeviceGlobalVar.empty(); 2920 } 2921 2922 /// Initialize target region entry. 2923 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2924 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2925 StringRef ParentName, unsigned LineNum, 2926 unsigned Order) { 2927 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 2928 "only required for the device " 2929 "code generation."); 2930 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 2931 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 2932 OMPTargetRegionEntryTargetRegion); 2933 ++OffloadingEntriesNum; 2934 } 2935 2936 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 2937 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 2938 StringRef ParentName, unsigned LineNum, 2939 llvm::Constant *Addr, llvm::Constant *ID, 2940 OMPTargetRegionEntryKind Flags) { 2941 // If we are emitting code for a target, the entry is already initialized, 2942 // only has to be registered. 2943 if (CGM.getLangOpts().OpenMPIsDevice) { 2944 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 2945 unsigned DiagID = CGM.getDiags().getCustomDiagID( 2946 DiagnosticsEngine::Error, 2947 "Unable to find target region on line '%0' in the device code."); 2948 CGM.getDiags().Report(DiagID) << LineNum; 2949 return; 2950 } 2951 auto &Entry = 2952 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 2953 assert(Entry.isValid() && "Entry not initialized!"); 2954 Entry.setAddress(Addr); 2955 Entry.setID(ID); 2956 Entry.setFlags(Flags); 2957 } else { 2958 if (Flags == 2959 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion && 2960 hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum, 2961 /*IgnoreAddressId*/ true)) 2962 return; 2963 assert(!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum) && 2964 "Target region entry already registered!"); 2965 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 2966 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 2967 ++OffloadingEntriesNum; 2968 } 2969 } 2970 2971 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 2972 unsigned DeviceID, unsigned FileID, StringRef ParentName, unsigned LineNum, 2973 bool IgnoreAddressId) const { 2974 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 2975 if (PerDevice == OffloadEntriesTargetRegion.end()) 2976 return false; 2977 auto PerFile = PerDevice->second.find(FileID); 2978 if (PerFile == PerDevice->second.end()) 2979 return false; 2980 auto PerParentName = PerFile->second.find(ParentName); 2981 if (PerParentName == PerFile->second.end()) 2982 return false; 2983 auto PerLine = PerParentName->second.find(LineNum); 2984 if (PerLine == PerParentName->second.end()) 2985 return false; 2986 // Fail if this entry is already registered. 2987 if (!IgnoreAddressId && 2988 (PerLine->second.getAddress() || PerLine->second.getID())) 2989 return false; 2990 return true; 2991 } 2992 2993 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 2994 const OffloadTargetRegionEntryInfoActTy &Action) { 2995 // Scan all target region entries and perform the provided action. 2996 for (const auto &D : OffloadEntriesTargetRegion) 2997 for (const auto &F : D.second) 2998 for (const auto &P : F.second) 2999 for (const auto &L : P.second) 3000 Action(D.first, F.first, P.first(), L.first, L.second); 3001 } 3002 3003 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3004 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3005 OMPTargetGlobalVarEntryKind Flags, 3006 unsigned Order) { 3007 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3008 "only required for the device " 3009 "code generation."); 3010 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3011 ++OffloadingEntriesNum; 3012 } 3013 3014 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3015 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3016 CharUnits VarSize, 3017 OMPTargetGlobalVarEntryKind Flags, 3018 llvm::GlobalValue::LinkageTypes Linkage) { 3019 if (CGM.getLangOpts().OpenMPIsDevice) { 3020 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3021 assert(Entry.isValid() && Entry.getFlags() == Flags && 3022 "Entry not initialized!"); 3023 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3024 "Resetting with the new address."); 3025 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3026 if (Entry.getVarSize().isZero()) { 3027 Entry.setVarSize(VarSize); 3028 Entry.setLinkage(Linkage); 3029 } 3030 return; 3031 } 3032 Entry.setVarSize(VarSize); 3033 Entry.setLinkage(Linkage); 3034 Entry.setAddress(Addr); 3035 } else { 3036 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3037 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3038 assert(Entry.isValid() && Entry.getFlags() == Flags && 3039 "Entry not initialized!"); 3040 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3041 "Resetting with the new address."); 3042 if (Entry.getVarSize().isZero()) { 3043 Entry.setVarSize(VarSize); 3044 Entry.setLinkage(Linkage); 3045 } 3046 return; 3047 } 3048 OffloadEntriesDeviceGlobalVar.try_emplace( 3049 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3050 ++OffloadingEntriesNum; 3051 } 3052 } 3053 3054 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3055 actOnDeviceGlobalVarEntriesInfo( 3056 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 3057 // Scan all target region entries and perform the provided action. 3058 for (const auto &E : OffloadEntriesDeviceGlobalVar) 3059 Action(E.getKey(), E.getValue()); 3060 } 3061 3062 void CGOpenMPRuntime::createOffloadEntry( 3063 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 3064 llvm::GlobalValue::LinkageTypes Linkage) { 3065 StringRef Name = Addr->getName(); 3066 llvm::Module &M = CGM.getModule(); 3067 llvm::LLVMContext &C = M.getContext(); 3068 3069 // Create constant string with the name. 3070 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 3071 3072 std::string StringName = getName({"omp_offloading", "entry_name"}); 3073 auto *Str = new llvm::GlobalVariable( 3074 M, StrPtrInit->getType(), /*isConstant=*/true, 3075 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 3076 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 3077 3078 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 3079 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 3080 llvm::ConstantInt::get(CGM.SizeTy, Size), 3081 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 3082 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 3083 std::string EntryName = getName({"omp_offloading", "entry", ""}); 3084 llvm::GlobalVariable *Entry = createGlobalStruct( 3085 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 3086 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 3087 3088 // The entry has to be created in the section the linker expects it to be. 3089 Entry->setSection("omp_offloading_entries"); 3090 } 3091 3092 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 3093 // Emit the offloading entries and metadata so that the device codegen side 3094 // can easily figure out what to emit. The produced metadata looks like 3095 // this: 3096 // 3097 // !omp_offload.info = !{!1, ...} 3098 // 3099 // Right now we only generate metadata for function that contain target 3100 // regions. 3101 3102 // If we are in simd mode or there are no entries, we don't need to do 3103 // anything. 3104 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 3105 return; 3106 3107 llvm::Module &M = CGM.getModule(); 3108 llvm::LLVMContext &C = M.getContext(); 3109 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 3110 SourceLocation, StringRef>, 3111 16> 3112 OrderedEntries(OffloadEntriesInfoManager.size()); 3113 llvm::SmallVector<StringRef, 16> ParentFunctions( 3114 OffloadEntriesInfoManager.size()); 3115 3116 // Auxiliary methods to create metadata values and strings. 3117 auto &&GetMDInt = [this](unsigned V) { 3118 return llvm::ConstantAsMetadata::get( 3119 llvm::ConstantInt::get(CGM.Int32Ty, V)); 3120 }; 3121 3122 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 3123 3124 // Create the offloading info metadata node. 3125 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 3126 3127 // Create function that emits metadata for each target region entry; 3128 auto &&TargetRegionMetadataEmitter = 3129 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 3130 &GetMDString]( 3131 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3132 unsigned Line, 3133 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 3134 // Generate metadata for target regions. Each entry of this metadata 3135 // contains: 3136 // - Entry 0 -> Kind of this type of metadata (0). 3137 // - Entry 1 -> Device ID of the file where the entry was identified. 3138 // - Entry 2 -> File ID of the file where the entry was identified. 3139 // - Entry 3 -> Mangled name of the function where the entry was 3140 // identified. 3141 // - Entry 4 -> Line in the file where the entry was identified. 3142 // - Entry 5 -> Order the entry was created. 3143 // The first element of the metadata node is the kind. 3144 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 3145 GetMDInt(FileID), GetMDString(ParentName), 3146 GetMDInt(Line), GetMDInt(E.getOrder())}; 3147 3148 SourceLocation Loc; 3149 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 3150 E = CGM.getContext().getSourceManager().fileinfo_end(); 3151 I != E; ++I) { 3152 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 3153 I->getFirst()->getUniqueID().getFile() == FileID) { 3154 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 3155 I->getFirst(), Line, 1); 3156 break; 3157 } 3158 } 3159 // Save this entry in the right position of the ordered entries array. 3160 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 3161 ParentFunctions[E.getOrder()] = ParentName; 3162 3163 // Add metadata to the named metadata node. 3164 MD->addOperand(llvm::MDNode::get(C, Ops)); 3165 }; 3166 3167 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 3168 TargetRegionMetadataEmitter); 3169 3170 // Create function that emits metadata for each device global variable entry; 3171 auto &&DeviceGlobalVarMetadataEmitter = 3172 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 3173 MD](StringRef MangledName, 3174 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 3175 &E) { 3176 // Generate metadata for global variables. Each entry of this metadata 3177 // contains: 3178 // - Entry 0 -> Kind of this type of metadata (1). 3179 // - Entry 1 -> Mangled name of the variable. 3180 // - Entry 2 -> Declare target kind. 3181 // - Entry 3 -> Order the entry was created. 3182 // The first element of the metadata node is the kind. 3183 llvm::Metadata *Ops[] = { 3184 GetMDInt(E.getKind()), GetMDString(MangledName), 3185 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 3186 3187 // Save this entry in the right position of the ordered entries array. 3188 OrderedEntries[E.getOrder()] = 3189 std::make_tuple(&E, SourceLocation(), MangledName); 3190 3191 // Add metadata to the named metadata node. 3192 MD->addOperand(llvm::MDNode::get(C, Ops)); 3193 }; 3194 3195 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 3196 DeviceGlobalVarMetadataEmitter); 3197 3198 for (const auto &E : OrderedEntries) { 3199 assert(std::get<0>(E) && "All ordered entries must exist!"); 3200 if (const auto *CE = 3201 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 3202 std::get<0>(E))) { 3203 if (!CE->getID() || !CE->getAddress()) { 3204 // Do not blame the entry if the parent funtion is not emitted. 3205 StringRef FnName = ParentFunctions[CE->getOrder()]; 3206 if (!CGM.GetGlobalValue(FnName)) 3207 continue; 3208 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3209 DiagnosticsEngine::Error, 3210 "Offloading entry for target region in %0 is incorrect: either the " 3211 "address or the ID is invalid."); 3212 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 3213 continue; 3214 } 3215 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 3216 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 3217 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 3218 OffloadEntryInfoDeviceGlobalVar>( 3219 std::get<0>(E))) { 3220 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 3221 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3222 CE->getFlags()); 3223 switch (Flags) { 3224 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 3225 if (CGM.getLangOpts().OpenMPIsDevice && 3226 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 3227 continue; 3228 if (!CE->getAddress()) { 3229 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3230 DiagnosticsEngine::Error, "Offloading entry for declare target " 3231 "variable %0 is incorrect: the " 3232 "address is invalid."); 3233 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 3234 continue; 3235 } 3236 // The vaiable has no definition - no need to add the entry. 3237 if (CE->getVarSize().isZero()) 3238 continue; 3239 break; 3240 } 3241 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 3242 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 3243 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 3244 "Declaret target link address is set."); 3245 if (CGM.getLangOpts().OpenMPIsDevice) 3246 continue; 3247 if (!CE->getAddress()) { 3248 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3249 DiagnosticsEngine::Error, 3250 "Offloading entry for declare target variable is incorrect: the " 3251 "address is invalid."); 3252 CGM.getDiags().Report(DiagID); 3253 continue; 3254 } 3255 break; 3256 } 3257 createOffloadEntry(CE->getAddress(), CE->getAddress(), 3258 CE->getVarSize().getQuantity(), Flags, 3259 CE->getLinkage()); 3260 } else { 3261 llvm_unreachable("Unsupported entry kind."); 3262 } 3263 } 3264 } 3265 3266 /// Loads all the offload entries information from the host IR 3267 /// metadata. 3268 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 3269 // If we are in target mode, load the metadata from the host IR. This code has 3270 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 3271 3272 if (!CGM.getLangOpts().OpenMPIsDevice) 3273 return; 3274 3275 if (CGM.getLangOpts().OMPHostIRFile.empty()) 3276 return; 3277 3278 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 3279 if (auto EC = Buf.getError()) { 3280 CGM.getDiags().Report(diag::err_cannot_open_file) 3281 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3282 return; 3283 } 3284 3285 llvm::LLVMContext C; 3286 auto ME = expectedToErrorOrAndEmitErrors( 3287 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 3288 3289 if (auto EC = ME.getError()) { 3290 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3291 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 3292 CGM.getDiags().Report(DiagID) 3293 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 3294 return; 3295 } 3296 3297 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 3298 if (!MD) 3299 return; 3300 3301 for (llvm::MDNode *MN : MD->operands()) { 3302 auto &&GetMDInt = [MN](unsigned Idx) { 3303 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 3304 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 3305 }; 3306 3307 auto &&GetMDString = [MN](unsigned Idx) { 3308 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 3309 return V->getString(); 3310 }; 3311 3312 switch (GetMDInt(0)) { 3313 default: 3314 llvm_unreachable("Unexpected metadata!"); 3315 break; 3316 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3317 OffloadingEntryInfoTargetRegion: 3318 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 3319 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 3320 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 3321 /*Order=*/GetMDInt(5)); 3322 break; 3323 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 3324 OffloadingEntryInfoDeviceGlobalVar: 3325 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 3326 /*MangledName=*/GetMDString(1), 3327 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 3328 /*Flags=*/GetMDInt(2)), 3329 /*Order=*/GetMDInt(3)); 3330 break; 3331 } 3332 } 3333 } 3334 3335 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 3336 if (!KmpRoutineEntryPtrTy) { 3337 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 3338 ASTContext &C = CGM.getContext(); 3339 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 3340 FunctionProtoType::ExtProtoInfo EPI; 3341 KmpRoutineEntryPtrQTy = C.getPointerType( 3342 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 3343 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 3344 } 3345 } 3346 3347 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 3348 // Make sure the type of the entry is already created. This is the type we 3349 // have to create: 3350 // struct __tgt_offload_entry{ 3351 // void *addr; // Pointer to the offload entry info. 3352 // // (function or global) 3353 // char *name; // Name of the function or global. 3354 // size_t size; // Size of the entry info (0 if it a function). 3355 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 3356 // int32_t reserved; // Reserved, to use by the runtime library. 3357 // }; 3358 if (TgtOffloadEntryQTy.isNull()) { 3359 ASTContext &C = CGM.getContext(); 3360 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 3361 RD->startDefinition(); 3362 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3363 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 3364 addFieldToRecordDecl(C, RD, C.getSizeType()); 3365 addFieldToRecordDecl( 3366 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3367 addFieldToRecordDecl( 3368 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 3369 RD->completeDefinition(); 3370 RD->addAttr(PackedAttr::CreateImplicit(C)); 3371 TgtOffloadEntryQTy = C.getRecordType(RD); 3372 } 3373 return TgtOffloadEntryQTy; 3374 } 3375 3376 namespace { 3377 struct PrivateHelpersTy { 3378 PrivateHelpersTy(const Expr *OriginalRef, const VarDecl *Original, 3379 const VarDecl *PrivateCopy, const VarDecl *PrivateElemInit) 3380 : OriginalRef(OriginalRef), Original(Original), PrivateCopy(PrivateCopy), 3381 PrivateElemInit(PrivateElemInit) {} 3382 PrivateHelpersTy(const VarDecl *Original) : Original(Original) {} 3383 const Expr *OriginalRef = nullptr; 3384 const VarDecl *Original = nullptr; 3385 const VarDecl *PrivateCopy = nullptr; 3386 const VarDecl *PrivateElemInit = nullptr; 3387 bool isLocalPrivate() const { 3388 return !OriginalRef && !PrivateCopy && !PrivateElemInit; 3389 } 3390 }; 3391 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 3392 } // anonymous namespace 3393 3394 static bool isAllocatableDecl(const VarDecl *VD) { 3395 const VarDecl *CVD = VD->getCanonicalDecl(); 3396 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 3397 return false; 3398 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 3399 // Use the default allocation. 3400 return !((AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc || 3401 AA->getAllocatorType() == OMPAllocateDeclAttr::OMPNullMemAlloc) && 3402 !AA->getAllocator()); 3403 } 3404 3405 static RecordDecl * 3406 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 3407 if (!Privates.empty()) { 3408 ASTContext &C = CGM.getContext(); 3409 // Build struct .kmp_privates_t. { 3410 // /* private vars */ 3411 // }; 3412 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 3413 RD->startDefinition(); 3414 for (const auto &Pair : Privates) { 3415 const VarDecl *VD = Pair.second.Original; 3416 QualType Type = VD->getType().getNonReferenceType(); 3417 // If the private variable is a local variable with lvalue ref type, 3418 // allocate the pointer instead of the pointee type. 3419 if (Pair.second.isLocalPrivate()) { 3420 if (VD->getType()->isLValueReferenceType()) 3421 Type = C.getPointerType(Type); 3422 if (isAllocatableDecl(VD)) 3423 Type = C.getPointerType(Type); 3424 } 3425 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 3426 if (VD->hasAttrs()) { 3427 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 3428 E(VD->getAttrs().end()); 3429 I != E; ++I) 3430 FD->addAttr(*I); 3431 } 3432 } 3433 RD->completeDefinition(); 3434 return RD; 3435 } 3436 return nullptr; 3437 } 3438 3439 static RecordDecl * 3440 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 3441 QualType KmpInt32Ty, 3442 QualType KmpRoutineEntryPointerQTy) { 3443 ASTContext &C = CGM.getContext(); 3444 // Build struct kmp_task_t { 3445 // void * shareds; 3446 // kmp_routine_entry_t routine; 3447 // kmp_int32 part_id; 3448 // kmp_cmplrdata_t data1; 3449 // kmp_cmplrdata_t data2; 3450 // For taskloops additional fields: 3451 // kmp_uint64 lb; 3452 // kmp_uint64 ub; 3453 // kmp_int64 st; 3454 // kmp_int32 liter; 3455 // void * reductions; 3456 // }; 3457 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 3458 UD->startDefinition(); 3459 addFieldToRecordDecl(C, UD, KmpInt32Ty); 3460 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 3461 UD->completeDefinition(); 3462 QualType KmpCmplrdataTy = C.getRecordType(UD); 3463 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 3464 RD->startDefinition(); 3465 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3466 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 3467 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3468 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3469 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 3470 if (isOpenMPTaskLoopDirective(Kind)) { 3471 QualType KmpUInt64Ty = 3472 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 3473 QualType KmpInt64Ty = 3474 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 3475 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3476 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 3477 addFieldToRecordDecl(C, RD, KmpInt64Ty); 3478 addFieldToRecordDecl(C, RD, KmpInt32Ty); 3479 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 3480 } 3481 RD->completeDefinition(); 3482 return RD; 3483 } 3484 3485 static RecordDecl * 3486 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 3487 ArrayRef<PrivateDataTy> Privates) { 3488 ASTContext &C = CGM.getContext(); 3489 // Build struct kmp_task_t_with_privates { 3490 // kmp_task_t task_data; 3491 // .kmp_privates_t. privates; 3492 // }; 3493 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 3494 RD->startDefinition(); 3495 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 3496 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 3497 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 3498 RD->completeDefinition(); 3499 return RD; 3500 } 3501 3502 /// Emit a proxy function which accepts kmp_task_t as the second 3503 /// argument. 3504 /// \code 3505 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 3506 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 3507 /// For taskloops: 3508 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3509 /// tt->reductions, tt->shareds); 3510 /// return 0; 3511 /// } 3512 /// \endcode 3513 static llvm::Function * 3514 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 3515 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 3516 QualType KmpTaskTWithPrivatesPtrQTy, 3517 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 3518 QualType SharedsPtrTy, llvm::Function *TaskFunction, 3519 llvm::Value *TaskPrivatesMap) { 3520 ASTContext &C = CGM.getContext(); 3521 FunctionArgList Args; 3522 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3523 ImplicitParamDecl::Other); 3524 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3525 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3526 ImplicitParamDecl::Other); 3527 Args.push_back(&GtidArg); 3528 Args.push_back(&TaskTypeArg); 3529 const auto &TaskEntryFnInfo = 3530 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3531 llvm::FunctionType *TaskEntryTy = 3532 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 3533 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 3534 auto *TaskEntry = llvm::Function::Create( 3535 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3536 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 3537 TaskEntry->setDoesNotRecurse(); 3538 CodeGenFunction CGF(CGM); 3539 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 3540 Loc, Loc); 3541 3542 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 3543 // tt, 3544 // For taskloops: 3545 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 3546 // tt->task_data.shareds); 3547 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 3548 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 3549 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3550 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3551 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3552 const auto *KmpTaskTWithPrivatesQTyRD = 3553 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3554 LValue Base = 3555 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3556 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 3557 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 3558 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 3559 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 3560 3561 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 3562 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 3563 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3564 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 3565 CGF.ConvertTypeForMem(SharedsPtrTy)); 3566 3567 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 3568 llvm::Value *PrivatesParam; 3569 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 3570 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 3571 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3572 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 3573 } else { 3574 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 3575 } 3576 3577 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 3578 TaskPrivatesMap, 3579 CGF.Builder 3580 .CreatePointerBitCastOrAddrSpaceCast( 3581 TDBase.getAddress(CGF), CGF.VoidPtrTy) 3582 .getPointer()}; 3583 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 3584 std::end(CommonArgs)); 3585 if (isOpenMPTaskLoopDirective(Kind)) { 3586 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 3587 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 3588 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 3589 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 3590 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 3591 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 3592 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 3593 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 3594 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 3595 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3596 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3597 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 3598 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 3599 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 3600 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 3601 CallArgs.push_back(LBParam); 3602 CallArgs.push_back(UBParam); 3603 CallArgs.push_back(StParam); 3604 CallArgs.push_back(LIParam); 3605 CallArgs.push_back(RParam); 3606 } 3607 CallArgs.push_back(SharedsParam); 3608 3609 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 3610 CallArgs); 3611 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 3612 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 3613 CGF.FinishFunction(); 3614 return TaskEntry; 3615 } 3616 3617 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 3618 SourceLocation Loc, 3619 QualType KmpInt32Ty, 3620 QualType KmpTaskTWithPrivatesPtrQTy, 3621 QualType KmpTaskTWithPrivatesQTy) { 3622 ASTContext &C = CGM.getContext(); 3623 FunctionArgList Args; 3624 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 3625 ImplicitParamDecl::Other); 3626 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3627 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 3628 ImplicitParamDecl::Other); 3629 Args.push_back(&GtidArg); 3630 Args.push_back(&TaskTypeArg); 3631 const auto &DestructorFnInfo = 3632 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 3633 llvm::FunctionType *DestructorFnTy = 3634 CGM.getTypes().GetFunctionType(DestructorFnInfo); 3635 std::string Name = 3636 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 3637 auto *DestructorFn = 3638 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 3639 Name, &CGM.getModule()); 3640 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 3641 DestructorFnInfo); 3642 DestructorFn->setDoesNotRecurse(); 3643 CodeGenFunction CGF(CGM); 3644 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 3645 Args, Loc, Loc); 3646 3647 LValue Base = CGF.EmitLoadOfPointerLValue( 3648 CGF.GetAddrOfLocalVar(&TaskTypeArg), 3649 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3650 const auto *KmpTaskTWithPrivatesQTyRD = 3651 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 3652 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3653 Base = CGF.EmitLValueForField(Base, *FI); 3654 for (const auto *Field : 3655 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 3656 if (QualType::DestructionKind DtorKind = 3657 Field->getType().isDestructedType()) { 3658 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 3659 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 3660 } 3661 } 3662 CGF.FinishFunction(); 3663 return DestructorFn; 3664 } 3665 3666 /// Emit a privates mapping function for correct handling of private and 3667 /// firstprivate variables. 3668 /// \code 3669 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 3670 /// **noalias priv1,..., <tyn> **noalias privn) { 3671 /// *priv1 = &.privates.priv1; 3672 /// ...; 3673 /// *privn = &.privates.privn; 3674 /// } 3675 /// \endcode 3676 static llvm::Value * 3677 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 3678 const OMPTaskDataTy &Data, QualType PrivatesQTy, 3679 ArrayRef<PrivateDataTy> Privates) { 3680 ASTContext &C = CGM.getContext(); 3681 FunctionArgList Args; 3682 ImplicitParamDecl TaskPrivatesArg( 3683 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3684 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 3685 ImplicitParamDecl::Other); 3686 Args.push_back(&TaskPrivatesArg); 3687 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, unsigned> PrivateVarsPos; 3688 unsigned Counter = 1; 3689 for (const Expr *E : Data.PrivateVars) { 3690 Args.push_back(ImplicitParamDecl::Create( 3691 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3692 C.getPointerType(C.getPointerType(E->getType())) 3693 .withConst() 3694 .withRestrict(), 3695 ImplicitParamDecl::Other)); 3696 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3697 PrivateVarsPos[VD] = Counter; 3698 ++Counter; 3699 } 3700 for (const Expr *E : Data.FirstprivateVars) { 3701 Args.push_back(ImplicitParamDecl::Create( 3702 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3703 C.getPointerType(C.getPointerType(E->getType())) 3704 .withConst() 3705 .withRestrict(), 3706 ImplicitParamDecl::Other)); 3707 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3708 PrivateVarsPos[VD] = Counter; 3709 ++Counter; 3710 } 3711 for (const Expr *E : Data.LastprivateVars) { 3712 Args.push_back(ImplicitParamDecl::Create( 3713 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3714 C.getPointerType(C.getPointerType(E->getType())) 3715 .withConst() 3716 .withRestrict(), 3717 ImplicitParamDecl::Other)); 3718 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 3719 PrivateVarsPos[VD] = Counter; 3720 ++Counter; 3721 } 3722 for (const VarDecl *VD : Data.PrivateLocals) { 3723 QualType Ty = VD->getType().getNonReferenceType(); 3724 if (VD->getType()->isLValueReferenceType()) 3725 Ty = C.getPointerType(Ty); 3726 if (isAllocatableDecl(VD)) 3727 Ty = C.getPointerType(Ty); 3728 Args.push_back(ImplicitParamDecl::Create( 3729 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3730 C.getPointerType(C.getPointerType(Ty)).withConst().withRestrict(), 3731 ImplicitParamDecl::Other)); 3732 PrivateVarsPos[VD] = Counter; 3733 ++Counter; 3734 } 3735 const auto &TaskPrivatesMapFnInfo = 3736 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3737 llvm::FunctionType *TaskPrivatesMapTy = 3738 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 3739 std::string Name = 3740 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 3741 auto *TaskPrivatesMap = llvm::Function::Create( 3742 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 3743 &CGM.getModule()); 3744 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 3745 TaskPrivatesMapFnInfo); 3746 if (CGM.getLangOpts().Optimize) { 3747 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 3748 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 3749 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 3750 } 3751 CodeGenFunction CGF(CGM); 3752 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 3753 TaskPrivatesMapFnInfo, Args, Loc, Loc); 3754 3755 // *privi = &.privates.privi; 3756 LValue Base = CGF.EmitLoadOfPointerLValue( 3757 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 3758 TaskPrivatesArg.getType()->castAs<PointerType>()); 3759 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 3760 Counter = 0; 3761 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 3762 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 3763 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 3764 LValue RefLVal = 3765 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 3766 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 3767 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 3768 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 3769 ++Counter; 3770 } 3771 CGF.FinishFunction(); 3772 return TaskPrivatesMap; 3773 } 3774 3775 /// Emit initialization for private variables in task-based directives. 3776 static void emitPrivatesInit(CodeGenFunction &CGF, 3777 const OMPExecutableDirective &D, 3778 Address KmpTaskSharedsPtr, LValue TDBase, 3779 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3780 QualType SharedsTy, QualType SharedsPtrTy, 3781 const OMPTaskDataTy &Data, 3782 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 3783 ASTContext &C = CGF.getContext(); 3784 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 3785 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 3786 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 3787 ? OMPD_taskloop 3788 : OMPD_task; 3789 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 3790 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 3791 LValue SrcBase; 3792 bool IsTargetTask = 3793 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 3794 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 3795 // For target-based directives skip 4 firstprivate arrays BasePointersArray, 3796 // PointersArray, SizesArray, and MappersArray. The original variables for 3797 // these arrays are not captured and we get their addresses explicitly. 3798 if ((!IsTargetTask && !Data.FirstprivateVars.empty() && ForDup) || 3799 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 3800 SrcBase = CGF.MakeAddrLValue( 3801 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3802 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 3803 SharedsTy); 3804 } 3805 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 3806 for (const PrivateDataTy &Pair : Privates) { 3807 // Do not initialize private locals. 3808 if (Pair.second.isLocalPrivate()) { 3809 ++FI; 3810 continue; 3811 } 3812 const VarDecl *VD = Pair.second.PrivateCopy; 3813 const Expr *Init = VD->getAnyInitializer(); 3814 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 3815 !CGF.isTrivialInitializer(Init)))) { 3816 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 3817 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 3818 const VarDecl *OriginalVD = Pair.second.Original; 3819 // Check if the variable is the target-based BasePointersArray, 3820 // PointersArray, SizesArray, or MappersArray. 3821 LValue SharedRefLValue; 3822 QualType Type = PrivateLValue.getType(); 3823 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 3824 if (IsTargetTask && !SharedField) { 3825 assert(isa<ImplicitParamDecl>(OriginalVD) && 3826 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 3827 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3828 ->getNumParams() == 0 && 3829 isa<TranslationUnitDecl>( 3830 cast<CapturedDecl>(OriginalVD->getDeclContext()) 3831 ->getDeclContext()) && 3832 "Expected artificial target data variable."); 3833 SharedRefLValue = 3834 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 3835 } else if (ForDup) { 3836 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 3837 SharedRefLValue = CGF.MakeAddrLValue( 3838 Address(SharedRefLValue.getPointer(CGF), 3839 C.getDeclAlign(OriginalVD)), 3840 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 3841 SharedRefLValue.getTBAAInfo()); 3842 } else if (CGF.LambdaCaptureFields.count( 3843 Pair.second.Original->getCanonicalDecl()) > 0 || 3844 dyn_cast_or_null<BlockDecl>(CGF.CurCodeDecl)) { 3845 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3846 } else { 3847 // Processing for implicitly captured variables. 3848 InlinedOpenMPRegionRAII Region( 3849 CGF, [](CodeGenFunction &, PrePostActionTy &) {}, OMPD_unknown, 3850 /*HasCancel=*/false); 3851 SharedRefLValue = CGF.EmitLValue(Pair.second.OriginalRef); 3852 } 3853 if (Type->isArrayType()) { 3854 // Initialize firstprivate array. 3855 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 3856 // Perform simple memcpy. 3857 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 3858 } else { 3859 // Initialize firstprivate array using element-by-element 3860 // initialization. 3861 CGF.EmitOMPAggregateAssign( 3862 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 3863 Type, 3864 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 3865 Address SrcElement) { 3866 // Clean up any temporaries needed by the initialization. 3867 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3868 InitScope.addPrivate( 3869 Elem, [SrcElement]() -> Address { return SrcElement; }); 3870 (void)InitScope.Privatize(); 3871 // Emit initialization for single element. 3872 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 3873 CGF, &CapturesInfo); 3874 CGF.EmitAnyExprToMem(Init, DestElement, 3875 Init->getType().getQualifiers(), 3876 /*IsInitializer=*/false); 3877 }); 3878 } 3879 } else { 3880 CodeGenFunction::OMPPrivateScope InitScope(CGF); 3881 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 3882 return SharedRefLValue.getAddress(CGF); 3883 }); 3884 (void)InitScope.Privatize(); 3885 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 3886 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 3887 /*capturedByInit=*/false); 3888 } 3889 } else { 3890 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 3891 } 3892 } 3893 ++FI; 3894 } 3895 } 3896 3897 /// Check if duplication function is required for taskloops. 3898 static bool checkInitIsRequired(CodeGenFunction &CGF, 3899 ArrayRef<PrivateDataTy> Privates) { 3900 bool InitRequired = false; 3901 for (const PrivateDataTy &Pair : Privates) { 3902 if (Pair.second.isLocalPrivate()) 3903 continue; 3904 const VarDecl *VD = Pair.second.PrivateCopy; 3905 const Expr *Init = VD->getAnyInitializer(); 3906 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 3907 !CGF.isTrivialInitializer(Init)); 3908 if (InitRequired) 3909 break; 3910 } 3911 return InitRequired; 3912 } 3913 3914 3915 /// Emit task_dup function (for initialization of 3916 /// private/firstprivate/lastprivate vars and last_iter flag) 3917 /// \code 3918 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 3919 /// lastpriv) { 3920 /// // setup lastprivate flag 3921 /// task_dst->last = lastpriv; 3922 /// // could be constructor calls here... 3923 /// } 3924 /// \endcode 3925 static llvm::Value * 3926 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 3927 const OMPExecutableDirective &D, 3928 QualType KmpTaskTWithPrivatesPtrQTy, 3929 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3930 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 3931 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 3932 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 3933 ASTContext &C = CGM.getContext(); 3934 FunctionArgList Args; 3935 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3936 KmpTaskTWithPrivatesPtrQTy, 3937 ImplicitParamDecl::Other); 3938 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 3939 KmpTaskTWithPrivatesPtrQTy, 3940 ImplicitParamDecl::Other); 3941 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 3942 ImplicitParamDecl::Other); 3943 Args.push_back(&DstArg); 3944 Args.push_back(&SrcArg); 3945 Args.push_back(&LastprivArg); 3946 const auto &TaskDupFnInfo = 3947 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3948 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 3949 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 3950 auto *TaskDup = llvm::Function::Create( 3951 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 3952 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 3953 TaskDup->setDoesNotRecurse(); 3954 CodeGenFunction CGF(CGM); 3955 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 3956 Loc); 3957 3958 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3959 CGF.GetAddrOfLocalVar(&DstArg), 3960 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3961 // task_dst->liter = lastpriv; 3962 if (WithLastIter) { 3963 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 3964 LValue Base = CGF.EmitLValueForField( 3965 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3966 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 3967 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 3968 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 3969 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 3970 } 3971 3972 // Emit initial values for private copies (if any). 3973 assert(!Privates.empty()); 3974 Address KmpTaskSharedsPtr = Address::invalid(); 3975 if (!Data.FirstprivateVars.empty()) { 3976 LValue TDBase = CGF.EmitLoadOfPointerLValue( 3977 CGF.GetAddrOfLocalVar(&SrcArg), 3978 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 3979 LValue Base = CGF.EmitLValueForField( 3980 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 3981 KmpTaskSharedsPtr = Address( 3982 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 3983 Base, *std::next(KmpTaskTQTyRD->field_begin(), 3984 KmpTaskTShareds)), 3985 Loc), 3986 CGM.getNaturalTypeAlignment(SharedsTy)); 3987 } 3988 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 3989 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 3990 CGF.FinishFunction(); 3991 return TaskDup; 3992 } 3993 3994 /// Checks if destructor function is required to be generated. 3995 /// \return true if cleanups are required, false otherwise. 3996 static bool 3997 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD, 3998 ArrayRef<PrivateDataTy> Privates) { 3999 for (const PrivateDataTy &P : Privates) { 4000 if (P.second.isLocalPrivate()) 4001 continue; 4002 QualType Ty = P.second.Original->getType().getNonReferenceType(); 4003 if (Ty.isDestructedType()) 4004 return true; 4005 } 4006 return false; 4007 } 4008 4009 namespace { 4010 /// Loop generator for OpenMP iterator expression. 4011 class OMPIteratorGeneratorScope final 4012 : public CodeGenFunction::OMPPrivateScope { 4013 CodeGenFunction &CGF; 4014 const OMPIteratorExpr *E = nullptr; 4015 SmallVector<CodeGenFunction::JumpDest, 4> ContDests; 4016 SmallVector<CodeGenFunction::JumpDest, 4> ExitDests; 4017 OMPIteratorGeneratorScope() = delete; 4018 OMPIteratorGeneratorScope(OMPIteratorGeneratorScope &) = delete; 4019 4020 public: 4021 OMPIteratorGeneratorScope(CodeGenFunction &CGF, const OMPIteratorExpr *E) 4022 : CodeGenFunction::OMPPrivateScope(CGF), CGF(CGF), E(E) { 4023 if (!E) 4024 return; 4025 SmallVector<llvm::Value *, 4> Uppers; 4026 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4027 Uppers.push_back(CGF.EmitScalarExpr(E->getHelper(I).Upper)); 4028 const auto *VD = cast<VarDecl>(E->getIteratorDecl(I)); 4029 addPrivate(VD, [&CGF, VD]() { 4030 return CGF.CreateMemTemp(VD->getType(), VD->getName()); 4031 }); 4032 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4033 addPrivate(HelperData.CounterVD, [&CGF, &HelperData]() { 4034 return CGF.CreateMemTemp(HelperData.CounterVD->getType(), 4035 "counter.addr"); 4036 }); 4037 } 4038 Privatize(); 4039 4040 for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) { 4041 const OMPIteratorHelperData &HelperData = E->getHelper(I); 4042 LValue CLVal = 4043 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(HelperData.CounterVD), 4044 HelperData.CounterVD->getType()); 4045 // Counter = 0; 4046 CGF.EmitStoreOfScalar( 4047 llvm::ConstantInt::get(CLVal.getAddress(CGF).getElementType(), 0), 4048 CLVal); 4049 CodeGenFunction::JumpDest &ContDest = 4050 ContDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.cont")); 4051 CodeGenFunction::JumpDest &ExitDest = 4052 ExitDests.emplace_back(CGF.getJumpDestInCurrentScope("iter.exit")); 4053 // N = <number-of_iterations>; 4054 llvm::Value *N = Uppers[I]; 4055 // cont: 4056 // if (Counter < N) goto body; else goto exit; 4057 CGF.EmitBlock(ContDest.getBlock()); 4058 auto *CVal = 4059 CGF.EmitLoadOfScalar(CLVal, HelperData.CounterVD->getLocation()); 4060 llvm::Value *Cmp = 4061 HelperData.CounterVD->getType()->isSignedIntegerOrEnumerationType() 4062 ? CGF.Builder.CreateICmpSLT(CVal, N) 4063 : CGF.Builder.CreateICmpULT(CVal, N); 4064 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("iter.body"); 4065 CGF.Builder.CreateCondBr(Cmp, BodyBB, ExitDest.getBlock()); 4066 // body: 4067 CGF.EmitBlock(BodyBB); 4068 // Iteri = Begini + Counter * Stepi; 4069 CGF.EmitIgnoredExpr(HelperData.Update); 4070 } 4071 } 4072 ~OMPIteratorGeneratorScope() { 4073 if (!E) 4074 return; 4075 for (unsigned I = E->numOfIterators(); I > 0; --I) { 4076 // Counter = Counter + 1; 4077 const OMPIteratorHelperData &HelperData = E->getHelper(I - 1); 4078 CGF.EmitIgnoredExpr(HelperData.CounterUpdate); 4079 // goto cont; 4080 CGF.EmitBranchThroughCleanup(ContDests[I - 1]); 4081 // exit: 4082 CGF.EmitBlock(ExitDests[I - 1].getBlock(), /*IsFinished=*/I == 1); 4083 } 4084 } 4085 }; 4086 } // namespace 4087 4088 static std::pair<llvm::Value *, llvm::Value *> 4089 getPointerAndSize(CodeGenFunction &CGF, const Expr *E) { 4090 const auto *OASE = dyn_cast<OMPArrayShapingExpr>(E); 4091 llvm::Value *Addr; 4092 if (OASE) { 4093 const Expr *Base = OASE->getBase(); 4094 Addr = CGF.EmitScalarExpr(Base); 4095 } else { 4096 Addr = CGF.EmitLValue(E).getPointer(CGF); 4097 } 4098 llvm::Value *SizeVal; 4099 QualType Ty = E->getType(); 4100 if (OASE) { 4101 SizeVal = CGF.getTypeSize(OASE->getBase()->getType()->getPointeeType()); 4102 for (const Expr *SE : OASE->getDimensions()) { 4103 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 4104 Sz = CGF.EmitScalarConversion( 4105 Sz, SE->getType(), CGF.getContext().getSizeType(), SE->getExprLoc()); 4106 SizeVal = CGF.Builder.CreateNUWMul(SizeVal, Sz); 4107 } 4108 } else if (const auto *ASE = 4109 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 4110 LValue UpAddrLVal = 4111 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 4112 llvm::Value *UpAddr = 4113 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 4114 llvm::Value *LowIntPtr = CGF.Builder.CreatePtrToInt(Addr, CGF.SizeTy); 4115 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGF.SizeTy); 4116 SizeVal = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 4117 } else { 4118 SizeVal = CGF.getTypeSize(Ty); 4119 } 4120 return std::make_pair(Addr, SizeVal); 4121 } 4122 4123 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4124 static void getKmpAffinityType(ASTContext &C, QualType &KmpTaskAffinityInfoTy) { 4125 QualType FlagsTy = C.getIntTypeForBitwidth(32, /*Signed=*/false); 4126 if (KmpTaskAffinityInfoTy.isNull()) { 4127 RecordDecl *KmpAffinityInfoRD = 4128 C.buildImplicitRecord("kmp_task_affinity_info_t"); 4129 KmpAffinityInfoRD->startDefinition(); 4130 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getIntPtrType()); 4131 addFieldToRecordDecl(C, KmpAffinityInfoRD, C.getSizeType()); 4132 addFieldToRecordDecl(C, KmpAffinityInfoRD, FlagsTy); 4133 KmpAffinityInfoRD->completeDefinition(); 4134 KmpTaskAffinityInfoTy = C.getRecordType(KmpAffinityInfoRD); 4135 } 4136 } 4137 4138 CGOpenMPRuntime::TaskResultTy 4139 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4140 const OMPExecutableDirective &D, 4141 llvm::Function *TaskFunction, QualType SharedsTy, 4142 Address Shareds, const OMPTaskDataTy &Data) { 4143 ASTContext &C = CGM.getContext(); 4144 llvm::SmallVector<PrivateDataTy, 4> Privates; 4145 // Aggregate privates and sort them by the alignment. 4146 const auto *I = Data.PrivateCopies.begin(); 4147 for (const Expr *E : Data.PrivateVars) { 4148 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4149 Privates.emplace_back( 4150 C.getDeclAlign(VD), 4151 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4152 /*PrivateElemInit=*/nullptr)); 4153 ++I; 4154 } 4155 I = Data.FirstprivateCopies.begin(); 4156 const auto *IElemInitRef = Data.FirstprivateInits.begin(); 4157 for (const Expr *E : Data.FirstprivateVars) { 4158 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4159 Privates.emplace_back( 4160 C.getDeclAlign(VD), 4161 PrivateHelpersTy( 4162 E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4163 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4164 ++I; 4165 ++IElemInitRef; 4166 } 4167 I = Data.LastprivateCopies.begin(); 4168 for (const Expr *E : Data.LastprivateVars) { 4169 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4170 Privates.emplace_back( 4171 C.getDeclAlign(VD), 4172 PrivateHelpersTy(E, VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4173 /*PrivateElemInit=*/nullptr)); 4174 ++I; 4175 } 4176 for (const VarDecl *VD : Data.PrivateLocals) { 4177 if (isAllocatableDecl(VD)) 4178 Privates.emplace_back(CGM.getPointerAlign(), PrivateHelpersTy(VD)); 4179 else 4180 Privates.emplace_back(C.getDeclAlign(VD), PrivateHelpersTy(VD)); 4181 } 4182 llvm::stable_sort(Privates, 4183 [](const PrivateDataTy &L, const PrivateDataTy &R) { 4184 return L.first > R.first; 4185 }); 4186 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4187 // Build type kmp_routine_entry_t (if not built yet). 4188 emitKmpRoutineEntryT(KmpInt32Ty); 4189 // Build type kmp_task_t (if not built yet). 4190 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 4191 if (SavedKmpTaskloopTQTy.isNull()) { 4192 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4193 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4194 } 4195 KmpTaskTQTy = SavedKmpTaskloopTQTy; 4196 } else { 4197 assert((D.getDirectiveKind() == OMPD_task || 4198 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 4199 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 4200 "Expected taskloop, task or target directive"); 4201 if (SavedKmpTaskTQTy.isNull()) { 4202 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4203 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4204 } 4205 KmpTaskTQTy = SavedKmpTaskTQTy; 4206 } 4207 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4208 // Build particular struct kmp_task_t for the given task. 4209 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 4210 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 4211 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 4212 QualType KmpTaskTWithPrivatesPtrQTy = 4213 C.getPointerType(KmpTaskTWithPrivatesQTy); 4214 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 4215 llvm::Type *KmpTaskTWithPrivatesPtrTy = 4216 KmpTaskTWithPrivatesTy->getPointerTo(); 4217 llvm::Value *KmpTaskTWithPrivatesTySize = 4218 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 4219 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 4220 4221 // Emit initial values for private copies (if any). 4222 llvm::Value *TaskPrivatesMap = nullptr; 4223 llvm::Type *TaskPrivatesMapTy = 4224 std::next(TaskFunction->arg_begin(), 3)->getType(); 4225 if (!Privates.empty()) { 4226 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4227 TaskPrivatesMap = 4228 emitTaskPrivateMappingFunction(CGM, Loc, Data, FI->getType(), Privates); 4229 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4230 TaskPrivatesMap, TaskPrivatesMapTy); 4231 } else { 4232 TaskPrivatesMap = llvm::ConstantPointerNull::get( 4233 cast<llvm::PointerType>(TaskPrivatesMapTy)); 4234 } 4235 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 4236 // kmp_task_t *tt); 4237 llvm::Function *TaskEntry = emitProxyTaskFunction( 4238 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4239 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 4240 TaskPrivatesMap); 4241 4242 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 4243 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 4244 // kmp_routine_entry_t *task_entry); 4245 // Task flags. Format is taken from 4246 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 4247 // description of kmp_tasking_flags struct. 4248 enum { 4249 TiedFlag = 0x1, 4250 FinalFlag = 0x2, 4251 DestructorsFlag = 0x8, 4252 PriorityFlag = 0x20, 4253 DetachableFlag = 0x40, 4254 }; 4255 unsigned Flags = Data.Tied ? TiedFlag : 0; 4256 bool NeedsCleanup = false; 4257 if (!Privates.empty()) { 4258 NeedsCleanup = 4259 checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD, Privates); 4260 if (NeedsCleanup) 4261 Flags = Flags | DestructorsFlag; 4262 } 4263 if (Data.Priority.getInt()) 4264 Flags = Flags | PriorityFlag; 4265 if (D.hasClausesOfKind<OMPDetachClause>()) 4266 Flags = Flags | DetachableFlag; 4267 llvm::Value *TaskFlags = 4268 Data.Final.getPointer() 4269 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 4270 CGF.Builder.getInt32(FinalFlag), 4271 CGF.Builder.getInt32(/*C=*/0)) 4272 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 4273 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 4274 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 4275 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 4276 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 4277 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4278 TaskEntry, KmpRoutineEntryPtrTy)}; 4279 llvm::Value *NewTask; 4280 if (D.hasClausesOfKind<OMPNowaitClause>()) { 4281 // Check if we have any device clause associated with the directive. 4282 const Expr *Device = nullptr; 4283 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 4284 Device = C->getDevice(); 4285 // Emit device ID if any otherwise use default value. 4286 llvm::Value *DeviceID; 4287 if (Device) 4288 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 4289 CGF.Int64Ty, /*isSigned=*/true); 4290 else 4291 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 4292 AllocArgs.push_back(DeviceID); 4293 NewTask = CGF.EmitRuntimeCall( 4294 OMPBuilder.getOrCreateRuntimeFunction( 4295 CGM.getModule(), OMPRTL___kmpc_omp_target_task_alloc), 4296 AllocArgs); 4297 } else { 4298 NewTask = 4299 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 4300 CGM.getModule(), OMPRTL___kmpc_omp_task_alloc), 4301 AllocArgs); 4302 } 4303 // Emit detach clause initialization. 4304 // evt = (typeof(evt))__kmpc_task_allow_completion_event(loc, tid, 4305 // task_descriptor); 4306 if (const auto *DC = D.getSingleClause<OMPDetachClause>()) { 4307 const Expr *Evt = DC->getEventHandler()->IgnoreParenImpCasts(); 4308 LValue EvtLVal = CGF.EmitLValue(Evt); 4309 4310 // Build kmp_event_t *__kmpc_task_allow_completion_event(ident_t *loc_ref, 4311 // int gtid, kmp_task_t *task); 4312 llvm::Value *Loc = emitUpdateLocation(CGF, DC->getBeginLoc()); 4313 llvm::Value *Tid = getThreadID(CGF, DC->getBeginLoc()); 4314 Tid = CGF.Builder.CreateIntCast(Tid, CGF.IntTy, /*isSigned=*/false); 4315 llvm::Value *EvtVal = CGF.EmitRuntimeCall( 4316 OMPBuilder.getOrCreateRuntimeFunction( 4317 CGM.getModule(), OMPRTL___kmpc_task_allow_completion_event), 4318 {Loc, Tid, NewTask}); 4319 EvtVal = CGF.EmitScalarConversion(EvtVal, C.VoidPtrTy, Evt->getType(), 4320 Evt->getExprLoc()); 4321 CGF.EmitStoreOfScalar(EvtVal, EvtLVal); 4322 } 4323 // Process affinity clauses. 4324 if (D.hasClausesOfKind<OMPAffinityClause>()) { 4325 // Process list of affinity data. 4326 ASTContext &C = CGM.getContext(); 4327 Address AffinitiesArray = Address::invalid(); 4328 // Calculate number of elements to form the array of affinity data. 4329 llvm::Value *NumOfElements = nullptr; 4330 unsigned NumAffinities = 0; 4331 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4332 if (const Expr *Modifier = C->getModifier()) { 4333 const auto *IE = cast<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts()); 4334 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4335 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4336 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4337 NumOfElements = 4338 NumOfElements ? CGF.Builder.CreateNUWMul(NumOfElements, Sz) : Sz; 4339 } 4340 } else { 4341 NumAffinities += C->varlist_size(); 4342 } 4343 } 4344 getKmpAffinityType(CGM.getContext(), KmpTaskAffinityInfoTy); 4345 // Fields ids in kmp_task_affinity_info record. 4346 enum RTLAffinityInfoFieldsTy { BaseAddr, Len, Flags }; 4347 4348 QualType KmpTaskAffinityInfoArrayTy; 4349 if (NumOfElements) { 4350 NumOfElements = CGF.Builder.CreateNUWAdd( 4351 llvm::ConstantInt::get(CGF.SizeTy, NumAffinities), NumOfElements); 4352 OpaqueValueExpr OVE( 4353 Loc, 4354 C.getIntTypeForBitwidth(C.getTypeSize(C.getSizeType()), /*Signed=*/0), 4355 VK_RValue); 4356 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 4357 RValue::get(NumOfElements)); 4358 KmpTaskAffinityInfoArrayTy = 4359 C.getVariableArrayType(KmpTaskAffinityInfoTy, &OVE, ArrayType::Normal, 4360 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4361 // Properly emit variable-sized array. 4362 auto *PD = ImplicitParamDecl::Create(C, KmpTaskAffinityInfoArrayTy, 4363 ImplicitParamDecl::Other); 4364 CGF.EmitVarDecl(*PD); 4365 AffinitiesArray = CGF.GetAddrOfLocalVar(PD); 4366 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4367 /*isSigned=*/false); 4368 } else { 4369 KmpTaskAffinityInfoArrayTy = C.getConstantArrayType( 4370 KmpTaskAffinityInfoTy, 4371 llvm::APInt(C.getTypeSize(C.getSizeType()), NumAffinities), nullptr, 4372 ArrayType::Normal, /*IndexTypeQuals=*/0); 4373 AffinitiesArray = 4374 CGF.CreateMemTemp(KmpTaskAffinityInfoArrayTy, ".affs.arr.addr"); 4375 AffinitiesArray = CGF.Builder.CreateConstArrayGEP(AffinitiesArray, 0); 4376 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumAffinities, 4377 /*isSigned=*/false); 4378 } 4379 4380 const auto *KmpAffinityInfoRD = KmpTaskAffinityInfoTy->getAsRecordDecl(); 4381 // Fill array by elements without iterators. 4382 unsigned Pos = 0; 4383 bool HasIterator = false; 4384 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4385 if (C->getModifier()) { 4386 HasIterator = true; 4387 continue; 4388 } 4389 for (const Expr *E : C->varlists()) { 4390 llvm::Value *Addr; 4391 llvm::Value *Size; 4392 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4393 LValue Base = 4394 CGF.MakeAddrLValue(CGF.Builder.CreateConstGEP(AffinitiesArray, Pos), 4395 KmpTaskAffinityInfoTy); 4396 // affs[i].base_addr = &<Affinities[i].second>; 4397 LValue BaseAddrLVal = CGF.EmitLValueForField( 4398 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4399 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4400 BaseAddrLVal); 4401 // affs[i].len = sizeof(<Affinities[i].second>); 4402 LValue LenLVal = CGF.EmitLValueForField( 4403 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4404 CGF.EmitStoreOfScalar(Size, LenLVal); 4405 ++Pos; 4406 } 4407 } 4408 LValue PosLVal; 4409 if (HasIterator) { 4410 PosLVal = CGF.MakeAddrLValue( 4411 CGF.CreateMemTemp(C.getSizeType(), "affs.counter.addr"), 4412 C.getSizeType()); 4413 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4414 } 4415 // Process elements with iterators. 4416 for (const auto *C : D.getClausesOfKind<OMPAffinityClause>()) { 4417 const Expr *Modifier = C->getModifier(); 4418 if (!Modifier) 4419 continue; 4420 OMPIteratorGeneratorScope IteratorScope( 4421 CGF, cast_or_null<OMPIteratorExpr>(Modifier->IgnoreParenImpCasts())); 4422 for (const Expr *E : C->varlists()) { 4423 llvm::Value *Addr; 4424 llvm::Value *Size; 4425 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4426 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4427 LValue Base = CGF.MakeAddrLValue( 4428 Address(CGF.Builder.CreateGEP(AffinitiesArray.getPointer(), Idx), 4429 AffinitiesArray.getAlignment()), 4430 KmpTaskAffinityInfoTy); 4431 // affs[i].base_addr = &<Affinities[i].second>; 4432 LValue BaseAddrLVal = CGF.EmitLValueForField( 4433 Base, *std::next(KmpAffinityInfoRD->field_begin(), BaseAddr)); 4434 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4435 BaseAddrLVal); 4436 // affs[i].len = sizeof(<Affinities[i].second>); 4437 LValue LenLVal = CGF.EmitLValueForField( 4438 Base, *std::next(KmpAffinityInfoRD->field_begin(), Len)); 4439 CGF.EmitStoreOfScalar(Size, LenLVal); 4440 Idx = CGF.Builder.CreateNUWAdd( 4441 Idx, llvm::ConstantInt::get(Idx->getType(), 1)); 4442 CGF.EmitStoreOfScalar(Idx, PosLVal); 4443 } 4444 } 4445 // Call to kmp_int32 __kmpc_omp_reg_task_with_affinity(ident_t *loc_ref, 4446 // kmp_int32 gtid, kmp_task_t *new_task, kmp_int32 4447 // naffins, kmp_task_affinity_info_t *affin_list); 4448 llvm::Value *LocRef = emitUpdateLocation(CGF, Loc); 4449 llvm::Value *GTid = getThreadID(CGF, Loc); 4450 llvm::Value *AffinListPtr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4451 AffinitiesArray.getPointer(), CGM.VoidPtrTy); 4452 // FIXME: Emit the function and ignore its result for now unless the 4453 // runtime function is properly implemented. 4454 (void)CGF.EmitRuntimeCall( 4455 OMPBuilder.getOrCreateRuntimeFunction( 4456 CGM.getModule(), OMPRTL___kmpc_omp_reg_task_with_affinity), 4457 {LocRef, GTid, NewTask, NumOfElements, AffinListPtr}); 4458 } 4459 llvm::Value *NewTaskNewTaskTTy = 4460 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4461 NewTask, KmpTaskTWithPrivatesPtrTy); 4462 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 4463 KmpTaskTWithPrivatesQTy); 4464 LValue TDBase = 4465 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4466 // Fill the data in the resulting kmp_task_t record. 4467 // Copy shareds if there are any. 4468 Address KmpTaskSharedsPtr = Address::invalid(); 4469 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 4470 KmpTaskSharedsPtr = 4471 Address(CGF.EmitLoadOfScalar( 4472 CGF.EmitLValueForField( 4473 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 4474 KmpTaskTShareds)), 4475 Loc), 4476 CGM.getNaturalTypeAlignment(SharedsTy)); 4477 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 4478 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 4479 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 4480 } 4481 // Emit initial values for private copies (if any). 4482 TaskResultTy Result; 4483 if (!Privates.empty()) { 4484 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 4485 SharedsTy, SharedsPtrTy, Data, Privates, 4486 /*ForDup=*/false); 4487 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 4488 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 4489 Result.TaskDupFn = emitTaskDupFunction( 4490 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 4491 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 4492 /*WithLastIter=*/!Data.LastprivateVars.empty()); 4493 } 4494 } 4495 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 4496 enum { Priority = 0, Destructors = 1 }; 4497 // Provide pointer to function with destructors for privates. 4498 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 4499 const RecordDecl *KmpCmplrdataUD = 4500 (*FI)->getType()->getAsUnionType()->getDecl(); 4501 if (NeedsCleanup) { 4502 llvm::Value *DestructorFn = emitDestructorsFunction( 4503 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 4504 KmpTaskTWithPrivatesQTy); 4505 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 4506 LValue DestructorsLV = CGF.EmitLValueForField( 4507 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 4508 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4509 DestructorFn, KmpRoutineEntryPtrTy), 4510 DestructorsLV); 4511 } 4512 // Set priority. 4513 if (Data.Priority.getInt()) { 4514 LValue Data2LV = CGF.EmitLValueForField( 4515 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 4516 LValue PriorityLV = CGF.EmitLValueForField( 4517 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 4518 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 4519 } 4520 Result.NewTask = NewTask; 4521 Result.TaskEntry = TaskEntry; 4522 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 4523 Result.TDBase = TDBase; 4524 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 4525 return Result; 4526 } 4527 4528 namespace { 4529 /// Dependence kind for RTL. 4530 enum RTLDependenceKindTy { 4531 DepIn = 0x01, 4532 DepInOut = 0x3, 4533 DepMutexInOutSet = 0x4 4534 }; 4535 /// Fields ids in kmp_depend_info record. 4536 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 4537 } // namespace 4538 4539 /// Translates internal dependency kind into the runtime kind. 4540 static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { 4541 RTLDependenceKindTy DepKind; 4542 switch (K) { 4543 case OMPC_DEPEND_in: 4544 DepKind = DepIn; 4545 break; 4546 // Out and InOut dependencies must use the same code. 4547 case OMPC_DEPEND_out: 4548 case OMPC_DEPEND_inout: 4549 DepKind = DepInOut; 4550 break; 4551 case OMPC_DEPEND_mutexinoutset: 4552 DepKind = DepMutexInOutSet; 4553 break; 4554 case OMPC_DEPEND_source: 4555 case OMPC_DEPEND_sink: 4556 case OMPC_DEPEND_depobj: 4557 case OMPC_DEPEND_unknown: 4558 llvm_unreachable("Unknown task dependence type"); 4559 } 4560 return DepKind; 4561 } 4562 4563 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 4564 static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, 4565 QualType &FlagsTy) { 4566 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 4567 if (KmpDependInfoTy.isNull()) { 4568 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 4569 KmpDependInfoRD->startDefinition(); 4570 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 4571 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 4572 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 4573 KmpDependInfoRD->completeDefinition(); 4574 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 4575 } 4576 } 4577 4578 std::pair<llvm::Value *, LValue> 4579 CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, 4580 SourceLocation Loc) { 4581 ASTContext &C = CGM.getContext(); 4582 QualType FlagsTy; 4583 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4584 RecordDecl *KmpDependInfoRD = 4585 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4586 LValue Base = CGF.EmitLoadOfPointerLValue( 4587 DepobjLVal.getAddress(CGF), 4588 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4589 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4590 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4591 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 4592 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4593 Base.getTBAAInfo()); 4594 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4595 Addr.getPointer(), 4596 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4597 LValue NumDepsBase = CGF.MakeAddrLValue( 4598 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4599 Base.getBaseInfo(), Base.getTBAAInfo()); 4600 // NumDeps = deps[i].base_addr; 4601 LValue BaseAddrLVal = CGF.EmitLValueForField( 4602 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4603 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc); 4604 return std::make_pair(NumDeps, Base); 4605 } 4606 4607 static void emitDependData(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4608 llvm::PointerUnion<unsigned *, LValue *> Pos, 4609 const OMPTaskDataTy::DependData &Data, 4610 Address DependenciesArray) { 4611 CodeGenModule &CGM = CGF.CGM; 4612 ASTContext &C = CGM.getContext(); 4613 QualType FlagsTy; 4614 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4615 RecordDecl *KmpDependInfoRD = 4616 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4617 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 4618 4619 OMPIteratorGeneratorScope IteratorScope( 4620 CGF, cast_or_null<OMPIteratorExpr>( 4621 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4622 : nullptr)); 4623 for (const Expr *E : Data.DepExprs) { 4624 llvm::Value *Addr; 4625 llvm::Value *Size; 4626 std::tie(Addr, Size) = getPointerAndSize(CGF, E); 4627 LValue Base; 4628 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4629 Base = CGF.MakeAddrLValue( 4630 CGF.Builder.CreateConstGEP(DependenciesArray, *P), KmpDependInfoTy); 4631 } else { 4632 LValue &PosLVal = *Pos.get<LValue *>(); 4633 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4634 Base = CGF.MakeAddrLValue( 4635 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Idx), 4636 DependenciesArray.getAlignment()), 4637 KmpDependInfoTy); 4638 } 4639 // deps[i].base_addr = &<Dependencies[i].second>; 4640 LValue BaseAddrLVal = CGF.EmitLValueForField( 4641 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4642 CGF.EmitStoreOfScalar(CGF.Builder.CreatePtrToInt(Addr, CGF.IntPtrTy), 4643 BaseAddrLVal); 4644 // deps[i].len = sizeof(<Dependencies[i].second>); 4645 LValue LenLVal = CGF.EmitLValueForField( 4646 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 4647 CGF.EmitStoreOfScalar(Size, LenLVal); 4648 // deps[i].flags = <Dependencies[i].first>; 4649 RTLDependenceKindTy DepKind = translateDependencyKind(Data.DepKind); 4650 LValue FlagsLVal = CGF.EmitLValueForField( 4651 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 4652 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 4653 FlagsLVal); 4654 if (unsigned *P = Pos.dyn_cast<unsigned *>()) { 4655 ++(*P); 4656 } else { 4657 LValue &PosLVal = *Pos.get<LValue *>(); 4658 llvm::Value *Idx = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4659 Idx = CGF.Builder.CreateNUWAdd(Idx, 4660 llvm::ConstantInt::get(Idx->getType(), 1)); 4661 CGF.EmitStoreOfScalar(Idx, PosLVal); 4662 } 4663 } 4664 } 4665 4666 static SmallVector<llvm::Value *, 4> 4667 emitDepobjElementsSizes(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4668 const OMPTaskDataTy::DependData &Data) { 4669 assert(Data.DepKind == OMPC_DEPEND_depobj && 4670 "Expected depobj dependecy kind."); 4671 SmallVector<llvm::Value *, 4> Sizes; 4672 SmallVector<LValue, 4> SizeLVals; 4673 ASTContext &C = CGF.getContext(); 4674 QualType FlagsTy; 4675 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4676 RecordDecl *KmpDependInfoRD = 4677 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4678 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4679 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4680 { 4681 OMPIteratorGeneratorScope IteratorScope( 4682 CGF, cast_or_null<OMPIteratorExpr>( 4683 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4684 : nullptr)); 4685 for (const Expr *E : Data.DepExprs) { 4686 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4687 LValue Base = CGF.EmitLoadOfPointerLValue( 4688 DepobjLVal.getAddress(CGF), 4689 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4690 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4691 Base.getAddress(CGF), KmpDependInfoPtrT); 4692 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4693 Base.getTBAAInfo()); 4694 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4695 Addr.getPointer(), 4696 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4697 LValue NumDepsBase = CGF.MakeAddrLValue( 4698 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4699 Base.getBaseInfo(), Base.getTBAAInfo()); 4700 // NumDeps = deps[i].base_addr; 4701 LValue BaseAddrLVal = CGF.EmitLValueForField( 4702 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4703 llvm::Value *NumDeps = 4704 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4705 LValue NumLVal = CGF.MakeAddrLValue( 4706 CGF.CreateMemTemp(C.getUIntPtrType(), "depobj.size.addr"), 4707 C.getUIntPtrType()); 4708 CGF.InitTempAlloca(NumLVal.getAddress(CGF), 4709 llvm::ConstantInt::get(CGF.IntPtrTy, 0)); 4710 llvm::Value *PrevVal = CGF.EmitLoadOfScalar(NumLVal, E->getExprLoc()); 4711 llvm::Value *Add = CGF.Builder.CreateNUWAdd(PrevVal, NumDeps); 4712 CGF.EmitStoreOfScalar(Add, NumLVal); 4713 SizeLVals.push_back(NumLVal); 4714 } 4715 } 4716 for (unsigned I = 0, E = SizeLVals.size(); I < E; ++I) { 4717 llvm::Value *Size = 4718 CGF.EmitLoadOfScalar(SizeLVals[I], Data.DepExprs[I]->getExprLoc()); 4719 Sizes.push_back(Size); 4720 } 4721 return Sizes; 4722 } 4723 4724 static void emitDepobjElements(CodeGenFunction &CGF, QualType &KmpDependInfoTy, 4725 LValue PosLVal, 4726 const OMPTaskDataTy::DependData &Data, 4727 Address DependenciesArray) { 4728 assert(Data.DepKind == OMPC_DEPEND_depobj && 4729 "Expected depobj dependecy kind."); 4730 ASTContext &C = CGF.getContext(); 4731 QualType FlagsTy; 4732 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4733 RecordDecl *KmpDependInfoRD = 4734 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4735 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4736 llvm::Type *KmpDependInfoPtrT = CGF.ConvertTypeForMem(KmpDependInfoPtrTy); 4737 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy); 4738 { 4739 OMPIteratorGeneratorScope IteratorScope( 4740 CGF, cast_or_null<OMPIteratorExpr>( 4741 Data.IteratorExpr ? Data.IteratorExpr->IgnoreParenImpCasts() 4742 : nullptr)); 4743 for (unsigned I = 0, End = Data.DepExprs.size(); I < End; ++I) { 4744 const Expr *E = Data.DepExprs[I]; 4745 LValue DepobjLVal = CGF.EmitLValue(E->IgnoreParenImpCasts()); 4746 LValue Base = CGF.EmitLoadOfPointerLValue( 4747 DepobjLVal.getAddress(CGF), 4748 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4749 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4750 Base.getAddress(CGF), KmpDependInfoPtrT); 4751 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 4752 Base.getTBAAInfo()); 4753 4754 // Get number of elements in a single depobj. 4755 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 4756 Addr.getPointer(), 4757 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 4758 LValue NumDepsBase = CGF.MakeAddrLValue( 4759 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 4760 Base.getBaseInfo(), Base.getTBAAInfo()); 4761 // NumDeps = deps[i].base_addr; 4762 LValue BaseAddrLVal = CGF.EmitLValueForField( 4763 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4764 llvm::Value *NumDeps = 4765 CGF.EmitLoadOfScalar(BaseAddrLVal, E->getExprLoc()); 4766 4767 // memcopy dependency data. 4768 llvm::Value *Size = CGF.Builder.CreateNUWMul( 4769 ElSize, 4770 CGF.Builder.CreateIntCast(NumDeps, CGF.SizeTy, /*isSigned=*/false)); 4771 llvm::Value *Pos = CGF.EmitLoadOfScalar(PosLVal, E->getExprLoc()); 4772 Address DepAddr = 4773 Address(CGF.Builder.CreateGEP(DependenciesArray.getPointer(), Pos), 4774 DependenciesArray.getAlignment()); 4775 CGF.Builder.CreateMemCpy(DepAddr, Base.getAddress(CGF), Size); 4776 4777 // Increase pos. 4778 // pos += size; 4779 llvm::Value *Add = CGF.Builder.CreateNUWAdd(Pos, NumDeps); 4780 CGF.EmitStoreOfScalar(Add, PosLVal); 4781 } 4782 } 4783 } 4784 4785 std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause( 4786 CodeGenFunction &CGF, ArrayRef<OMPTaskDataTy::DependData> Dependencies, 4787 SourceLocation Loc) { 4788 if (llvm::all_of(Dependencies, [](const OMPTaskDataTy::DependData &D) { 4789 return D.DepExprs.empty(); 4790 })) 4791 return std::make_pair(nullptr, Address::invalid()); 4792 // Process list of dependencies. 4793 ASTContext &C = CGM.getContext(); 4794 Address DependenciesArray = Address::invalid(); 4795 llvm::Value *NumOfElements = nullptr; 4796 unsigned NumDependencies = std::accumulate( 4797 Dependencies.begin(), Dependencies.end(), 0, 4798 [](unsigned V, const OMPTaskDataTy::DependData &D) { 4799 return D.DepKind == OMPC_DEPEND_depobj 4800 ? V 4801 : (V + (D.IteratorExpr ? 0 : D.DepExprs.size())); 4802 }); 4803 QualType FlagsTy; 4804 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4805 bool HasDepobjDeps = false; 4806 bool HasRegularWithIterators = false; 4807 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0); 4808 llvm::Value *NumOfRegularWithIterators = 4809 llvm::ConstantInt::get(CGF.IntPtrTy, 1); 4810 // Calculate number of depobj dependecies and regular deps with the iterators. 4811 for (const OMPTaskDataTy::DependData &D : Dependencies) { 4812 if (D.DepKind == OMPC_DEPEND_depobj) { 4813 SmallVector<llvm::Value *, 4> Sizes = 4814 emitDepobjElementsSizes(CGF, KmpDependInfoTy, D); 4815 for (llvm::Value *Size : Sizes) { 4816 NumOfDepobjElements = 4817 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, Size); 4818 } 4819 HasDepobjDeps = true; 4820 continue; 4821 } 4822 // Include number of iterations, if any. 4823 if (const auto *IE = cast_or_null<OMPIteratorExpr>(D.IteratorExpr)) { 4824 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4825 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4826 Sz = CGF.Builder.CreateIntCast(Sz, CGF.IntPtrTy, /*isSigned=*/false); 4827 NumOfRegularWithIterators = 4828 CGF.Builder.CreateNUWMul(NumOfRegularWithIterators, Sz); 4829 } 4830 HasRegularWithIterators = true; 4831 continue; 4832 } 4833 } 4834 4835 QualType KmpDependInfoArrayTy; 4836 if (HasDepobjDeps || HasRegularWithIterators) { 4837 NumOfElements = llvm::ConstantInt::get(CGM.IntPtrTy, NumDependencies, 4838 /*isSigned=*/false); 4839 if (HasDepobjDeps) { 4840 NumOfElements = 4841 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumOfElements); 4842 } 4843 if (HasRegularWithIterators) { 4844 NumOfElements = 4845 CGF.Builder.CreateNUWAdd(NumOfRegularWithIterators, NumOfElements); 4846 } 4847 OpaqueValueExpr OVE(Loc, 4848 C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0), 4849 VK_RValue); 4850 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 4851 RValue::get(NumOfElements)); 4852 KmpDependInfoArrayTy = 4853 C.getVariableArrayType(KmpDependInfoTy, &OVE, ArrayType::Normal, 4854 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 4855 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy); 4856 // Properly emit variable-sized array. 4857 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy, 4858 ImplicitParamDecl::Other); 4859 CGF.EmitVarDecl(*PD); 4860 DependenciesArray = CGF.GetAddrOfLocalVar(PD); 4861 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 4862 /*isSigned=*/false); 4863 } else { 4864 KmpDependInfoArrayTy = C.getConstantArrayType( 4865 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), nullptr, 4866 ArrayType::Normal, /*IndexTypeQuals=*/0); 4867 DependenciesArray = 4868 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 4869 DependenciesArray = CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0); 4870 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 4871 /*isSigned=*/false); 4872 } 4873 unsigned Pos = 0; 4874 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4875 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4876 Dependencies[I].IteratorExpr) 4877 continue; 4878 emitDependData(CGF, KmpDependInfoTy, &Pos, Dependencies[I], 4879 DependenciesArray); 4880 } 4881 // Copy regular dependecies with iterators. 4882 LValue PosLVal = CGF.MakeAddrLValue( 4883 CGF.CreateMemTemp(C.getSizeType(), "dep.counter.addr"), C.getSizeType()); 4884 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Pos), PosLVal); 4885 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4886 if (Dependencies[I].DepKind == OMPC_DEPEND_depobj || 4887 !Dependencies[I].IteratorExpr) 4888 continue; 4889 emitDependData(CGF, KmpDependInfoTy, &PosLVal, Dependencies[I], 4890 DependenciesArray); 4891 } 4892 // Copy final depobj arrays without iterators. 4893 if (HasDepobjDeps) { 4894 for (unsigned I = 0, End = Dependencies.size(); I < End; ++I) { 4895 if (Dependencies[I].DepKind != OMPC_DEPEND_depobj) 4896 continue; 4897 emitDepobjElements(CGF, KmpDependInfoTy, PosLVal, Dependencies[I], 4898 DependenciesArray); 4899 } 4900 } 4901 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4902 DependenciesArray, CGF.VoidPtrTy); 4903 return std::make_pair(NumOfElements, DependenciesArray); 4904 } 4905 4906 Address CGOpenMPRuntime::emitDepobjDependClause( 4907 CodeGenFunction &CGF, const OMPTaskDataTy::DependData &Dependencies, 4908 SourceLocation Loc) { 4909 if (Dependencies.DepExprs.empty()) 4910 return Address::invalid(); 4911 // Process list of dependencies. 4912 ASTContext &C = CGM.getContext(); 4913 Address DependenciesArray = Address::invalid(); 4914 unsigned NumDependencies = Dependencies.DepExprs.size(); 4915 QualType FlagsTy; 4916 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4917 RecordDecl *KmpDependInfoRD = 4918 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 4919 4920 llvm::Value *Size; 4921 // Define type kmp_depend_info[<Dependencies.size()>]; 4922 // For depobj reserve one extra element to store the number of elements. 4923 // It is required to handle depobj(x) update(in) construct. 4924 // kmp_depend_info[<Dependencies.size()>] deps; 4925 llvm::Value *NumDepsVal; 4926 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoTy); 4927 if (const auto *IE = 4928 cast_or_null<OMPIteratorExpr>(Dependencies.IteratorExpr)) { 4929 NumDepsVal = llvm::ConstantInt::get(CGF.SizeTy, 1); 4930 for (unsigned I = 0, E = IE->numOfIterators(); I < E; ++I) { 4931 llvm::Value *Sz = CGF.EmitScalarExpr(IE->getHelper(I).Upper); 4932 Sz = CGF.Builder.CreateIntCast(Sz, CGF.SizeTy, /*isSigned=*/false); 4933 NumDepsVal = CGF.Builder.CreateNUWMul(NumDepsVal, Sz); 4934 } 4935 Size = CGF.Builder.CreateNUWAdd(llvm::ConstantInt::get(CGF.SizeTy, 1), 4936 NumDepsVal); 4937 CharUnits SizeInBytes = 4938 C.getTypeSizeInChars(KmpDependInfoTy).alignTo(Align); 4939 llvm::Value *RecSize = CGM.getSize(SizeInBytes); 4940 Size = CGF.Builder.CreateNUWMul(Size, RecSize); 4941 NumDepsVal = 4942 CGF.Builder.CreateIntCast(NumDepsVal, CGF.IntPtrTy, /*isSigned=*/false); 4943 } else { 4944 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 4945 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1), 4946 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 4947 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy); 4948 Size = CGM.getSize(Sz.alignTo(Align)); 4949 NumDepsVal = llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies); 4950 } 4951 // Need to allocate on the dynamic memory. 4952 llvm::Value *ThreadID = getThreadID(CGF, Loc); 4953 // Use default allocator. 4954 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4955 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 4956 4957 llvm::Value *Addr = 4958 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 4959 CGM.getModule(), OMPRTL___kmpc_alloc), 4960 Args, ".dep.arr.addr"); 4961 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4962 Addr, CGF.ConvertTypeForMem(KmpDependInfoTy)->getPointerTo()); 4963 DependenciesArray = Address(Addr, Align); 4964 // Write number of elements in the first element of array for depobj. 4965 LValue Base = CGF.MakeAddrLValue(DependenciesArray, KmpDependInfoTy); 4966 // deps[i].base_addr = NumDependencies; 4967 LValue BaseAddrLVal = CGF.EmitLValueForField( 4968 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 4969 CGF.EmitStoreOfScalar(NumDepsVal, BaseAddrLVal); 4970 llvm::PointerUnion<unsigned *, LValue *> Pos; 4971 unsigned Idx = 1; 4972 LValue PosLVal; 4973 if (Dependencies.IteratorExpr) { 4974 PosLVal = CGF.MakeAddrLValue( 4975 CGF.CreateMemTemp(C.getSizeType(), "iterator.counter.addr"), 4976 C.getSizeType()); 4977 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(CGF.SizeTy, Idx), PosLVal, 4978 /*IsInit=*/true); 4979 Pos = &PosLVal; 4980 } else { 4981 Pos = &Idx; 4982 } 4983 emitDependData(CGF, KmpDependInfoTy, Pos, Dependencies, DependenciesArray); 4984 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4985 CGF.Builder.CreateConstGEP(DependenciesArray, 1), CGF.VoidPtrTy); 4986 return DependenciesArray; 4987 } 4988 4989 void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 4990 SourceLocation Loc) { 4991 ASTContext &C = CGM.getContext(); 4992 QualType FlagsTy; 4993 getDependTypes(C, KmpDependInfoTy, FlagsTy); 4994 LValue Base = CGF.EmitLoadOfPointerLValue( 4995 DepobjLVal.getAddress(CGF), 4996 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 4997 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 4998 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4999 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 5000 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5001 Addr.getPointer(), 5002 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5003 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, 5004 CGF.VoidPtrTy); 5005 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5006 // Use default allocator. 5007 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5008 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator}; 5009 5010 // _kmpc_free(gtid, addr, nullptr); 5011 (void)CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5012 CGM.getModule(), OMPRTL___kmpc_free), 5013 Args); 5014 } 5015 5016 void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 5017 OpenMPDependClauseKind NewDepKind, 5018 SourceLocation Loc) { 5019 ASTContext &C = CGM.getContext(); 5020 QualType FlagsTy; 5021 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5022 RecordDecl *KmpDependInfoRD = 5023 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5024 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5025 llvm::Value *NumDeps; 5026 LValue Base; 5027 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 5028 5029 Address Begin = Base.getAddress(CGF); 5030 // Cast from pointer to array type to pointer to single element. 5031 llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps); 5032 // The basic structure here is a while-do loop. 5033 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); 5034 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); 5035 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5036 CGF.EmitBlock(BodyBB); 5037 llvm::PHINode *ElementPHI = 5038 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); 5039 ElementPHI->addIncoming(Begin.getPointer(), EntryBB); 5040 Begin = Address(ElementPHI, Begin.getAlignment()); 5041 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), 5042 Base.getTBAAInfo()); 5043 // deps[i].flags = NewDepKind; 5044 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind); 5045 LValue FlagsLVal = CGF.EmitLValueForField( 5046 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5047 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5048 FlagsLVal); 5049 5050 // Shift the address forward by one element. 5051 Address ElementNext = 5052 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); 5053 ElementPHI->addIncoming(ElementNext.getPointer(), 5054 CGF.Builder.GetInsertBlock()); 5055 llvm::Value *IsEmpty = 5056 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); 5057 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5058 // Done. 5059 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5060 } 5061 5062 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5063 const OMPExecutableDirective &D, 5064 llvm::Function *TaskFunction, 5065 QualType SharedsTy, Address Shareds, 5066 const Expr *IfCond, 5067 const OMPTaskDataTy &Data) { 5068 if (!CGF.HaveInsertPoint()) 5069 return; 5070 5071 TaskResultTy Result = 5072 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5073 llvm::Value *NewTask = Result.NewTask; 5074 llvm::Function *TaskEntry = Result.TaskEntry; 5075 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5076 LValue TDBase = Result.TDBase; 5077 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5078 // Process list of dependences. 5079 Address DependenciesArray = Address::invalid(); 5080 llvm::Value *NumOfElements; 5081 std::tie(NumOfElements, DependenciesArray) = 5082 emitDependClause(CGF, Data.Dependences, Loc); 5083 5084 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5085 // libcall. 5086 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5087 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5088 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5089 // list is not empty 5090 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5091 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5092 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5093 llvm::Value *DepTaskArgs[7]; 5094 if (!Data.Dependences.empty()) { 5095 DepTaskArgs[0] = UpLoc; 5096 DepTaskArgs[1] = ThreadID; 5097 DepTaskArgs[2] = NewTask; 5098 DepTaskArgs[3] = NumOfElements; 5099 DepTaskArgs[4] = DependenciesArray.getPointer(); 5100 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5101 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5102 } 5103 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs, 5104 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5105 if (!Data.Tied) { 5106 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5107 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5108 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5109 } 5110 if (!Data.Dependences.empty()) { 5111 CGF.EmitRuntimeCall( 5112 OMPBuilder.getOrCreateRuntimeFunction( 5113 CGM.getModule(), OMPRTL___kmpc_omp_task_with_deps), 5114 DepTaskArgs); 5115 } else { 5116 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5117 CGM.getModule(), OMPRTL___kmpc_omp_task), 5118 TaskArgs); 5119 } 5120 // Check if parent region is untied and build return for untied task; 5121 if (auto *Region = 5122 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5123 Region->emitUntiedSwitch(CGF); 5124 }; 5125 5126 llvm::Value *DepWaitTaskArgs[6]; 5127 if (!Data.Dependences.empty()) { 5128 DepWaitTaskArgs[0] = UpLoc; 5129 DepWaitTaskArgs[1] = ThreadID; 5130 DepWaitTaskArgs[2] = NumOfElements; 5131 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5132 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5133 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5134 } 5135 auto &M = CGM.getModule(); 5136 auto &&ElseCodeGen = [this, &M, &TaskArgs, ThreadID, NewTaskNewTaskTTy, 5137 TaskEntry, &Data, &DepWaitTaskArgs, 5138 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5139 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5140 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5141 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5142 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5143 // is specified. 5144 if (!Data.Dependences.empty()) 5145 CGF.EmitRuntimeCall( 5146 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps), 5147 DepWaitTaskArgs); 5148 // Call proxy_task_entry(gtid, new_task); 5149 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5150 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5151 Action.Enter(CGF); 5152 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5153 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5154 OutlinedFnArgs); 5155 }; 5156 5157 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5158 // kmp_task_t *new_task); 5159 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5160 // kmp_task_t *new_task); 5161 RegionCodeGenTy RCG(CodeGen); 5162 CommonActionTy Action(OMPBuilder.getOrCreateRuntimeFunction( 5163 M, OMPRTL___kmpc_omp_task_begin_if0), 5164 TaskArgs, 5165 OMPBuilder.getOrCreateRuntimeFunction( 5166 M, OMPRTL___kmpc_omp_task_complete_if0), 5167 TaskArgs); 5168 RCG.setAction(Action); 5169 RCG(CGF); 5170 }; 5171 5172 if (IfCond) { 5173 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5174 } else { 5175 RegionCodeGenTy ThenRCG(ThenCodeGen); 5176 ThenRCG(CGF); 5177 } 5178 } 5179 5180 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5181 const OMPLoopDirective &D, 5182 llvm::Function *TaskFunction, 5183 QualType SharedsTy, Address Shareds, 5184 const Expr *IfCond, 5185 const OMPTaskDataTy &Data) { 5186 if (!CGF.HaveInsertPoint()) 5187 return; 5188 TaskResultTy Result = 5189 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5190 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5191 // libcall. 5192 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5193 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5194 // sched, kmp_uint64 grainsize, void *task_dup); 5195 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5196 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5197 llvm::Value *IfVal; 5198 if (IfCond) { 5199 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5200 /*isSigned=*/true); 5201 } else { 5202 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5203 } 5204 5205 LValue LBLVal = CGF.EmitLValueForField( 5206 Result.TDBase, 5207 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5208 const auto *LBVar = 5209 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5210 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5211 LBLVal.getQuals(), 5212 /*IsInitializer=*/true); 5213 LValue UBLVal = CGF.EmitLValueForField( 5214 Result.TDBase, 5215 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5216 const auto *UBVar = 5217 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5218 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5219 UBLVal.getQuals(), 5220 /*IsInitializer=*/true); 5221 LValue StLVal = CGF.EmitLValueForField( 5222 Result.TDBase, 5223 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5224 const auto *StVar = 5225 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5226 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5227 StLVal.getQuals(), 5228 /*IsInitializer=*/true); 5229 // Store reductions address. 5230 LValue RedLVal = CGF.EmitLValueForField( 5231 Result.TDBase, 5232 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5233 if (Data.Reductions) { 5234 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5235 } else { 5236 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5237 CGF.getContext().VoidPtrTy); 5238 } 5239 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5240 llvm::Value *TaskArgs[] = { 5241 UpLoc, 5242 ThreadID, 5243 Result.NewTask, 5244 IfVal, 5245 LBLVal.getPointer(CGF), 5246 UBLVal.getPointer(CGF), 5247 CGF.EmitLoadOfScalar(StLVal, Loc), 5248 llvm::ConstantInt::getSigned( 5249 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5250 llvm::ConstantInt::getSigned( 5251 CGF.IntTy, Data.Schedule.getPointer() 5252 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5253 : NoSchedule), 5254 Data.Schedule.getPointer() 5255 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5256 /*isSigned=*/false) 5257 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5258 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5259 Result.TaskDupFn, CGF.VoidPtrTy) 5260 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5261 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 5262 CGM.getModule(), OMPRTL___kmpc_taskloop), 5263 TaskArgs); 5264 } 5265 5266 /// Emit reduction operation for each element of array (required for 5267 /// array sections) LHS op = RHS. 5268 /// \param Type Type of array. 5269 /// \param LHSVar Variable on the left side of the reduction operation 5270 /// (references element of array in original variable). 5271 /// \param RHSVar Variable on the right side of the reduction operation 5272 /// (references element of array in original variable). 5273 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5274 /// RHSVar. 5275 static void EmitOMPAggregateReduction( 5276 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5277 const VarDecl *RHSVar, 5278 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5279 const Expr *, const Expr *)> &RedOpGen, 5280 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5281 const Expr *UpExpr = nullptr) { 5282 // Perform element-by-element initialization. 5283 QualType ElementTy; 5284 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5285 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5286 5287 // Drill down to the base element type on both arrays. 5288 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5289 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5290 5291 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5292 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5293 // Cast from pointer to array type to pointer to single element. 5294 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5295 // The basic structure here is a while-do loop. 5296 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5297 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5298 llvm::Value *IsEmpty = 5299 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5300 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5301 5302 // Enter the loop body, making that address the current address. 5303 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5304 CGF.EmitBlock(BodyBB); 5305 5306 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5307 5308 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5309 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5310 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5311 Address RHSElementCurrent = 5312 Address(RHSElementPHI, 5313 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5314 5315 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5316 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5317 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5318 Address LHSElementCurrent = 5319 Address(LHSElementPHI, 5320 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5321 5322 // Emit copy. 5323 CodeGenFunction::OMPPrivateScope Scope(CGF); 5324 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5325 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5326 Scope.Privatize(); 5327 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5328 Scope.ForceCleanup(); 5329 5330 // Shift the address forward by one element. 5331 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5332 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5333 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5334 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5335 // Check whether we've reached the end. 5336 llvm::Value *Done = 5337 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5338 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5339 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5340 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5341 5342 // Done. 5343 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5344 } 5345 5346 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5347 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5348 /// UDR combiner function. 5349 static void emitReductionCombiner(CodeGenFunction &CGF, 5350 const Expr *ReductionOp) { 5351 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5352 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5353 if (const auto *DRE = 5354 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5355 if (const auto *DRD = 5356 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5357 std::pair<llvm::Function *, llvm::Function *> Reduction = 5358 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5359 RValue Func = RValue::get(Reduction.first); 5360 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5361 CGF.EmitIgnoredExpr(ReductionOp); 5362 return; 5363 } 5364 CGF.EmitIgnoredExpr(ReductionOp); 5365 } 5366 5367 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5368 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5369 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5370 ArrayRef<const Expr *> ReductionOps) { 5371 ASTContext &C = CGM.getContext(); 5372 5373 // void reduction_func(void *LHSArg, void *RHSArg); 5374 FunctionArgList Args; 5375 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5376 ImplicitParamDecl::Other); 5377 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5378 ImplicitParamDecl::Other); 5379 Args.push_back(&LHSArg); 5380 Args.push_back(&RHSArg); 5381 const auto &CGFI = 5382 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5383 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5384 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5385 llvm::GlobalValue::InternalLinkage, Name, 5386 &CGM.getModule()); 5387 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5388 Fn->setDoesNotRecurse(); 5389 CodeGenFunction CGF(CGM); 5390 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5391 5392 // Dst = (void*[n])(LHSArg); 5393 // Src = (void*[n])(RHSArg); 5394 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5395 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5396 ArgsType), CGF.getPointerAlign()); 5397 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5398 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5399 ArgsType), CGF.getPointerAlign()); 5400 5401 // ... 5402 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5403 // ... 5404 CodeGenFunction::OMPPrivateScope Scope(CGF); 5405 auto IPriv = Privates.begin(); 5406 unsigned Idx = 0; 5407 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5408 const auto *RHSVar = 5409 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5410 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5411 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5412 }); 5413 const auto *LHSVar = 5414 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5415 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5416 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5417 }); 5418 QualType PrivTy = (*IPriv)->getType(); 5419 if (PrivTy->isVariablyModifiedType()) { 5420 // Get array size and emit VLA type. 5421 ++Idx; 5422 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5423 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5424 const VariableArrayType *VLA = 5425 CGF.getContext().getAsVariableArrayType(PrivTy); 5426 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5427 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5428 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5429 CGF.EmitVariablyModifiedType(PrivTy); 5430 } 5431 } 5432 Scope.Privatize(); 5433 IPriv = Privates.begin(); 5434 auto ILHS = LHSExprs.begin(); 5435 auto IRHS = RHSExprs.begin(); 5436 for (const Expr *E : ReductionOps) { 5437 if ((*IPriv)->getType()->isArrayType()) { 5438 // Emit reduction for array section. 5439 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5440 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5441 EmitOMPAggregateReduction( 5442 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5443 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5444 emitReductionCombiner(CGF, E); 5445 }); 5446 } else { 5447 // Emit reduction for array subscript or single variable. 5448 emitReductionCombiner(CGF, E); 5449 } 5450 ++IPriv; 5451 ++ILHS; 5452 ++IRHS; 5453 } 5454 Scope.ForceCleanup(); 5455 CGF.FinishFunction(); 5456 return Fn; 5457 } 5458 5459 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5460 const Expr *ReductionOp, 5461 const Expr *PrivateRef, 5462 const DeclRefExpr *LHS, 5463 const DeclRefExpr *RHS) { 5464 if (PrivateRef->getType()->isArrayType()) { 5465 // Emit reduction for array section. 5466 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5467 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5468 EmitOMPAggregateReduction( 5469 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5470 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5471 emitReductionCombiner(CGF, ReductionOp); 5472 }); 5473 } else { 5474 // Emit reduction for array subscript or single variable. 5475 emitReductionCombiner(CGF, ReductionOp); 5476 } 5477 } 5478 5479 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5480 ArrayRef<const Expr *> Privates, 5481 ArrayRef<const Expr *> LHSExprs, 5482 ArrayRef<const Expr *> RHSExprs, 5483 ArrayRef<const Expr *> ReductionOps, 5484 ReductionOptionsTy Options) { 5485 if (!CGF.HaveInsertPoint()) 5486 return; 5487 5488 bool WithNowait = Options.WithNowait; 5489 bool SimpleReduction = Options.SimpleReduction; 5490 5491 // Next code should be emitted for reduction: 5492 // 5493 // static kmp_critical_name lock = { 0 }; 5494 // 5495 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5496 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5497 // ... 5498 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5499 // *(Type<n>-1*)rhs[<n>-1]); 5500 // } 5501 // 5502 // ... 5503 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5504 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5505 // RedList, reduce_func, &<lock>)) { 5506 // case 1: 5507 // ... 5508 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5509 // ... 5510 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5511 // break; 5512 // case 2: 5513 // ... 5514 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5515 // ... 5516 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5517 // break; 5518 // default:; 5519 // } 5520 // 5521 // if SimpleReduction is true, only the next code is generated: 5522 // ... 5523 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5524 // ... 5525 5526 ASTContext &C = CGM.getContext(); 5527 5528 if (SimpleReduction) { 5529 CodeGenFunction::RunCleanupsScope Scope(CGF); 5530 auto IPriv = Privates.begin(); 5531 auto ILHS = LHSExprs.begin(); 5532 auto IRHS = RHSExprs.begin(); 5533 for (const Expr *E : ReductionOps) { 5534 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5535 cast<DeclRefExpr>(*IRHS)); 5536 ++IPriv; 5537 ++ILHS; 5538 ++IRHS; 5539 } 5540 return; 5541 } 5542 5543 // 1. Build a list of reduction variables. 5544 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5545 auto Size = RHSExprs.size(); 5546 for (const Expr *E : Privates) { 5547 if (E->getType()->isVariablyModifiedType()) 5548 // Reserve place for array size. 5549 ++Size; 5550 } 5551 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5552 QualType ReductionArrayTy = 5553 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5554 /*IndexTypeQuals=*/0); 5555 Address ReductionList = 5556 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5557 auto IPriv = Privates.begin(); 5558 unsigned Idx = 0; 5559 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5560 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5561 CGF.Builder.CreateStore( 5562 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5563 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5564 Elem); 5565 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5566 // Store array size. 5567 ++Idx; 5568 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5569 llvm::Value *Size = CGF.Builder.CreateIntCast( 5570 CGF.getVLASize( 5571 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5572 .NumElts, 5573 CGF.SizeTy, /*isSigned=*/false); 5574 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5575 Elem); 5576 } 5577 } 5578 5579 // 2. Emit reduce_func(). 5580 llvm::Function *ReductionFn = emitReductionFunction( 5581 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5582 LHSExprs, RHSExprs, ReductionOps); 5583 5584 // 3. Create static kmp_critical_name lock = { 0 }; 5585 std::string Name = getName({"reduction"}); 5586 llvm::Value *Lock = getCriticalRegionLock(Name); 5587 5588 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5589 // RedList, reduce_func, &<lock>); 5590 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5591 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5592 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5593 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5594 ReductionList.getPointer(), CGF.VoidPtrTy); 5595 llvm::Value *Args[] = { 5596 IdentTLoc, // ident_t *<loc> 5597 ThreadId, // i32 <gtid> 5598 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5599 ReductionArrayTySize, // size_type sizeof(RedList) 5600 RL, // void *RedList 5601 ReductionFn, // void (*) (void *, void *) <reduce_func> 5602 Lock // kmp_critical_name *&<lock> 5603 }; 5604 llvm::Value *Res = CGF.EmitRuntimeCall( 5605 OMPBuilder.getOrCreateRuntimeFunction( 5606 CGM.getModule(), 5607 WithNowait ? OMPRTL___kmpc_reduce_nowait : OMPRTL___kmpc_reduce), 5608 Args); 5609 5610 // 5. Build switch(res) 5611 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5612 llvm::SwitchInst *SwInst = 5613 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5614 5615 // 6. Build case 1: 5616 // ... 5617 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5618 // ... 5619 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5620 // break; 5621 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5622 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5623 CGF.EmitBlock(Case1BB); 5624 5625 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5626 llvm::Value *EndArgs[] = { 5627 IdentTLoc, // ident_t *<loc> 5628 ThreadId, // i32 <gtid> 5629 Lock // kmp_critical_name *&<lock> 5630 }; 5631 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5632 CodeGenFunction &CGF, PrePostActionTy &Action) { 5633 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5634 auto IPriv = Privates.begin(); 5635 auto ILHS = LHSExprs.begin(); 5636 auto IRHS = RHSExprs.begin(); 5637 for (const Expr *E : ReductionOps) { 5638 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5639 cast<DeclRefExpr>(*IRHS)); 5640 ++IPriv; 5641 ++ILHS; 5642 ++IRHS; 5643 } 5644 }; 5645 RegionCodeGenTy RCG(CodeGen); 5646 CommonActionTy Action( 5647 nullptr, llvm::None, 5648 OMPBuilder.getOrCreateRuntimeFunction( 5649 CGM.getModule(), WithNowait ? OMPRTL___kmpc_end_reduce_nowait 5650 : OMPRTL___kmpc_end_reduce), 5651 EndArgs); 5652 RCG.setAction(Action); 5653 RCG(CGF); 5654 5655 CGF.EmitBranch(DefaultBB); 5656 5657 // 7. Build case 2: 5658 // ... 5659 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5660 // ... 5661 // break; 5662 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5663 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5664 CGF.EmitBlock(Case2BB); 5665 5666 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5667 CodeGenFunction &CGF, PrePostActionTy &Action) { 5668 auto ILHS = LHSExprs.begin(); 5669 auto IRHS = RHSExprs.begin(); 5670 auto IPriv = Privates.begin(); 5671 for (const Expr *E : ReductionOps) { 5672 const Expr *XExpr = nullptr; 5673 const Expr *EExpr = nullptr; 5674 const Expr *UpExpr = nullptr; 5675 BinaryOperatorKind BO = BO_Comma; 5676 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5677 if (BO->getOpcode() == BO_Assign) { 5678 XExpr = BO->getLHS(); 5679 UpExpr = BO->getRHS(); 5680 } 5681 } 5682 // Try to emit update expression as a simple atomic. 5683 const Expr *RHSExpr = UpExpr; 5684 if (RHSExpr) { 5685 // Analyze RHS part of the whole expression. 5686 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5687 RHSExpr->IgnoreParenImpCasts())) { 5688 // If this is a conditional operator, analyze its condition for 5689 // min/max reduction operator. 5690 RHSExpr = ACO->getCond(); 5691 } 5692 if (const auto *BORHS = 5693 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5694 EExpr = BORHS->getRHS(); 5695 BO = BORHS->getOpcode(); 5696 } 5697 } 5698 if (XExpr) { 5699 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5700 auto &&AtomicRedGen = [BO, VD, 5701 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5702 const Expr *EExpr, const Expr *UpExpr) { 5703 LValue X = CGF.EmitLValue(XExpr); 5704 RValue E; 5705 if (EExpr) 5706 E = CGF.EmitAnyExpr(EExpr); 5707 CGF.EmitOMPAtomicSimpleUpdateExpr( 5708 X, E, BO, /*IsXLHSInRHSPart=*/true, 5709 llvm::AtomicOrdering::Monotonic, Loc, 5710 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5711 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5712 PrivateScope.addPrivate( 5713 VD, [&CGF, VD, XRValue, Loc]() { 5714 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5715 CGF.emitOMPSimpleStore( 5716 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5717 VD->getType().getNonReferenceType(), Loc); 5718 return LHSTemp; 5719 }); 5720 (void)PrivateScope.Privatize(); 5721 return CGF.EmitAnyExpr(UpExpr); 5722 }); 5723 }; 5724 if ((*IPriv)->getType()->isArrayType()) { 5725 // Emit atomic reduction for array section. 5726 const auto *RHSVar = 5727 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5728 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5729 AtomicRedGen, XExpr, EExpr, UpExpr); 5730 } else { 5731 // Emit atomic reduction for array subscript or single variable. 5732 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5733 } 5734 } else { 5735 // Emit as a critical region. 5736 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5737 const Expr *, const Expr *) { 5738 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5739 std::string Name = RT.getName({"atomic_reduction"}); 5740 RT.emitCriticalRegion( 5741 CGF, Name, 5742 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5743 Action.Enter(CGF); 5744 emitReductionCombiner(CGF, E); 5745 }, 5746 Loc); 5747 }; 5748 if ((*IPriv)->getType()->isArrayType()) { 5749 const auto *LHSVar = 5750 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5751 const auto *RHSVar = 5752 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5753 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5754 CritRedGen); 5755 } else { 5756 CritRedGen(CGF, nullptr, nullptr, nullptr); 5757 } 5758 } 5759 ++ILHS; 5760 ++IRHS; 5761 ++IPriv; 5762 } 5763 }; 5764 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5765 if (!WithNowait) { 5766 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5767 llvm::Value *EndArgs[] = { 5768 IdentTLoc, // ident_t *<loc> 5769 ThreadId, // i32 <gtid> 5770 Lock // kmp_critical_name *&<lock> 5771 }; 5772 CommonActionTy Action(nullptr, llvm::None, 5773 OMPBuilder.getOrCreateRuntimeFunction( 5774 CGM.getModule(), OMPRTL___kmpc_end_reduce), 5775 EndArgs); 5776 AtomicRCG.setAction(Action); 5777 AtomicRCG(CGF); 5778 } else { 5779 AtomicRCG(CGF); 5780 } 5781 5782 CGF.EmitBranch(DefaultBB); 5783 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5784 } 5785 5786 /// Generates unique name for artificial threadprivate variables. 5787 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5788 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5789 const Expr *Ref) { 5790 SmallString<256> Buffer; 5791 llvm::raw_svector_ostream Out(Buffer); 5792 const clang::DeclRefExpr *DE; 5793 const VarDecl *D = ::getBaseDecl(Ref, DE); 5794 if (!D) 5795 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5796 D = D->getCanonicalDecl(); 5797 std::string Name = CGM.getOpenMPRuntime().getName( 5798 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5799 Out << Prefix << Name << "_" 5800 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5801 return std::string(Out.str()); 5802 } 5803 5804 /// Emits reduction initializer function: 5805 /// \code 5806 /// void @.red_init(void* %arg, void* %orig) { 5807 /// %0 = bitcast void* %arg to <type>* 5808 /// store <type> <init>, <type>* %0 5809 /// ret void 5810 /// } 5811 /// \endcode 5812 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 5813 SourceLocation Loc, 5814 ReductionCodeGen &RCG, unsigned N) { 5815 ASTContext &C = CGM.getContext(); 5816 QualType VoidPtrTy = C.VoidPtrTy; 5817 VoidPtrTy.addRestrict(); 5818 FunctionArgList Args; 5819 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5820 ImplicitParamDecl::Other); 5821 ImplicitParamDecl ParamOrig(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, VoidPtrTy, 5822 ImplicitParamDecl::Other); 5823 Args.emplace_back(&Param); 5824 Args.emplace_back(&ParamOrig); 5825 const auto &FnInfo = 5826 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5827 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5828 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 5829 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5830 Name, &CGM.getModule()); 5831 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5832 Fn->setDoesNotRecurse(); 5833 CodeGenFunction CGF(CGM); 5834 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5835 Address PrivateAddr = CGF.EmitLoadOfPointer( 5836 CGF.GetAddrOfLocalVar(&Param), 5837 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5838 llvm::Value *Size = nullptr; 5839 // If the size of the reduction item is non-constant, load it from global 5840 // threadprivate variable. 5841 if (RCG.getSizes(N).second) { 5842 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5843 CGF, CGM.getContext().getSizeType(), 5844 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5845 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5846 CGM.getContext().getSizeType(), Loc); 5847 } 5848 RCG.emitAggregateType(CGF, N, Size); 5849 LValue OrigLVal; 5850 // If initializer uses initializer from declare reduction construct, emit a 5851 // pointer to the address of the original reduction item (reuired by reduction 5852 // initializer) 5853 if (RCG.usesReductionInitializer(N)) { 5854 Address SharedAddr = CGF.GetAddrOfLocalVar(&ParamOrig); 5855 SharedAddr = CGF.EmitLoadOfPointer( 5856 SharedAddr, 5857 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 5858 OrigLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 5859 } else { 5860 OrigLVal = CGF.MakeNaturalAlignAddrLValue( 5861 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 5862 CGM.getContext().VoidPtrTy); 5863 } 5864 // Emit the initializer: 5865 // %0 = bitcast void* %arg to <type>* 5866 // store <type> <init>, <type>* %0 5867 RCG.emitInitialization(CGF, N, PrivateAddr, OrigLVal, 5868 [](CodeGenFunction &) { return false; }); 5869 CGF.FinishFunction(); 5870 return Fn; 5871 } 5872 5873 /// Emits reduction combiner function: 5874 /// \code 5875 /// void @.red_comb(void* %arg0, void* %arg1) { 5876 /// %lhs = bitcast void* %arg0 to <type>* 5877 /// %rhs = bitcast void* %arg1 to <type>* 5878 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 5879 /// store <type> %2, <type>* %lhs 5880 /// ret void 5881 /// } 5882 /// \endcode 5883 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 5884 SourceLocation Loc, 5885 ReductionCodeGen &RCG, unsigned N, 5886 const Expr *ReductionOp, 5887 const Expr *LHS, const Expr *RHS, 5888 const Expr *PrivateRef) { 5889 ASTContext &C = CGM.getContext(); 5890 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 5891 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 5892 FunctionArgList Args; 5893 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 5894 C.VoidPtrTy, ImplicitParamDecl::Other); 5895 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5896 ImplicitParamDecl::Other); 5897 Args.emplace_back(&ParamInOut); 5898 Args.emplace_back(&ParamIn); 5899 const auto &FnInfo = 5900 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5901 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5902 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 5903 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5904 Name, &CGM.getModule()); 5905 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5906 Fn->setDoesNotRecurse(); 5907 CodeGenFunction CGF(CGM); 5908 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5909 llvm::Value *Size = nullptr; 5910 // If the size of the reduction item is non-constant, load it from global 5911 // threadprivate variable. 5912 if (RCG.getSizes(N).second) { 5913 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5914 CGF, CGM.getContext().getSizeType(), 5915 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5916 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5917 CGM.getContext().getSizeType(), Loc); 5918 } 5919 RCG.emitAggregateType(CGF, N, Size); 5920 // Remap lhs and rhs variables to the addresses of the function arguments. 5921 // %lhs = bitcast void* %arg0 to <type>* 5922 // %rhs = bitcast void* %arg1 to <type>* 5923 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5924 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 5925 // Pull out the pointer to the variable. 5926 Address PtrAddr = CGF.EmitLoadOfPointer( 5927 CGF.GetAddrOfLocalVar(&ParamInOut), 5928 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5929 return CGF.Builder.CreateElementBitCast( 5930 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 5931 }); 5932 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 5933 // Pull out the pointer to the variable. 5934 Address PtrAddr = CGF.EmitLoadOfPointer( 5935 CGF.GetAddrOfLocalVar(&ParamIn), 5936 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5937 return CGF.Builder.CreateElementBitCast( 5938 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 5939 }); 5940 PrivateScope.Privatize(); 5941 // Emit the combiner body: 5942 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 5943 // store <type> %2, <type>* %lhs 5944 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 5945 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 5946 cast<DeclRefExpr>(RHS)); 5947 CGF.FinishFunction(); 5948 return Fn; 5949 } 5950 5951 /// Emits reduction finalizer function: 5952 /// \code 5953 /// void @.red_fini(void* %arg) { 5954 /// %0 = bitcast void* %arg to <type>* 5955 /// <destroy>(<type>* %0) 5956 /// ret void 5957 /// } 5958 /// \endcode 5959 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 5960 SourceLocation Loc, 5961 ReductionCodeGen &RCG, unsigned N) { 5962 if (!RCG.needCleanups(N)) 5963 return nullptr; 5964 ASTContext &C = CGM.getContext(); 5965 FunctionArgList Args; 5966 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5967 ImplicitParamDecl::Other); 5968 Args.emplace_back(&Param); 5969 const auto &FnInfo = 5970 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5971 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5972 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 5973 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5974 Name, &CGM.getModule()); 5975 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 5976 Fn->setDoesNotRecurse(); 5977 CodeGenFunction CGF(CGM); 5978 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 5979 Address PrivateAddr = CGF.EmitLoadOfPointer( 5980 CGF.GetAddrOfLocalVar(&Param), 5981 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5982 llvm::Value *Size = nullptr; 5983 // If the size of the reduction item is non-constant, load it from global 5984 // threadprivate variable. 5985 if (RCG.getSizes(N).second) { 5986 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 5987 CGF, CGM.getContext().getSizeType(), 5988 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 5989 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 5990 CGM.getContext().getSizeType(), Loc); 5991 } 5992 RCG.emitAggregateType(CGF, N, Size); 5993 // Emit the finalizer body: 5994 // <destroy>(<type>* %0) 5995 RCG.emitCleanups(CGF, N, PrivateAddr); 5996 CGF.FinishFunction(Loc); 5997 return Fn; 5998 } 5999 6000 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6001 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6002 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6003 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6004 return nullptr; 6005 6006 // Build typedef struct: 6007 // kmp_taskred_input { 6008 // void *reduce_shar; // shared reduction item 6009 // void *reduce_orig; // original reduction item used for initialization 6010 // size_t reduce_size; // size of data item 6011 // void *reduce_init; // data initialization routine 6012 // void *reduce_fini; // data finalization routine 6013 // void *reduce_comb; // data combiner routine 6014 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6015 // } kmp_taskred_input_t; 6016 ASTContext &C = CGM.getContext(); 6017 RecordDecl *RD = C.buildImplicitRecord("kmp_taskred_input_t"); 6018 RD->startDefinition(); 6019 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6020 const FieldDecl *OrigFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6021 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6022 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6023 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6024 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6025 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6026 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6027 RD->completeDefinition(); 6028 QualType RDType = C.getRecordType(RD); 6029 unsigned Size = Data.ReductionVars.size(); 6030 llvm::APInt ArraySize(/*numBits=*/64, Size); 6031 QualType ArrayRDType = C.getConstantArrayType( 6032 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6033 // kmp_task_red_input_t .rd_input.[Size]; 6034 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6035 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionOrigs, 6036 Data.ReductionCopies, Data.ReductionOps); 6037 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6038 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6039 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6040 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6041 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6042 TaskRedInput.getPointer(), Idxs, 6043 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6044 ".rd_input.gep."); 6045 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6046 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6047 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6048 RCG.emitSharedOrigLValue(CGF, Cnt); 6049 llvm::Value *CastedShared = 6050 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6051 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6052 // ElemLVal.reduce_orig = &Origs[Cnt]; 6053 LValue OrigLVal = CGF.EmitLValueForField(ElemLVal, OrigFD); 6054 llvm::Value *CastedOrig = 6055 CGF.EmitCastToVoidPtr(RCG.getOrigLValue(Cnt).getPointer(CGF)); 6056 CGF.EmitStoreOfScalar(CastedOrig, OrigLVal); 6057 RCG.emitAggregateType(CGF, Cnt); 6058 llvm::Value *SizeValInChars; 6059 llvm::Value *SizeVal; 6060 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6061 // We use delayed creation/initialization for VLAs and array sections. It is 6062 // required because runtime does not provide the way to pass the sizes of 6063 // VLAs/array sections to initializer/combiner/finalizer functions. Instead 6064 // threadprivate global variables are used to store these values and use 6065 // them in the functions. 6066 bool DelayedCreation = !!SizeVal; 6067 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6068 /*isSigned=*/false); 6069 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6070 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6071 // ElemLVal.reduce_init = init; 6072 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6073 llvm::Value *InitAddr = 6074 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6075 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6076 // ElemLVal.reduce_fini = fini; 6077 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6078 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6079 llvm::Value *FiniAddr = Fini 6080 ? CGF.EmitCastToVoidPtr(Fini) 6081 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6082 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6083 // ElemLVal.reduce_comb = comb; 6084 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6085 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6086 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6087 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6088 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6089 // ElemLVal.flags = 0; 6090 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6091 if (DelayedCreation) { 6092 CGF.EmitStoreOfScalar( 6093 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6094 FlagsLVal); 6095 } else 6096 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6097 FlagsLVal.getType()); 6098 } 6099 if (Data.IsReductionWithTaskMod) { 6100 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6101 // is_ws, int num, void *data); 6102 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6103 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6104 CGM.IntTy, /*isSigned=*/true); 6105 llvm::Value *Args[] = { 6106 IdentTLoc, GTid, 6107 llvm::ConstantInt::get(CGM.IntTy, Data.IsWorksharingReduction ? 1 : 0, 6108 /*isSigned=*/true), 6109 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6110 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6111 TaskRedInput.getPointer(), CGM.VoidPtrTy)}; 6112 return CGF.EmitRuntimeCall( 6113 OMPBuilder.getOrCreateRuntimeFunction( 6114 CGM.getModule(), OMPRTL___kmpc_taskred_modifier_init), 6115 Args); 6116 } 6117 // Build call void *__kmpc_taskred_init(int gtid, int num_data, void *data); 6118 llvm::Value *Args[] = { 6119 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6120 /*isSigned=*/true), 6121 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6122 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6123 CGM.VoidPtrTy)}; 6124 return CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6125 CGM.getModule(), OMPRTL___kmpc_taskred_init), 6126 Args); 6127 } 6128 6129 void CGOpenMPRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 6130 SourceLocation Loc, 6131 bool IsWorksharingReduction) { 6132 // Build call void *__kmpc_taskred_modifier_init(ident_t *loc, int gtid, int 6133 // is_ws, int num, void *data); 6134 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc); 6135 llvm::Value *GTid = CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6136 CGM.IntTy, /*isSigned=*/true); 6137 llvm::Value *Args[] = {IdentTLoc, GTid, 6138 llvm::ConstantInt::get(CGM.IntTy, 6139 IsWorksharingReduction ? 1 : 0, 6140 /*isSigned=*/true)}; 6141 (void)CGF.EmitRuntimeCall( 6142 OMPBuilder.getOrCreateRuntimeFunction( 6143 CGM.getModule(), OMPRTL___kmpc_task_reduction_modifier_fini), 6144 Args); 6145 } 6146 6147 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6148 SourceLocation Loc, 6149 ReductionCodeGen &RCG, 6150 unsigned N) { 6151 auto Sizes = RCG.getSizes(N); 6152 // Emit threadprivate global variable if the type is non-constant 6153 // (Sizes.second = nullptr). 6154 if (Sizes.second) { 6155 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6156 /*isSigned=*/false); 6157 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6158 CGF, CGM.getContext().getSizeType(), 6159 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6160 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6161 } 6162 } 6163 6164 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6165 SourceLocation Loc, 6166 llvm::Value *ReductionsPtr, 6167 LValue SharedLVal) { 6168 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6169 // *d); 6170 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6171 CGM.IntTy, 6172 /*isSigned=*/true), 6173 ReductionsPtr, 6174 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6175 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6176 return Address( 6177 CGF.EmitRuntimeCall( 6178 OMPBuilder.getOrCreateRuntimeFunction( 6179 CGM.getModule(), OMPRTL___kmpc_task_reduction_get_th_data), 6180 Args), 6181 SharedLVal.getAlignment()); 6182 } 6183 6184 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6185 SourceLocation Loc) { 6186 if (!CGF.HaveInsertPoint()) 6187 return; 6188 6189 if (CGF.CGM.getLangOpts().OpenMPIRBuilder) { 6190 OMPBuilder.createTaskwait(CGF.Builder); 6191 } else { 6192 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6193 // global_tid); 6194 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6195 // Ignore return result until untied tasks are supported. 6196 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6197 CGM.getModule(), OMPRTL___kmpc_omp_taskwait), 6198 Args); 6199 } 6200 6201 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6202 Region->emitUntiedSwitch(CGF); 6203 } 6204 6205 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6206 OpenMPDirectiveKind InnerKind, 6207 const RegionCodeGenTy &CodeGen, 6208 bool HasCancel) { 6209 if (!CGF.HaveInsertPoint()) 6210 return; 6211 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6212 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6213 } 6214 6215 namespace { 6216 enum RTCancelKind { 6217 CancelNoreq = 0, 6218 CancelParallel = 1, 6219 CancelLoop = 2, 6220 CancelSections = 3, 6221 CancelTaskgroup = 4 6222 }; 6223 } // anonymous namespace 6224 6225 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6226 RTCancelKind CancelKind = CancelNoreq; 6227 if (CancelRegion == OMPD_parallel) 6228 CancelKind = CancelParallel; 6229 else if (CancelRegion == OMPD_for) 6230 CancelKind = CancelLoop; 6231 else if (CancelRegion == OMPD_sections) 6232 CancelKind = CancelSections; 6233 else { 6234 assert(CancelRegion == OMPD_taskgroup); 6235 CancelKind = CancelTaskgroup; 6236 } 6237 return CancelKind; 6238 } 6239 6240 void CGOpenMPRuntime::emitCancellationPointCall( 6241 CodeGenFunction &CGF, SourceLocation Loc, 6242 OpenMPDirectiveKind CancelRegion) { 6243 if (!CGF.HaveInsertPoint()) 6244 return; 6245 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6246 // global_tid, kmp_int32 cncl_kind); 6247 if (auto *OMPRegionInfo = 6248 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6249 // For 'cancellation point taskgroup', the task region info may not have a 6250 // cancel. This may instead happen in another adjacent task. 6251 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6252 llvm::Value *Args[] = { 6253 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6254 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6255 // Ignore return result until untied tasks are supported. 6256 llvm::Value *Result = CGF.EmitRuntimeCall( 6257 OMPBuilder.getOrCreateRuntimeFunction( 6258 CGM.getModule(), OMPRTL___kmpc_cancellationpoint), 6259 Args); 6260 // if (__kmpc_cancellationpoint()) { 6261 // exit from construct; 6262 // } 6263 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6264 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6265 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6266 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6267 CGF.EmitBlock(ExitBB); 6268 // exit from construct; 6269 CodeGenFunction::JumpDest CancelDest = 6270 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6271 CGF.EmitBranchThroughCleanup(CancelDest); 6272 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6273 } 6274 } 6275 } 6276 6277 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6278 const Expr *IfCond, 6279 OpenMPDirectiveKind CancelRegion) { 6280 if (!CGF.HaveInsertPoint()) 6281 return; 6282 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6283 // kmp_int32 cncl_kind); 6284 auto &M = CGM.getModule(); 6285 if (auto *OMPRegionInfo = 6286 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6287 auto &&ThenGen = [this, &M, Loc, CancelRegion, 6288 OMPRegionInfo](CodeGenFunction &CGF, PrePostActionTy &) { 6289 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6290 llvm::Value *Args[] = { 6291 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6292 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6293 // Ignore return result until untied tasks are supported. 6294 llvm::Value *Result = CGF.EmitRuntimeCall( 6295 OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_cancel), Args); 6296 // if (__kmpc_cancel()) { 6297 // exit from construct; 6298 // } 6299 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6300 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6301 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6302 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6303 CGF.EmitBlock(ExitBB); 6304 // exit from construct; 6305 CodeGenFunction::JumpDest CancelDest = 6306 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6307 CGF.EmitBranchThroughCleanup(CancelDest); 6308 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6309 }; 6310 if (IfCond) { 6311 emitIfClause(CGF, IfCond, ThenGen, 6312 [](CodeGenFunction &, PrePostActionTy &) {}); 6313 } else { 6314 RegionCodeGenTy ThenRCG(ThenGen); 6315 ThenRCG(CGF); 6316 } 6317 } 6318 } 6319 6320 namespace { 6321 /// Cleanup action for uses_allocators support. 6322 class OMPUsesAllocatorsActionTy final : public PrePostActionTy { 6323 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators; 6324 6325 public: 6326 OMPUsesAllocatorsActionTy( 6327 ArrayRef<std::pair<const Expr *, const Expr *>> Allocators) 6328 : Allocators(Allocators) {} 6329 void Enter(CodeGenFunction &CGF) override { 6330 if (!CGF.HaveInsertPoint()) 6331 return; 6332 for (const auto &AllocatorData : Allocators) { 6333 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsInit( 6334 CGF, AllocatorData.first, AllocatorData.second); 6335 } 6336 } 6337 void Exit(CodeGenFunction &CGF) override { 6338 if (!CGF.HaveInsertPoint()) 6339 return; 6340 for (const auto &AllocatorData : Allocators) { 6341 CGF.CGM.getOpenMPRuntime().emitUsesAllocatorsFini(CGF, 6342 AllocatorData.first); 6343 } 6344 } 6345 }; 6346 } // namespace 6347 6348 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6349 const OMPExecutableDirective &D, StringRef ParentName, 6350 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6351 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6352 assert(!ParentName.empty() && "Invalid target region parent name!"); 6353 HasEmittedTargetRegion = true; 6354 SmallVector<std::pair<const Expr *, const Expr *>, 4> Allocators; 6355 for (const auto *C : D.getClausesOfKind<OMPUsesAllocatorsClause>()) { 6356 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 6357 const OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 6358 if (!D.AllocatorTraits) 6359 continue; 6360 Allocators.emplace_back(D.Allocator, D.AllocatorTraits); 6361 } 6362 } 6363 OMPUsesAllocatorsActionTy UsesAllocatorAction(Allocators); 6364 CodeGen.setAction(UsesAllocatorAction); 6365 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6366 IsOffloadEntry, CodeGen); 6367 } 6368 6369 void CGOpenMPRuntime::emitUsesAllocatorsInit(CodeGenFunction &CGF, 6370 const Expr *Allocator, 6371 const Expr *AllocatorTraits) { 6372 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6373 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6374 // Use default memspace handle. 6375 llvm::Value *MemSpaceHandle = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 6376 llvm::Value *NumTraits = llvm::ConstantInt::get( 6377 CGF.IntTy, cast<ConstantArrayType>( 6378 AllocatorTraits->getType()->getAsArrayTypeUnsafe()) 6379 ->getSize() 6380 .getLimitedValue()); 6381 LValue AllocatorTraitsLVal = CGF.EmitLValue(AllocatorTraits); 6382 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6383 AllocatorTraitsLVal.getAddress(CGF), CGF.VoidPtrPtrTy); 6384 AllocatorTraitsLVal = CGF.MakeAddrLValue(Addr, CGF.getContext().VoidPtrTy, 6385 AllocatorTraitsLVal.getBaseInfo(), 6386 AllocatorTraitsLVal.getTBAAInfo()); 6387 llvm::Value *Traits = 6388 CGF.EmitLoadOfScalar(AllocatorTraitsLVal, AllocatorTraits->getExprLoc()); 6389 6390 llvm::Value *AllocatorVal = 6391 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 6392 CGM.getModule(), OMPRTL___kmpc_init_allocator), 6393 {ThreadId, MemSpaceHandle, NumTraits, Traits}); 6394 // Store to allocator. 6395 CGF.EmitVarDecl(*cast<VarDecl>( 6396 cast<DeclRefExpr>(Allocator->IgnoreParenImpCasts())->getDecl())); 6397 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6398 AllocatorVal = 6399 CGF.EmitScalarConversion(AllocatorVal, CGF.getContext().VoidPtrTy, 6400 Allocator->getType(), Allocator->getExprLoc()); 6401 CGF.EmitStoreOfScalar(AllocatorVal, AllocatorLVal); 6402 } 6403 6404 void CGOpenMPRuntime::emitUsesAllocatorsFini(CodeGenFunction &CGF, 6405 const Expr *Allocator) { 6406 llvm::Value *ThreadId = getThreadID(CGF, Allocator->getExprLoc()); 6407 ThreadId = CGF.Builder.CreateIntCast(ThreadId, CGF.IntTy, /*isSigned=*/true); 6408 LValue AllocatorLVal = CGF.EmitLValue(Allocator->IgnoreParenImpCasts()); 6409 llvm::Value *AllocatorVal = 6410 CGF.EmitLoadOfScalar(AllocatorLVal, Allocator->getExprLoc()); 6411 AllocatorVal = CGF.EmitScalarConversion(AllocatorVal, Allocator->getType(), 6412 CGF.getContext().VoidPtrTy, 6413 Allocator->getExprLoc()); 6414 (void)CGF.EmitRuntimeCall( 6415 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 6416 OMPRTL___kmpc_destroy_allocator), 6417 {ThreadId, AllocatorVal}); 6418 } 6419 6420 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6421 const OMPExecutableDirective &D, StringRef ParentName, 6422 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6423 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6424 // Create a unique name for the entry function using the source location 6425 // information of the current target region. The name will be something like: 6426 // 6427 // __omp_offloading_DD_FFFF_PP_lBB 6428 // 6429 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6430 // mangled name of the function that encloses the target region and BB is the 6431 // line number of the target region. 6432 6433 unsigned DeviceID; 6434 unsigned FileID; 6435 unsigned Line; 6436 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6437 Line); 6438 SmallString<64> EntryFnName; 6439 { 6440 llvm::raw_svector_ostream OS(EntryFnName); 6441 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6442 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6443 } 6444 6445 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6446 6447 CodeGenFunction CGF(CGM, true); 6448 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6449 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6450 6451 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6452 6453 // If this target outline function is not an offload entry, we don't need to 6454 // register it. 6455 if (!IsOffloadEntry) 6456 return; 6457 6458 // The target region ID is used by the runtime library to identify the current 6459 // target region, so it only has to be unique and not necessarily point to 6460 // anything. It could be the pointer to the outlined function that implements 6461 // the target region, but we aren't using that so that the compiler doesn't 6462 // need to keep that, and could therefore inline the host function if proven 6463 // worthwhile during optimization. In the other hand, if emitting code for the 6464 // device, the ID has to be the function address so that it can retrieved from 6465 // the offloading entry and launched by the runtime library. We also mark the 6466 // outlined function to have external linkage in case we are emitting code for 6467 // the device, because these functions will be entry points to the device. 6468 6469 if (CGM.getLangOpts().OpenMPIsDevice) { 6470 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6471 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6472 OutlinedFn->setDSOLocal(false); 6473 } else { 6474 std::string Name = getName({EntryFnName, "region_id"}); 6475 OutlinedFnID = new llvm::GlobalVariable( 6476 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6477 llvm::GlobalValue::WeakAnyLinkage, 6478 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6479 } 6480 6481 // Register the information for the entry associated with this target region. 6482 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6483 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6484 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6485 } 6486 6487 /// Checks if the expression is constant or does not have non-trivial function 6488 /// calls. 6489 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6490 // We can skip constant expressions. 6491 // We can skip expressions with trivial calls or simple expressions. 6492 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6493 !E->hasNonTrivialCall(Ctx)) && 6494 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6495 } 6496 6497 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6498 const Stmt *Body) { 6499 const Stmt *Child = Body->IgnoreContainers(); 6500 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6501 Child = nullptr; 6502 for (const Stmt *S : C->body()) { 6503 if (const auto *E = dyn_cast<Expr>(S)) { 6504 if (isTrivial(Ctx, E)) 6505 continue; 6506 } 6507 // Some of the statements can be ignored. 6508 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6509 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6510 continue; 6511 // Analyze declarations. 6512 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6513 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6514 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6515 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6516 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6517 isa<UsingDirectiveDecl>(D) || 6518 isa<OMPDeclareReductionDecl>(D) || 6519 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6520 return true; 6521 const auto *VD = dyn_cast<VarDecl>(D); 6522 if (!VD) 6523 return false; 6524 return VD->isConstexpr() || 6525 ((VD->getType().isTrivialType(Ctx) || 6526 VD->getType()->isReferenceType()) && 6527 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6528 })) 6529 continue; 6530 } 6531 // Found multiple children - cannot get the one child only. 6532 if (Child) 6533 return nullptr; 6534 Child = S; 6535 } 6536 if (Child) 6537 Child = Child->IgnoreContainers(); 6538 } 6539 return Child; 6540 } 6541 6542 /// Emit the number of teams for a target directive. Inspect the num_teams 6543 /// clause associated with a teams construct combined or closely nested 6544 /// with the target directive. 6545 /// 6546 /// Emit a team of size one for directives such as 'target parallel' that 6547 /// have no associated teams construct. 6548 /// 6549 /// Otherwise, return nullptr. 6550 static llvm::Value * 6551 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6552 const OMPExecutableDirective &D) { 6553 assert(!CGF.getLangOpts().OpenMPIsDevice && 6554 "Clauses associated with the teams directive expected to be emitted " 6555 "only for the host!"); 6556 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6557 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6558 "Expected target-based executable directive."); 6559 CGBuilderTy &Bld = CGF.Builder; 6560 switch (DirectiveKind) { 6561 case OMPD_target: { 6562 const auto *CS = D.getInnermostCapturedStmt(); 6563 const auto *Body = 6564 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6565 const Stmt *ChildStmt = 6566 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6567 if (const auto *NestedDir = 6568 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6569 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6570 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6571 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6572 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6573 const Expr *NumTeams = 6574 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6575 llvm::Value *NumTeamsVal = 6576 CGF.EmitScalarExpr(NumTeams, 6577 /*IgnoreResultAssign*/ true); 6578 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6579 /*isSigned=*/true); 6580 } 6581 return Bld.getInt32(0); 6582 } 6583 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6584 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6585 return Bld.getInt32(1); 6586 return Bld.getInt32(0); 6587 } 6588 return nullptr; 6589 } 6590 case OMPD_target_teams: 6591 case OMPD_target_teams_distribute: 6592 case OMPD_target_teams_distribute_simd: 6593 case OMPD_target_teams_distribute_parallel_for: 6594 case OMPD_target_teams_distribute_parallel_for_simd: { 6595 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6596 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6597 const Expr *NumTeams = 6598 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6599 llvm::Value *NumTeamsVal = 6600 CGF.EmitScalarExpr(NumTeams, 6601 /*IgnoreResultAssign*/ true); 6602 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6603 /*isSigned=*/true); 6604 } 6605 return Bld.getInt32(0); 6606 } 6607 case OMPD_target_parallel: 6608 case OMPD_target_parallel_for: 6609 case OMPD_target_parallel_for_simd: 6610 case OMPD_target_simd: 6611 return Bld.getInt32(1); 6612 case OMPD_parallel: 6613 case OMPD_for: 6614 case OMPD_parallel_for: 6615 case OMPD_parallel_master: 6616 case OMPD_parallel_sections: 6617 case OMPD_for_simd: 6618 case OMPD_parallel_for_simd: 6619 case OMPD_cancel: 6620 case OMPD_cancellation_point: 6621 case OMPD_ordered: 6622 case OMPD_threadprivate: 6623 case OMPD_allocate: 6624 case OMPD_task: 6625 case OMPD_simd: 6626 case OMPD_sections: 6627 case OMPD_section: 6628 case OMPD_single: 6629 case OMPD_master: 6630 case OMPD_critical: 6631 case OMPD_taskyield: 6632 case OMPD_barrier: 6633 case OMPD_taskwait: 6634 case OMPD_taskgroup: 6635 case OMPD_atomic: 6636 case OMPD_flush: 6637 case OMPD_depobj: 6638 case OMPD_scan: 6639 case OMPD_teams: 6640 case OMPD_target_data: 6641 case OMPD_target_exit_data: 6642 case OMPD_target_enter_data: 6643 case OMPD_distribute: 6644 case OMPD_distribute_simd: 6645 case OMPD_distribute_parallel_for: 6646 case OMPD_distribute_parallel_for_simd: 6647 case OMPD_teams_distribute: 6648 case OMPD_teams_distribute_simd: 6649 case OMPD_teams_distribute_parallel_for: 6650 case OMPD_teams_distribute_parallel_for_simd: 6651 case OMPD_target_update: 6652 case OMPD_declare_simd: 6653 case OMPD_declare_variant: 6654 case OMPD_begin_declare_variant: 6655 case OMPD_end_declare_variant: 6656 case OMPD_declare_target: 6657 case OMPD_end_declare_target: 6658 case OMPD_declare_reduction: 6659 case OMPD_declare_mapper: 6660 case OMPD_taskloop: 6661 case OMPD_taskloop_simd: 6662 case OMPD_master_taskloop: 6663 case OMPD_master_taskloop_simd: 6664 case OMPD_parallel_master_taskloop: 6665 case OMPD_parallel_master_taskloop_simd: 6666 case OMPD_requires: 6667 case OMPD_unknown: 6668 break; 6669 default: 6670 break; 6671 } 6672 llvm_unreachable("Unexpected directive kind."); 6673 } 6674 6675 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6676 llvm::Value *DefaultThreadLimitVal) { 6677 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6678 CGF.getContext(), CS->getCapturedStmt()); 6679 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6680 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6681 llvm::Value *NumThreads = nullptr; 6682 llvm::Value *CondVal = nullptr; 6683 // Handle if clause. If if clause present, the number of threads is 6684 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6685 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6686 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6687 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6688 const OMPIfClause *IfClause = nullptr; 6689 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6690 if (C->getNameModifier() == OMPD_unknown || 6691 C->getNameModifier() == OMPD_parallel) { 6692 IfClause = C; 6693 break; 6694 } 6695 } 6696 if (IfClause) { 6697 const Expr *Cond = IfClause->getCondition(); 6698 bool Result; 6699 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6700 if (!Result) 6701 return CGF.Builder.getInt32(1); 6702 } else { 6703 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6704 if (const auto *PreInit = 6705 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6706 for (const auto *I : PreInit->decls()) { 6707 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6708 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6709 } else { 6710 CodeGenFunction::AutoVarEmission Emission = 6711 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6712 CGF.EmitAutoVarCleanups(Emission); 6713 } 6714 } 6715 } 6716 CondVal = CGF.EvaluateExprAsBool(Cond); 6717 } 6718 } 6719 } 6720 // Check the value of num_threads clause iff if clause was not specified 6721 // or is not evaluated to false. 6722 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6723 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6724 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6725 const auto *NumThreadsClause = 6726 Dir->getSingleClause<OMPNumThreadsClause>(); 6727 CodeGenFunction::LexicalScope Scope( 6728 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6729 if (const auto *PreInit = 6730 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6731 for (const auto *I : PreInit->decls()) { 6732 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6733 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6734 } else { 6735 CodeGenFunction::AutoVarEmission Emission = 6736 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6737 CGF.EmitAutoVarCleanups(Emission); 6738 } 6739 } 6740 } 6741 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6742 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6743 /*isSigned=*/false); 6744 if (DefaultThreadLimitVal) 6745 NumThreads = CGF.Builder.CreateSelect( 6746 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6747 DefaultThreadLimitVal, NumThreads); 6748 } else { 6749 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6750 : CGF.Builder.getInt32(0); 6751 } 6752 // Process condition of the if clause. 6753 if (CondVal) { 6754 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6755 CGF.Builder.getInt32(1)); 6756 } 6757 return NumThreads; 6758 } 6759 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6760 return CGF.Builder.getInt32(1); 6761 return DefaultThreadLimitVal; 6762 } 6763 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6764 : CGF.Builder.getInt32(0); 6765 } 6766 6767 /// Emit the number of threads for a target directive. Inspect the 6768 /// thread_limit clause associated with a teams construct combined or closely 6769 /// nested with the target directive. 6770 /// 6771 /// Emit the num_threads clause for directives such as 'target parallel' that 6772 /// have no associated teams construct. 6773 /// 6774 /// Otherwise, return nullptr. 6775 static llvm::Value * 6776 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6777 const OMPExecutableDirective &D) { 6778 assert(!CGF.getLangOpts().OpenMPIsDevice && 6779 "Clauses associated with the teams directive expected to be emitted " 6780 "only for the host!"); 6781 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6782 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6783 "Expected target-based executable directive."); 6784 CGBuilderTy &Bld = CGF.Builder; 6785 llvm::Value *ThreadLimitVal = nullptr; 6786 llvm::Value *NumThreadsVal = nullptr; 6787 switch (DirectiveKind) { 6788 case OMPD_target: { 6789 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6790 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6791 return NumThreads; 6792 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6793 CGF.getContext(), CS->getCapturedStmt()); 6794 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6795 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6796 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6797 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6798 const auto *ThreadLimitClause = 6799 Dir->getSingleClause<OMPThreadLimitClause>(); 6800 CodeGenFunction::LexicalScope Scope( 6801 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6802 if (const auto *PreInit = 6803 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6804 for (const auto *I : PreInit->decls()) { 6805 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6806 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6807 } else { 6808 CodeGenFunction::AutoVarEmission Emission = 6809 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6810 CGF.EmitAutoVarCleanups(Emission); 6811 } 6812 } 6813 } 6814 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6815 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6816 ThreadLimitVal = 6817 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6818 } 6819 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6820 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6821 CS = Dir->getInnermostCapturedStmt(); 6822 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6823 CGF.getContext(), CS->getCapturedStmt()); 6824 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6825 } 6826 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6827 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6828 CS = Dir->getInnermostCapturedStmt(); 6829 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6830 return NumThreads; 6831 } 6832 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6833 return Bld.getInt32(1); 6834 } 6835 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6836 } 6837 case OMPD_target_teams: { 6838 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6839 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6840 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6841 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6842 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6843 ThreadLimitVal = 6844 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6845 } 6846 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6847 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6848 return NumThreads; 6849 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6850 CGF.getContext(), CS->getCapturedStmt()); 6851 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6852 if (Dir->getDirectiveKind() == OMPD_distribute) { 6853 CS = Dir->getInnermostCapturedStmt(); 6854 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6855 return NumThreads; 6856 } 6857 } 6858 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6859 } 6860 case OMPD_target_teams_distribute: 6861 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6862 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6863 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6864 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6865 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6866 ThreadLimitVal = 6867 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6868 } 6869 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6870 case OMPD_target_parallel: 6871 case OMPD_target_parallel_for: 6872 case OMPD_target_parallel_for_simd: 6873 case OMPD_target_teams_distribute_parallel_for: 6874 case OMPD_target_teams_distribute_parallel_for_simd: { 6875 llvm::Value *CondVal = nullptr; 6876 // Handle if clause. If if clause present, the number of threads is 6877 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6878 if (D.hasClausesOfKind<OMPIfClause>()) { 6879 const OMPIfClause *IfClause = nullptr; 6880 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6881 if (C->getNameModifier() == OMPD_unknown || 6882 C->getNameModifier() == OMPD_parallel) { 6883 IfClause = C; 6884 break; 6885 } 6886 } 6887 if (IfClause) { 6888 const Expr *Cond = IfClause->getCondition(); 6889 bool Result; 6890 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6891 if (!Result) 6892 return Bld.getInt32(1); 6893 } else { 6894 CodeGenFunction::RunCleanupsScope Scope(CGF); 6895 CondVal = CGF.EvaluateExprAsBool(Cond); 6896 } 6897 } 6898 } 6899 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6900 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6901 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6902 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6903 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6904 ThreadLimitVal = 6905 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6906 } 6907 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6908 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6909 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6910 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6911 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6912 NumThreadsVal = 6913 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6914 ThreadLimitVal = ThreadLimitVal 6915 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6916 ThreadLimitVal), 6917 NumThreadsVal, ThreadLimitVal) 6918 : NumThreadsVal; 6919 } 6920 if (!ThreadLimitVal) 6921 ThreadLimitVal = Bld.getInt32(0); 6922 if (CondVal) 6923 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6924 return ThreadLimitVal; 6925 } 6926 case OMPD_target_teams_distribute_simd: 6927 case OMPD_target_simd: 6928 return Bld.getInt32(1); 6929 case OMPD_parallel: 6930 case OMPD_for: 6931 case OMPD_parallel_for: 6932 case OMPD_parallel_master: 6933 case OMPD_parallel_sections: 6934 case OMPD_for_simd: 6935 case OMPD_parallel_for_simd: 6936 case OMPD_cancel: 6937 case OMPD_cancellation_point: 6938 case OMPD_ordered: 6939 case OMPD_threadprivate: 6940 case OMPD_allocate: 6941 case OMPD_task: 6942 case OMPD_simd: 6943 case OMPD_sections: 6944 case OMPD_section: 6945 case OMPD_single: 6946 case OMPD_master: 6947 case OMPD_critical: 6948 case OMPD_taskyield: 6949 case OMPD_barrier: 6950 case OMPD_taskwait: 6951 case OMPD_taskgroup: 6952 case OMPD_atomic: 6953 case OMPD_flush: 6954 case OMPD_depobj: 6955 case OMPD_scan: 6956 case OMPD_teams: 6957 case OMPD_target_data: 6958 case OMPD_target_exit_data: 6959 case OMPD_target_enter_data: 6960 case OMPD_distribute: 6961 case OMPD_distribute_simd: 6962 case OMPD_distribute_parallel_for: 6963 case OMPD_distribute_parallel_for_simd: 6964 case OMPD_teams_distribute: 6965 case OMPD_teams_distribute_simd: 6966 case OMPD_teams_distribute_parallel_for: 6967 case OMPD_teams_distribute_parallel_for_simd: 6968 case OMPD_target_update: 6969 case OMPD_declare_simd: 6970 case OMPD_declare_variant: 6971 case OMPD_begin_declare_variant: 6972 case OMPD_end_declare_variant: 6973 case OMPD_declare_target: 6974 case OMPD_end_declare_target: 6975 case OMPD_declare_reduction: 6976 case OMPD_declare_mapper: 6977 case OMPD_taskloop: 6978 case OMPD_taskloop_simd: 6979 case OMPD_master_taskloop: 6980 case OMPD_master_taskloop_simd: 6981 case OMPD_parallel_master_taskloop: 6982 case OMPD_parallel_master_taskloop_simd: 6983 case OMPD_requires: 6984 case OMPD_unknown: 6985 break; 6986 default: 6987 break; 6988 } 6989 llvm_unreachable("Unsupported directive kind."); 6990 } 6991 6992 namespace { 6993 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 6994 6995 // Utility to handle information from clauses associated with a given 6996 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 6997 // It provides a convenient interface to obtain the information and generate 6998 // code for that information. 6999 class MappableExprsHandler { 7000 public: 7001 /// Values for bit flags used to specify the mapping type for 7002 /// offloading. 7003 enum OpenMPOffloadMappingFlags : uint64_t { 7004 /// No flags 7005 OMP_MAP_NONE = 0x0, 7006 /// Allocate memory on the device and move data from host to device. 7007 OMP_MAP_TO = 0x01, 7008 /// Allocate memory on the device and move data from device to host. 7009 OMP_MAP_FROM = 0x02, 7010 /// Always perform the requested mapping action on the element, even 7011 /// if it was already mapped before. 7012 OMP_MAP_ALWAYS = 0x04, 7013 /// Delete the element from the device environment, ignoring the 7014 /// current reference count associated with the element. 7015 OMP_MAP_DELETE = 0x08, 7016 /// The element being mapped is a pointer-pointee pair; both the 7017 /// pointer and the pointee should be mapped. 7018 OMP_MAP_PTR_AND_OBJ = 0x10, 7019 /// This flags signals that the base address of an entry should be 7020 /// passed to the target kernel as an argument. 7021 OMP_MAP_TARGET_PARAM = 0x20, 7022 /// Signal that the runtime library has to return the device pointer 7023 /// in the current position for the data being mapped. Used when we have the 7024 /// use_device_ptr or use_device_addr clause. 7025 OMP_MAP_RETURN_PARAM = 0x40, 7026 /// This flag signals that the reference being passed is a pointer to 7027 /// private data. 7028 OMP_MAP_PRIVATE = 0x80, 7029 /// Pass the element to the device by value. 7030 OMP_MAP_LITERAL = 0x100, 7031 /// Implicit map 7032 OMP_MAP_IMPLICIT = 0x200, 7033 /// Close is a hint to the runtime to allocate memory close to 7034 /// the target device. 7035 OMP_MAP_CLOSE = 0x400, 7036 /// 0x800 is reserved for compatibility with XLC. 7037 /// Produce a runtime error if the data is not already allocated. 7038 OMP_MAP_PRESENT = 0x1000, 7039 /// Signal that the runtime library should use args as an array of 7040 /// descriptor_dim pointers and use args_size as dims. Used when we have 7041 /// non-contiguous list items in target update directive 7042 OMP_MAP_NON_CONTIG = 0x100000000000, 7043 /// The 16 MSBs of the flags indicate whether the entry is member of some 7044 /// struct/class. 7045 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7046 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7047 }; 7048 7049 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7050 static unsigned getFlagMemberOffset() { 7051 unsigned Offset = 0; 7052 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7053 Remain = Remain >> 1) 7054 Offset++; 7055 return Offset; 7056 } 7057 7058 /// Class that holds debugging information for a data mapping to be passed to 7059 /// the runtime library. 7060 class MappingExprInfo { 7061 /// The variable declaration used for the data mapping. 7062 const ValueDecl *MapDecl = nullptr; 7063 /// The original expression used in the map clause, or null if there is 7064 /// none. 7065 const Expr *MapExpr = nullptr; 7066 7067 public: 7068 MappingExprInfo(const ValueDecl *MapDecl, const Expr *MapExpr = nullptr) 7069 : MapDecl(MapDecl), MapExpr(MapExpr) {} 7070 7071 const ValueDecl *getMapDecl() const { return MapDecl; } 7072 const Expr *getMapExpr() const { return MapExpr; } 7073 }; 7074 7075 /// Class that associates information with a base pointer to be passed to the 7076 /// runtime library. 7077 class BasePointerInfo { 7078 /// The base pointer. 7079 llvm::Value *Ptr = nullptr; 7080 /// The base declaration that refers to this device pointer, or null if 7081 /// there is none. 7082 const ValueDecl *DevPtrDecl = nullptr; 7083 7084 public: 7085 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7086 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7087 llvm::Value *operator*() const { return Ptr; } 7088 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7089 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7090 }; 7091 7092 using MapExprsArrayTy = SmallVector<MappingExprInfo, 4>; 7093 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7094 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7095 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7096 using MapMappersArrayTy = SmallVector<const ValueDecl *, 4>; 7097 using MapDimArrayTy = SmallVector<uint64_t, 4>; 7098 using MapNonContiguousArrayTy = SmallVector<MapValuesArrayTy, 4>; 7099 7100 /// This structure contains combined information generated for mappable 7101 /// clauses, including base pointers, pointers, sizes, map types, user-defined 7102 /// mappers, and non-contiguous information. 7103 struct MapCombinedInfoTy { 7104 struct StructNonContiguousInfo { 7105 bool IsNonContiguous = false; 7106 MapDimArrayTy Dims; 7107 MapNonContiguousArrayTy Offsets; 7108 MapNonContiguousArrayTy Counts; 7109 MapNonContiguousArrayTy Strides; 7110 }; 7111 MapExprsArrayTy Exprs; 7112 MapBaseValuesArrayTy BasePointers; 7113 MapValuesArrayTy Pointers; 7114 MapValuesArrayTy Sizes; 7115 MapFlagsArrayTy Types; 7116 MapMappersArrayTy Mappers; 7117 StructNonContiguousInfo NonContigInfo; 7118 7119 /// Append arrays in \a CurInfo. 7120 void append(MapCombinedInfoTy &CurInfo) { 7121 Exprs.append(CurInfo.Exprs.begin(), CurInfo.Exprs.end()); 7122 BasePointers.append(CurInfo.BasePointers.begin(), 7123 CurInfo.BasePointers.end()); 7124 Pointers.append(CurInfo.Pointers.begin(), CurInfo.Pointers.end()); 7125 Sizes.append(CurInfo.Sizes.begin(), CurInfo.Sizes.end()); 7126 Types.append(CurInfo.Types.begin(), CurInfo.Types.end()); 7127 Mappers.append(CurInfo.Mappers.begin(), CurInfo.Mappers.end()); 7128 NonContigInfo.Dims.append(CurInfo.NonContigInfo.Dims.begin(), 7129 CurInfo.NonContigInfo.Dims.end()); 7130 NonContigInfo.Offsets.append(CurInfo.NonContigInfo.Offsets.begin(), 7131 CurInfo.NonContigInfo.Offsets.end()); 7132 NonContigInfo.Counts.append(CurInfo.NonContigInfo.Counts.begin(), 7133 CurInfo.NonContigInfo.Counts.end()); 7134 NonContigInfo.Strides.append(CurInfo.NonContigInfo.Strides.begin(), 7135 CurInfo.NonContigInfo.Strides.end()); 7136 } 7137 }; 7138 7139 /// Map between a struct and the its lowest & highest elements which have been 7140 /// mapped. 7141 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7142 /// HE(FieldIndex, Pointer)} 7143 struct StructRangeInfoTy { 7144 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7145 0, Address::invalid()}; 7146 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7147 0, Address::invalid()}; 7148 Address Base = Address::invalid(); 7149 bool IsArraySection = false; 7150 }; 7151 7152 private: 7153 /// Kind that defines how a device pointer has to be returned. 7154 struct MapInfo { 7155 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7156 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7157 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7158 ArrayRef<OpenMPMotionModifierKind> MotionModifiers; 7159 bool ReturnDevicePointer = false; 7160 bool IsImplicit = false; 7161 const ValueDecl *Mapper = nullptr; 7162 const Expr *VarRef = nullptr; 7163 bool ForDeviceAddr = false; 7164 7165 MapInfo() = default; 7166 MapInfo( 7167 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7168 OpenMPMapClauseKind MapType, 7169 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7170 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7171 bool ReturnDevicePointer, bool IsImplicit, 7172 const ValueDecl *Mapper = nullptr, const Expr *VarRef = nullptr, 7173 bool ForDeviceAddr = false) 7174 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7175 MotionModifiers(MotionModifiers), 7176 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit), 7177 Mapper(Mapper), VarRef(VarRef), ForDeviceAddr(ForDeviceAddr) {} 7178 }; 7179 7180 /// If use_device_ptr or use_device_addr is used on a decl which is a struct 7181 /// member and there is no map information about it, then emission of that 7182 /// entry is deferred until the whole struct has been processed. 7183 struct DeferredDevicePtrEntryTy { 7184 const Expr *IE = nullptr; 7185 const ValueDecl *VD = nullptr; 7186 bool ForDeviceAddr = false; 7187 7188 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD, 7189 bool ForDeviceAddr) 7190 : IE(IE), VD(VD), ForDeviceAddr(ForDeviceAddr) {} 7191 }; 7192 7193 /// The target directive from where the mappable clauses were extracted. It 7194 /// is either a executable directive or a user-defined mapper directive. 7195 llvm::PointerUnion<const OMPExecutableDirective *, 7196 const OMPDeclareMapperDecl *> 7197 CurDir; 7198 7199 /// Function the directive is being generated for. 7200 CodeGenFunction &CGF; 7201 7202 /// Set of all first private variables in the current directive. 7203 /// bool data is set to true if the variable is implicitly marked as 7204 /// firstprivate, false otherwise. 7205 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7206 7207 /// Map between device pointer declarations and their expression components. 7208 /// The key value for declarations in 'this' is null. 7209 llvm::DenseMap< 7210 const ValueDecl *, 7211 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7212 DevPointersMap; 7213 7214 llvm::Value *getExprTypeSize(const Expr *E) const { 7215 QualType ExprTy = E->getType().getCanonicalType(); 7216 7217 // Calculate the size for array shaping expression. 7218 if (const auto *OAE = dyn_cast<OMPArrayShapingExpr>(E)) { 7219 llvm::Value *Size = 7220 CGF.getTypeSize(OAE->getBase()->getType()->getPointeeType()); 7221 for (const Expr *SE : OAE->getDimensions()) { 7222 llvm::Value *Sz = CGF.EmitScalarExpr(SE); 7223 Sz = CGF.EmitScalarConversion(Sz, SE->getType(), 7224 CGF.getContext().getSizeType(), 7225 SE->getExprLoc()); 7226 Size = CGF.Builder.CreateNUWMul(Size, Sz); 7227 } 7228 return Size; 7229 } 7230 7231 // Reference types are ignored for mapping purposes. 7232 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7233 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7234 7235 // Given that an array section is considered a built-in type, we need to 7236 // do the calculation based on the length of the section instead of relying 7237 // on CGF.getTypeSize(E->getType()). 7238 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7239 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7240 OAE->getBase()->IgnoreParenImpCasts()) 7241 .getCanonicalType(); 7242 7243 // If there is no length associated with the expression and lower bound is 7244 // not specified too, that means we are using the whole length of the 7245 // base. 7246 if (!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7247 !OAE->getLowerBound()) 7248 return CGF.getTypeSize(BaseTy); 7249 7250 llvm::Value *ElemSize; 7251 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7252 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7253 } else { 7254 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7255 assert(ATy && "Expecting array type if not a pointer type."); 7256 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7257 } 7258 7259 // If we don't have a length at this point, that is because we have an 7260 // array section with a single element. 7261 if (!OAE->getLength() && OAE->getColonLocFirst().isInvalid()) 7262 return ElemSize; 7263 7264 if (const Expr *LenExpr = OAE->getLength()) { 7265 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7266 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7267 CGF.getContext().getSizeType(), 7268 LenExpr->getExprLoc()); 7269 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7270 } 7271 assert(!OAE->getLength() && OAE->getColonLocFirst().isValid() && 7272 OAE->getLowerBound() && "expected array_section[lb:]."); 7273 // Size = sizetype - lb * elemtype; 7274 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7275 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7276 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7277 CGF.getContext().getSizeType(), 7278 OAE->getLowerBound()->getExprLoc()); 7279 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7280 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7281 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7282 LengthVal = CGF.Builder.CreateSelect( 7283 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7284 return LengthVal; 7285 } 7286 return CGF.getTypeSize(ExprTy); 7287 } 7288 7289 /// Return the corresponding bits for a given map clause modifier. Add 7290 /// a flag marking the map as a pointer if requested. Add a flag marking the 7291 /// map as the first one of a series of maps that relate to the same map 7292 /// expression. 7293 OpenMPOffloadMappingFlags getMapTypeBits( 7294 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7295 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, bool IsImplicit, 7296 bool AddPtrFlag, bool AddIsTargetParamFlag, bool IsNonContiguous) const { 7297 OpenMPOffloadMappingFlags Bits = 7298 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7299 switch (MapType) { 7300 case OMPC_MAP_alloc: 7301 case OMPC_MAP_release: 7302 // alloc and release is the default behavior in the runtime library, i.e. 7303 // if we don't pass any bits alloc/release that is what the runtime is 7304 // going to do. Therefore, we don't need to signal anything for these two 7305 // type modifiers. 7306 break; 7307 case OMPC_MAP_to: 7308 Bits |= OMP_MAP_TO; 7309 break; 7310 case OMPC_MAP_from: 7311 Bits |= OMP_MAP_FROM; 7312 break; 7313 case OMPC_MAP_tofrom: 7314 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7315 break; 7316 case OMPC_MAP_delete: 7317 Bits |= OMP_MAP_DELETE; 7318 break; 7319 case OMPC_MAP_unknown: 7320 llvm_unreachable("Unexpected map type!"); 7321 } 7322 if (AddPtrFlag) 7323 Bits |= OMP_MAP_PTR_AND_OBJ; 7324 if (AddIsTargetParamFlag) 7325 Bits |= OMP_MAP_TARGET_PARAM; 7326 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7327 != MapModifiers.end()) 7328 Bits |= OMP_MAP_ALWAYS; 7329 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7330 != MapModifiers.end()) 7331 Bits |= OMP_MAP_CLOSE; 7332 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_present) 7333 != MapModifiers.end()) 7334 Bits |= OMP_MAP_PRESENT; 7335 if (llvm::find(MotionModifiers, OMPC_MOTION_MODIFIER_present) 7336 != MotionModifiers.end()) 7337 Bits |= OMP_MAP_PRESENT; 7338 if (IsNonContiguous) 7339 Bits |= OMP_MAP_NON_CONTIG; 7340 return Bits; 7341 } 7342 7343 /// Return true if the provided expression is a final array section. A 7344 /// final array section, is one whose length can't be proved to be one. 7345 bool isFinalArraySectionExpression(const Expr *E) const { 7346 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7347 7348 // It is not an array section and therefore not a unity-size one. 7349 if (!OASE) 7350 return false; 7351 7352 // An array section with no colon always refer to a single element. 7353 if (OASE->getColonLocFirst().isInvalid()) 7354 return false; 7355 7356 const Expr *Length = OASE->getLength(); 7357 7358 // If we don't have a length we have to check if the array has size 1 7359 // for this dimension. Also, we should always expect a length if the 7360 // base type is pointer. 7361 if (!Length) { 7362 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7363 OASE->getBase()->IgnoreParenImpCasts()) 7364 .getCanonicalType(); 7365 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7366 return ATy->getSize().getSExtValue() != 1; 7367 // If we don't have a constant dimension length, we have to consider 7368 // the current section as having any size, so it is not necessarily 7369 // unitary. If it happen to be unity size, that's user fault. 7370 return true; 7371 } 7372 7373 // Check if the length evaluates to 1. 7374 Expr::EvalResult Result; 7375 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7376 return true; // Can have more that size 1. 7377 7378 llvm::APSInt ConstLength = Result.Val.getInt(); 7379 return ConstLength.getSExtValue() != 1; 7380 } 7381 7382 /// Generate the base pointers, section pointers, sizes, map type bits, and 7383 /// user-defined mappers (all included in \a CombinedInfo) for the provided 7384 /// map type, map or motion modifiers, and expression components. 7385 /// \a IsFirstComponent should be set to true if the provided set of 7386 /// components is the first associated with a capture. 7387 void generateInfoForComponentList( 7388 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7389 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 7390 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7391 MapCombinedInfoTy &CombinedInfo, StructRangeInfoTy &PartialStruct, 7392 bool IsFirstComponentList, bool IsImplicit, 7393 const ValueDecl *Mapper = nullptr, bool ForDeviceAddr = false, 7394 const ValueDecl *BaseDecl = nullptr, const Expr *MapExpr = nullptr, 7395 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7396 OverlappedElements = llvm::None) const { 7397 // The following summarizes what has to be generated for each map and the 7398 // types below. The generated information is expressed in this order: 7399 // base pointer, section pointer, size, flags 7400 // (to add to the ones that come from the map type and modifier). 7401 // 7402 // double d; 7403 // int i[100]; 7404 // float *p; 7405 // 7406 // struct S1 { 7407 // int i; 7408 // float f[50]; 7409 // } 7410 // struct S2 { 7411 // int i; 7412 // float f[50]; 7413 // S1 s; 7414 // double *p; 7415 // struct S2 *ps; 7416 // } 7417 // S2 s; 7418 // S2 *ps; 7419 // 7420 // map(d) 7421 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7422 // 7423 // map(i) 7424 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7425 // 7426 // map(i[1:23]) 7427 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7428 // 7429 // map(p) 7430 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7431 // 7432 // map(p[1:24]) 7433 // &p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM | PTR_AND_OBJ 7434 // in unified shared memory mode or for local pointers 7435 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7436 // 7437 // map(s) 7438 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7439 // 7440 // map(s.i) 7441 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7442 // 7443 // map(s.s.f) 7444 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7445 // 7446 // map(s.p) 7447 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7448 // 7449 // map(to: s.p[:22]) 7450 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7451 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7452 // &(s.p), &(s.p[0]), 22*sizeof(double), 7453 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7454 // (*) alloc space for struct members, only this is a target parameter 7455 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7456 // optimizes this entry out, same in the examples below) 7457 // (***) map the pointee (map: to) 7458 // 7459 // map(s.ps) 7460 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7461 // 7462 // map(from: s.ps->s.i) 7463 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7464 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7465 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7466 // 7467 // map(to: s.ps->ps) 7468 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7469 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7470 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7471 // 7472 // map(s.ps->ps->ps) 7473 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7474 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7475 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7476 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7477 // 7478 // map(to: s.ps->ps->s.f[:22]) 7479 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7480 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7481 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7482 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7483 // 7484 // map(ps) 7485 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7486 // 7487 // map(ps->i) 7488 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7489 // 7490 // map(ps->s.f) 7491 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7492 // 7493 // map(from: ps->p) 7494 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7495 // 7496 // map(to: ps->p[:22]) 7497 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7498 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7499 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7500 // 7501 // map(ps->ps) 7502 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7503 // 7504 // map(from: ps->ps->s.i) 7505 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7506 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7507 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7508 // 7509 // map(from: ps->ps->ps) 7510 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7511 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7512 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7513 // 7514 // map(ps->ps->ps->ps) 7515 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7516 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7517 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7518 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7519 // 7520 // map(to: ps->ps->ps->s.f[:22]) 7521 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7522 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7523 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7524 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7525 // 7526 // map(to: s.f[:22]) map(from: s.p[:33]) 7527 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7528 // sizeof(double*) (**), TARGET_PARAM 7529 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7530 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7531 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7532 // (*) allocate contiguous space needed to fit all mapped members even if 7533 // we allocate space for members not mapped (in this example, 7534 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7535 // them as well because they fall between &s.f[0] and &s.p) 7536 // 7537 // map(from: s.f[:22]) map(to: ps->p[:33]) 7538 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7539 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7540 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7541 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7542 // (*) the struct this entry pertains to is the 2nd element in the list of 7543 // arguments, hence MEMBER_OF(2) 7544 // 7545 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7546 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7547 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7548 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7549 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7550 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7551 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7552 // (*) the struct this entry pertains to is the 4th element in the list 7553 // of arguments, hence MEMBER_OF(4) 7554 7555 // Track if the map information being generated is the first for a capture. 7556 bool IsCaptureFirstInfo = IsFirstComponentList; 7557 // When the variable is on a declare target link or in a to clause with 7558 // unified memory, a reference is needed to hold the host/device address 7559 // of the variable. 7560 bool RequiresReference = false; 7561 7562 // Scan the components from the base to the complete expression. 7563 auto CI = Components.rbegin(); 7564 auto CE = Components.rend(); 7565 auto I = CI; 7566 7567 // Track if the map information being generated is the first for a list of 7568 // components. 7569 bool IsExpressionFirstInfo = true; 7570 bool FirstPointerInComplexData = false; 7571 Address BP = Address::invalid(); 7572 const Expr *AssocExpr = I->getAssociatedExpression(); 7573 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7574 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7575 const auto *OAShE = dyn_cast<OMPArrayShapingExpr>(AssocExpr); 7576 7577 if (isa<MemberExpr>(AssocExpr)) { 7578 // The base is the 'this' pointer. The content of the pointer is going 7579 // to be the base of the field being mapped. 7580 BP = CGF.LoadCXXThisAddress(); 7581 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7582 (OASE && 7583 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7584 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7585 } else if (OAShE && 7586 isa<CXXThisExpr>(OAShE->getBase()->IgnoreParenCasts())) { 7587 BP = Address( 7588 CGF.EmitScalarExpr(OAShE->getBase()), 7589 CGF.getContext().getTypeAlignInChars(OAShE->getBase()->getType())); 7590 } else { 7591 // The base is the reference to the variable. 7592 // BP = &Var. 7593 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7594 if (const auto *VD = 7595 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7596 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7597 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7598 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7599 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7600 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7601 RequiresReference = true; 7602 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7603 } 7604 } 7605 } 7606 7607 // If the variable is a pointer and is being dereferenced (i.e. is not 7608 // the last component), the base has to be the pointer itself, not its 7609 // reference. References are ignored for mapping purposes. 7610 QualType Ty = 7611 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7612 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7613 // No need to generate individual map information for the pointer, it 7614 // can be associated with the combined storage if shared memory mode is 7615 // active or the base declaration is not global variable. 7616 const auto *VD = dyn_cast<VarDecl>(I->getAssociatedDeclaration()); 7617 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 7618 !VD || VD->hasLocalStorage()) 7619 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7620 else 7621 FirstPointerInComplexData = true; 7622 ++I; 7623 } 7624 } 7625 7626 // Track whether a component of the list should be marked as MEMBER_OF some 7627 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7628 // in a component list should be marked as MEMBER_OF, all subsequent entries 7629 // do not belong to the base struct. E.g. 7630 // struct S2 s; 7631 // s.ps->ps->ps->f[:] 7632 // (1) (2) (3) (4) 7633 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7634 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7635 // is the pointee of ps(2) which is not member of struct s, so it should not 7636 // be marked as such (it is still PTR_AND_OBJ). 7637 // The variable is initialized to false so that PTR_AND_OBJ entries which 7638 // are not struct members are not considered (e.g. array of pointers to 7639 // data). 7640 bool ShouldBeMemberOf = false; 7641 7642 // Variable keeping track of whether or not we have encountered a component 7643 // in the component list which is a member expression. Useful when we have a 7644 // pointer or a final array section, in which case it is the previous 7645 // component in the list which tells us whether we have a member expression. 7646 // E.g. X.f[:] 7647 // While processing the final array section "[:]" it is "f" which tells us 7648 // whether we are dealing with a member of a declared struct. 7649 const MemberExpr *EncounteredME = nullptr; 7650 7651 // Track for the total number of dimension. Start from one for the dummy 7652 // dimension. 7653 uint64_t DimSize = 1; 7654 7655 bool IsNonContiguous = CombinedInfo.NonContigInfo.IsNonContiguous; 7656 7657 for (; I != CE; ++I) { 7658 // If the current component is member of a struct (parent struct) mark it. 7659 if (!EncounteredME) { 7660 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7661 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7662 // as MEMBER_OF the parent struct. 7663 if (EncounteredME) { 7664 ShouldBeMemberOf = true; 7665 // Do not emit as complex pointer if this is actually not array-like 7666 // expression. 7667 if (FirstPointerInComplexData) { 7668 QualType Ty = std::prev(I) 7669 ->getAssociatedDeclaration() 7670 ->getType() 7671 .getNonReferenceType(); 7672 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7673 FirstPointerInComplexData = false; 7674 } 7675 } 7676 } 7677 7678 auto Next = std::next(I); 7679 7680 // We need to generate the addresses and sizes if this is the last 7681 // component, if the component is a pointer or if it is an array section 7682 // whose length can't be proved to be one. If this is a pointer, it 7683 // becomes the base address for the following components. 7684 7685 // A final array section, is one whose length can't be proved to be one. 7686 // If the map item is non-contiguous then we don't treat any array section 7687 // as final array section. 7688 bool IsFinalArraySection = 7689 !IsNonContiguous && 7690 isFinalArraySectionExpression(I->getAssociatedExpression()); 7691 7692 // If we have a declaration for the mapping use that, otherwise use 7693 // the base declaration of the map clause. 7694 const ValueDecl *MapDecl = (I->getAssociatedDeclaration()) 7695 ? I->getAssociatedDeclaration() 7696 : BaseDecl; 7697 7698 // Get information on whether the element is a pointer. Have to do a 7699 // special treatment for array sections given that they are built-in 7700 // types. 7701 const auto *OASE = 7702 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7703 const auto *OAShE = 7704 dyn_cast<OMPArrayShapingExpr>(I->getAssociatedExpression()); 7705 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 7706 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 7707 bool IsPointer = 7708 OAShE || 7709 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7710 .getCanonicalType() 7711 ->isAnyPointerType()) || 7712 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7713 bool IsNonDerefPointer = IsPointer && !UO && !BO && !IsNonContiguous; 7714 7715 if (OASE) 7716 ++DimSize; 7717 7718 if (Next == CE || IsNonDerefPointer || IsFinalArraySection) { 7719 // If this is not the last component, we expect the pointer to be 7720 // associated with an array expression or member expression. 7721 assert((Next == CE || 7722 isa<MemberExpr>(Next->getAssociatedExpression()) || 7723 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7724 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 7725 isa<OMPArrayShapingExpr>(Next->getAssociatedExpression()) || 7726 isa<UnaryOperator>(Next->getAssociatedExpression()) || 7727 isa<BinaryOperator>(Next->getAssociatedExpression())) && 7728 "Unexpected expression"); 7729 7730 Address LB = Address::invalid(); 7731 if (OAShE) { 7732 LB = Address(CGF.EmitScalarExpr(OAShE->getBase()), 7733 CGF.getContext().getTypeAlignInChars( 7734 OAShE->getBase()->getType())); 7735 } else { 7736 LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7737 .getAddress(CGF); 7738 } 7739 7740 // If this component is a pointer inside the base struct then we don't 7741 // need to create any entry for it - it will be combined with the object 7742 // it is pointing to into a single PTR_AND_OBJ entry. 7743 bool IsMemberPointerOrAddr = 7744 (IsPointer || ForDeviceAddr) && EncounteredME && 7745 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7746 EncounteredME); 7747 if (!OverlappedElements.empty()) { 7748 // Handle base element with the info for overlapped elements. 7749 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7750 assert(Next == CE && 7751 "Expected last element for the overlapped elements."); 7752 assert(!IsPointer && 7753 "Unexpected base element with the pointer type."); 7754 // Mark the whole struct as the struct that requires allocation on the 7755 // device. 7756 PartialStruct.LowestElem = {0, LB}; 7757 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7758 I->getAssociatedExpression()->getType()); 7759 Address HB = CGF.Builder.CreateConstGEP( 7760 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7761 CGF.VoidPtrTy), 7762 TypeSize.getQuantity() - 1); 7763 PartialStruct.HighestElem = { 7764 std::numeric_limits<decltype( 7765 PartialStruct.HighestElem.first)>::max(), 7766 HB}; 7767 PartialStruct.Base = BP; 7768 // Emit data for non-overlapped data. 7769 OpenMPOffloadMappingFlags Flags = 7770 OMP_MAP_MEMBER_OF | 7771 getMapTypeBits(MapType, MapModifiers, MotionModifiers, IsImplicit, 7772 /*AddPtrFlag=*/false, 7773 /*AddIsTargetParamFlag=*/false, IsNonContiguous); 7774 LB = BP; 7775 llvm::Value *Size = nullptr; 7776 // Do bitcopy of all non-overlapped structure elements. 7777 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7778 Component : OverlappedElements) { 7779 Address ComponentLB = Address::invalid(); 7780 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7781 Component) { 7782 if (MC.getAssociatedDeclaration()) { 7783 ComponentLB = 7784 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7785 .getAddress(CGF); 7786 Size = CGF.Builder.CreatePtrDiff( 7787 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7788 CGF.EmitCastToVoidPtr(LB.getPointer())); 7789 break; 7790 } 7791 } 7792 assert(Size && "Failed to determine structure size"); 7793 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 7794 CombinedInfo.BasePointers.push_back(BP.getPointer()); 7795 CombinedInfo.Pointers.push_back(LB.getPointer()); 7796 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 7797 Size, CGF.Int64Ty, /*isSigned=*/true)); 7798 CombinedInfo.Types.push_back(Flags); 7799 CombinedInfo.Mappers.push_back(nullptr); 7800 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 7801 : 1); 7802 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7803 } 7804 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 7805 CombinedInfo.BasePointers.push_back(BP.getPointer()); 7806 CombinedInfo.Pointers.push_back(LB.getPointer()); 7807 Size = CGF.Builder.CreatePtrDiff( 7808 CGF.EmitCastToVoidPtr( 7809 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7810 CGF.EmitCastToVoidPtr(LB.getPointer())); 7811 CombinedInfo.Sizes.push_back( 7812 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7813 CombinedInfo.Types.push_back(Flags); 7814 CombinedInfo.Mappers.push_back(nullptr); 7815 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 7816 : 1); 7817 break; 7818 } 7819 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7820 if (!IsMemberPointerOrAddr || 7821 (Next == CE && MapType != OMPC_MAP_unknown)) { 7822 CombinedInfo.Exprs.emplace_back(MapDecl, MapExpr); 7823 CombinedInfo.BasePointers.push_back(BP.getPointer()); 7824 CombinedInfo.Pointers.push_back(LB.getPointer()); 7825 CombinedInfo.Sizes.push_back( 7826 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7827 CombinedInfo.NonContigInfo.Dims.push_back(IsNonContiguous ? DimSize 7828 : 1); 7829 7830 // If Mapper is valid, the last component inherits the mapper. 7831 bool HasMapper = Mapper && Next == CE; 7832 CombinedInfo.Mappers.push_back(HasMapper ? Mapper : nullptr); 7833 7834 // We need to add a pointer flag for each map that comes from the 7835 // same expression except for the first one. We also need to signal 7836 // this map is the first one that relates with the current capture 7837 // (there is a set of entries for each capture). 7838 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7839 MapType, MapModifiers, MotionModifiers, IsImplicit, 7840 !IsExpressionFirstInfo || RequiresReference || 7841 FirstPointerInComplexData, 7842 IsCaptureFirstInfo && !RequiresReference, IsNonContiguous); 7843 7844 if (!IsExpressionFirstInfo) { 7845 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7846 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7847 if (IsPointer) 7848 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7849 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7850 7851 if (ShouldBeMemberOf) { 7852 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7853 // should be later updated with the correct value of MEMBER_OF. 7854 Flags |= OMP_MAP_MEMBER_OF; 7855 // From now on, all subsequent PTR_AND_OBJ entries should not be 7856 // marked as MEMBER_OF. 7857 ShouldBeMemberOf = false; 7858 } 7859 } 7860 7861 CombinedInfo.Types.push_back(Flags); 7862 } 7863 7864 // If we have encountered a member expression so far, keep track of the 7865 // mapped member. If the parent is "*this", then the value declaration 7866 // is nullptr. 7867 if (EncounteredME) { 7868 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 7869 unsigned FieldIndex = FD->getFieldIndex(); 7870 7871 // Update info about the lowest and highest elements for this struct 7872 if (!PartialStruct.Base.isValid()) { 7873 PartialStruct.LowestElem = {FieldIndex, LB}; 7874 if (IsFinalArraySection) { 7875 Address HB = 7876 CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false) 7877 .getAddress(CGF); 7878 PartialStruct.HighestElem = {FieldIndex, HB}; 7879 } else { 7880 PartialStruct.HighestElem = {FieldIndex, LB}; 7881 } 7882 PartialStruct.Base = BP; 7883 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7884 PartialStruct.LowestElem = {FieldIndex, LB}; 7885 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7886 PartialStruct.HighestElem = {FieldIndex, LB}; 7887 } 7888 } 7889 7890 // Need to emit combined struct for array sections. 7891 if (IsFinalArraySection || IsNonContiguous) 7892 PartialStruct.IsArraySection = true; 7893 7894 // If we have a final array section, we are done with this expression. 7895 if (IsFinalArraySection) 7896 break; 7897 7898 // The pointer becomes the base for the next element. 7899 if (Next != CE) 7900 BP = LB; 7901 7902 IsExpressionFirstInfo = false; 7903 IsCaptureFirstInfo = false; 7904 FirstPointerInComplexData = false; 7905 } else if (FirstPointerInComplexData) { 7906 BP = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7907 .getAddress(CGF); 7908 FirstPointerInComplexData = false; 7909 } 7910 } 7911 7912 if (!IsNonContiguous) 7913 return; 7914 7915 const ASTContext &Context = CGF.getContext(); 7916 7917 // For supporting stride in array section, we need to initialize the first 7918 // dimension size as 1, first offset as 0, and first count as 1 7919 MapValuesArrayTy CurOffsets = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 0)}; 7920 MapValuesArrayTy CurCounts = {llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 7921 MapValuesArrayTy CurStrides; 7922 MapValuesArrayTy DimSizes{llvm::ConstantInt::get(CGF.CGM.Int64Ty, 1)}; 7923 uint64_t ElementTypeSize; 7924 7925 // Collect Size information for each dimension and get the element size as 7926 // the first Stride. For example, for `int arr[10][10]`, the DimSizes 7927 // should be [10, 10] and the first stride is 4 btyes. 7928 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 7929 Components) { 7930 const Expr *AssocExpr = Component.getAssociatedExpression(); 7931 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7932 7933 if (!OASE) 7934 continue; 7935 7936 QualType Ty = OMPArraySectionExpr::getBaseOriginalType(OASE->getBase()); 7937 auto *CAT = Context.getAsConstantArrayType(Ty); 7938 auto *VAT = Context.getAsVariableArrayType(Ty); 7939 7940 // We need all the dimension size except for the last dimension. 7941 assert((VAT || CAT || &Component == &*Components.begin()) && 7942 "Should be either ConstantArray or VariableArray if not the " 7943 "first Component"); 7944 7945 // Get element size if CurStrides is empty. 7946 if (CurStrides.empty()) { 7947 const Type *ElementType = nullptr; 7948 if (CAT) 7949 ElementType = CAT->getElementType().getTypePtr(); 7950 else if (VAT) 7951 ElementType = VAT->getElementType().getTypePtr(); 7952 else 7953 assert(&Component == &*Components.begin() && 7954 "Only expect pointer (non CAT or VAT) when this is the " 7955 "first Component"); 7956 // If ElementType is null, then it means the base is a pointer 7957 // (neither CAT nor VAT) and we'll attempt to get ElementType again 7958 // for next iteration. 7959 if (ElementType) { 7960 // For the case that having pointer as base, we need to remove one 7961 // level of indirection. 7962 if (&Component != &*Components.begin()) 7963 ElementType = ElementType->getPointeeOrArrayElementType(); 7964 ElementTypeSize = 7965 Context.getTypeSizeInChars(ElementType).getQuantity(); 7966 CurStrides.push_back( 7967 llvm::ConstantInt::get(CGF.Int64Ty, ElementTypeSize)); 7968 } 7969 } 7970 // Get dimension value except for the last dimension since we don't need 7971 // it. 7972 if (DimSizes.size() < Components.size() - 1) { 7973 if (CAT) 7974 DimSizes.push_back(llvm::ConstantInt::get( 7975 CGF.Int64Ty, CAT->getSize().getZExtValue())); 7976 else if (VAT) 7977 DimSizes.push_back(CGF.Builder.CreateIntCast( 7978 CGF.EmitScalarExpr(VAT->getSizeExpr()), CGF.Int64Ty, 7979 /*IsSigned=*/false)); 7980 } 7981 } 7982 7983 // Skip the dummy dimension since we have already have its information. 7984 auto DI = DimSizes.begin() + 1; 7985 // Product of dimension. 7986 llvm::Value *DimProd = 7987 llvm::ConstantInt::get(CGF.CGM.Int64Ty, ElementTypeSize); 7988 7989 // Collect info for non-contiguous. Notice that offset, count, and stride 7990 // are only meaningful for array-section, so we insert a null for anything 7991 // other than array-section. 7992 // Also, the size of offset, count, and stride are not the same as 7993 // pointers, base_pointers, sizes, or dims. Instead, the size of offset, 7994 // count, and stride are the same as the number of non-contiguous 7995 // declaration in target update to/from clause. 7996 for (const OMPClauseMappableExprCommon::MappableComponent &Component : 7997 Components) { 7998 const Expr *AssocExpr = Component.getAssociatedExpression(); 7999 8000 if (const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr)) { 8001 llvm::Value *Offset = CGF.Builder.CreateIntCast( 8002 CGF.EmitScalarExpr(AE->getIdx()), CGF.Int64Ty, 8003 /*isSigned=*/false); 8004 CurOffsets.push_back(Offset); 8005 CurCounts.push_back(llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/1)); 8006 CurStrides.push_back(CurStrides.back()); 8007 continue; 8008 } 8009 8010 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 8011 8012 if (!OASE) 8013 continue; 8014 8015 // Offset 8016 const Expr *OffsetExpr = OASE->getLowerBound(); 8017 llvm::Value *Offset = nullptr; 8018 if (!OffsetExpr) { 8019 // If offset is absent, then we just set it to zero. 8020 Offset = llvm::ConstantInt::get(CGF.Int64Ty, 0); 8021 } else { 8022 Offset = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(OffsetExpr), 8023 CGF.Int64Ty, 8024 /*isSigned=*/false); 8025 } 8026 CurOffsets.push_back(Offset); 8027 8028 // Count 8029 const Expr *CountExpr = OASE->getLength(); 8030 llvm::Value *Count = nullptr; 8031 if (!CountExpr) { 8032 // In Clang, once a high dimension is an array section, we construct all 8033 // the lower dimension as array section, however, for case like 8034 // arr[0:2][2], Clang construct the inner dimension as an array section 8035 // but it actually is not in an array section form according to spec. 8036 if (!OASE->getColonLocFirst().isValid() && 8037 !OASE->getColonLocSecond().isValid()) { 8038 Count = llvm::ConstantInt::get(CGF.Int64Ty, 1); 8039 } else { 8040 // OpenMP 5.0, 2.1.5 Array Sections, Description. 8041 // When the length is absent it defaults to ⌈(size − 8042 // lower-bound)/stride⌉, where size is the size of the array 8043 // dimension. 8044 const Expr *StrideExpr = OASE->getStride(); 8045 llvm::Value *Stride = 8046 StrideExpr 8047 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8048 CGF.Int64Ty, /*isSigned=*/false) 8049 : nullptr; 8050 if (Stride) 8051 Count = CGF.Builder.CreateUDiv( 8052 CGF.Builder.CreateNUWSub(*DI, Offset), Stride); 8053 else 8054 Count = CGF.Builder.CreateNUWSub(*DI, Offset); 8055 } 8056 } else { 8057 Count = CGF.EmitScalarExpr(CountExpr); 8058 } 8059 Count = CGF.Builder.CreateIntCast(Count, CGF.Int64Ty, /*isSigned=*/false); 8060 CurCounts.push_back(Count); 8061 8062 // Stride_n' = Stride_n * (D_0 * D_1 ... * D_n-1) * Unit size 8063 // Take `int arr[5][5][5]` and `arr[0:2:2][1:2:1][0:2:2]` as an example: 8064 // Offset Count Stride 8065 // D0 0 1 4 (int) <- dummy dimension 8066 // D1 0 2 8 (2 * (1) * 4) 8067 // D2 1 2 20 (1 * (1 * 5) * 4) 8068 // D3 0 2 200 (2 * (1 * 5 * 4) * 4) 8069 const Expr *StrideExpr = OASE->getStride(); 8070 llvm::Value *Stride = 8071 StrideExpr 8072 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(StrideExpr), 8073 CGF.Int64Ty, /*isSigned=*/false) 8074 : nullptr; 8075 DimProd = CGF.Builder.CreateNUWMul(DimProd, *(DI - 1)); 8076 if (Stride) 8077 CurStrides.push_back(CGF.Builder.CreateNUWMul(DimProd, Stride)); 8078 else 8079 CurStrides.push_back(DimProd); 8080 if (DI != DimSizes.end()) 8081 ++DI; 8082 } 8083 8084 CombinedInfo.NonContigInfo.Offsets.push_back(CurOffsets); 8085 CombinedInfo.NonContigInfo.Counts.push_back(CurCounts); 8086 CombinedInfo.NonContigInfo.Strides.push_back(CurStrides); 8087 } 8088 8089 /// Return the adjusted map modifiers if the declaration a capture refers to 8090 /// appears in a first-private clause. This is expected to be used only with 8091 /// directives that start with 'target'. 8092 MappableExprsHandler::OpenMPOffloadMappingFlags 8093 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 8094 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 8095 8096 // A first private variable captured by reference will use only the 8097 // 'private ptr' and 'map to' flag. Return the right flags if the captured 8098 // declaration is known as first-private in this handler. 8099 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 8100 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 8101 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 8102 return MappableExprsHandler::OMP_MAP_ALWAYS | 8103 MappableExprsHandler::OMP_MAP_TO; 8104 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 8105 return MappableExprsHandler::OMP_MAP_TO | 8106 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 8107 return MappableExprsHandler::OMP_MAP_PRIVATE | 8108 MappableExprsHandler::OMP_MAP_TO; 8109 } 8110 return MappableExprsHandler::OMP_MAP_TO | 8111 MappableExprsHandler::OMP_MAP_FROM; 8112 } 8113 8114 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 8115 // Rotate by getFlagMemberOffset() bits. 8116 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 8117 << getFlagMemberOffset()); 8118 } 8119 8120 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 8121 OpenMPOffloadMappingFlags MemberOfFlag) { 8122 // If the entry is PTR_AND_OBJ but has not been marked with the special 8123 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 8124 // marked as MEMBER_OF. 8125 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 8126 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 8127 return; 8128 8129 // Reset the placeholder value to prepare the flag for the assignment of the 8130 // proper MEMBER_OF value. 8131 Flags &= ~OMP_MAP_MEMBER_OF; 8132 Flags |= MemberOfFlag; 8133 } 8134 8135 void getPlainLayout(const CXXRecordDecl *RD, 8136 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 8137 bool AsBase) const { 8138 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 8139 8140 llvm::StructType *St = 8141 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 8142 8143 unsigned NumElements = St->getNumElements(); 8144 llvm::SmallVector< 8145 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 8146 RecordLayout(NumElements); 8147 8148 // Fill bases. 8149 for (const auto &I : RD->bases()) { 8150 if (I.isVirtual()) 8151 continue; 8152 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8153 // Ignore empty bases. 8154 if (Base->isEmpty() || CGF.getContext() 8155 .getASTRecordLayout(Base) 8156 .getNonVirtualSize() 8157 .isZero()) 8158 continue; 8159 8160 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 8161 RecordLayout[FieldIndex] = Base; 8162 } 8163 // Fill in virtual bases. 8164 for (const auto &I : RD->vbases()) { 8165 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8166 // Ignore empty bases. 8167 if (Base->isEmpty()) 8168 continue; 8169 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 8170 if (RecordLayout[FieldIndex]) 8171 continue; 8172 RecordLayout[FieldIndex] = Base; 8173 } 8174 // Fill in all the fields. 8175 assert(!RD->isUnion() && "Unexpected union."); 8176 for (const auto *Field : RD->fields()) { 8177 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 8178 // will fill in later.) 8179 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 8180 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 8181 RecordLayout[FieldIndex] = Field; 8182 } 8183 } 8184 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 8185 &Data : RecordLayout) { 8186 if (Data.isNull()) 8187 continue; 8188 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 8189 getPlainLayout(Base, Layout, /*AsBase=*/true); 8190 else 8191 Layout.push_back(Data.get<const FieldDecl *>()); 8192 } 8193 } 8194 8195 public: 8196 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 8197 : CurDir(&Dir), CGF(CGF) { 8198 // Extract firstprivate clause information. 8199 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 8200 for (const auto *D : C->varlists()) 8201 FirstPrivateDecls.try_emplace( 8202 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 8203 // Extract implicit firstprivates from uses_allocators clauses. 8204 for (const auto *C : Dir.getClausesOfKind<OMPUsesAllocatorsClause>()) { 8205 for (unsigned I = 0, E = C->getNumberOfAllocators(); I < E; ++I) { 8206 OMPUsesAllocatorsClause::Data D = C->getAllocatorData(I); 8207 if (const auto *DRE = dyn_cast_or_null<DeclRefExpr>(D.AllocatorTraits)) 8208 FirstPrivateDecls.try_emplace(cast<VarDecl>(DRE->getDecl()), 8209 /*Implicit=*/true); 8210 else if (const auto *VD = dyn_cast<VarDecl>( 8211 cast<DeclRefExpr>(D.Allocator->IgnoreParenImpCasts()) 8212 ->getDecl())) 8213 FirstPrivateDecls.try_emplace(VD, /*Implicit=*/true); 8214 } 8215 } 8216 // Extract device pointer clause information. 8217 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 8218 for (auto L : C->component_lists()) 8219 DevPointersMap[std::get<0>(L)].push_back(std::get<1>(L)); 8220 } 8221 8222 /// Constructor for the declare mapper directive. 8223 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 8224 : CurDir(&Dir), CGF(CGF) {} 8225 8226 /// Generate code for the combined entry if we have a partially mapped struct 8227 /// and take care of the mapping flags of the arguments corresponding to 8228 /// individual struct members. 8229 void emitCombinedEntry(MapCombinedInfoTy &CombinedInfo, 8230 MapFlagsArrayTy &CurTypes, 8231 const StructRangeInfoTy &PartialStruct, 8232 const ValueDecl *VD = nullptr, 8233 bool NotTargetParams = false) const { 8234 if (CurTypes.size() == 1 && 8235 ((CurTypes.back() & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF) && 8236 !PartialStruct.IsArraySection) 8237 return; 8238 CombinedInfo.Exprs.push_back(VD); 8239 // Base is the base of the struct 8240 CombinedInfo.BasePointers.push_back(PartialStruct.Base.getPointer()); 8241 // Pointer is the address of the lowest element 8242 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 8243 CombinedInfo.Pointers.push_back(LB); 8244 // There should not be a mapper for a combined entry. 8245 CombinedInfo.Mappers.push_back(nullptr); 8246 // Size is (addr of {highest+1} element) - (addr of lowest element) 8247 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 8248 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 8249 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 8250 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 8251 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 8252 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 8253 /*isSigned=*/false); 8254 CombinedInfo.Sizes.push_back(Size); 8255 // Map type is always TARGET_PARAM, if generate info for captures. 8256 CombinedInfo.Types.push_back(NotTargetParams ? OMP_MAP_NONE 8257 : OMP_MAP_TARGET_PARAM); 8258 // If any element has the present modifier, then make sure the runtime 8259 // doesn't attempt to allocate the struct. 8260 if (CurTypes.end() != 8261 llvm::find_if(CurTypes, [](OpenMPOffloadMappingFlags Type) { 8262 return Type & OMP_MAP_PRESENT; 8263 })) 8264 CombinedInfo.Types.back() |= OMP_MAP_PRESENT; 8265 // Remove TARGET_PARAM flag from the first element if any. 8266 if (!CurTypes.empty()) 8267 CurTypes.front() &= ~OMP_MAP_TARGET_PARAM; 8268 8269 // All other current entries will be MEMBER_OF the combined entry 8270 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8271 // 0xFFFF in the MEMBER_OF field). 8272 OpenMPOffloadMappingFlags MemberOfFlag = 8273 getMemberOfFlag(CombinedInfo.BasePointers.size() - 1); 8274 for (auto &M : CurTypes) 8275 setCorrectMemberOfFlag(M, MemberOfFlag); 8276 } 8277 8278 /// Generate all the base pointers, section pointers, sizes, map types, and 8279 /// mappers for the extracted mappable expressions (all included in \a 8280 /// CombinedInfo). Also, for each item that relates with a device pointer, a 8281 /// pair of the relevant declaration and index where it occurs is appended to 8282 /// the device pointers info array. 8283 void generateAllInfo( 8284 MapCombinedInfoTy &CombinedInfo, bool NotTargetParams = false, 8285 const llvm::DenseSet<CanonicalDeclPtr<const Decl>> &SkipVarSet = 8286 llvm::DenseSet<CanonicalDeclPtr<const Decl>>()) const { 8287 // We have to process the component lists that relate with the same 8288 // declaration in a single chunk so that we can generate the map flags 8289 // correctly. Therefore, we organize all lists in a map. 8290 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8291 8292 // Helper function to fill the information map for the different supported 8293 // clauses. 8294 auto &&InfoGen = 8295 [&Info, &SkipVarSet]( 8296 const ValueDecl *D, 8297 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8298 OpenMPMapClauseKind MapType, 8299 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8300 ArrayRef<OpenMPMotionModifierKind> MotionModifiers, 8301 bool ReturnDevicePointer, bool IsImplicit, const ValueDecl *Mapper, 8302 const Expr *VarRef = nullptr, bool ForDeviceAddr = false) { 8303 const ValueDecl *VD = 8304 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8305 if (SkipVarSet.count(VD)) 8306 return; 8307 Info[VD].emplace_back(L, MapType, MapModifiers, MotionModifiers, 8308 ReturnDevicePointer, IsImplicit, Mapper, VarRef, 8309 ForDeviceAddr); 8310 }; 8311 8312 assert(CurDir.is<const OMPExecutableDirective *>() && 8313 "Expect a executable directive"); 8314 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8315 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8316 const auto *EI = C->getVarRefs().begin(); 8317 for (const auto L : C->component_lists()) { 8318 // The Expression is not correct if the mapping is implicit 8319 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 8320 InfoGen(std::get<0>(L), std::get<1>(L), C->getMapType(), 8321 C->getMapTypeModifiers(), llvm::None, 8322 /*ReturnDevicePointer=*/false, C->isImplicit(), std::get<2>(L), 8323 E); 8324 ++EI; 8325 } 8326 } 8327 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) { 8328 const auto *EI = C->getVarRefs().begin(); 8329 for (const auto L : C->component_lists()) { 8330 InfoGen(std::get<0>(L), std::get<1>(L), OMPC_MAP_to, llvm::None, 8331 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8332 C->isImplicit(), std::get<2>(L), *EI); 8333 ++EI; 8334 } 8335 } 8336 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) { 8337 const auto *EI = C->getVarRefs().begin(); 8338 for (const auto L : C->component_lists()) { 8339 InfoGen(std::get<0>(L), std::get<1>(L), OMPC_MAP_from, llvm::None, 8340 C->getMotionModifiers(), /*ReturnDevicePointer=*/false, 8341 C->isImplicit(), std::get<2>(L), *EI); 8342 ++EI; 8343 } 8344 } 8345 8346 // Look at the use_device_ptr clause information and mark the existing map 8347 // entries as such. If there is no map information for an entry in the 8348 // use_device_ptr list, we create one with map type 'alloc' and zero size 8349 // section. It is the user fault if that was not mapped before. If there is 8350 // no map information and the pointer is a struct member, then we defer the 8351 // emission of that entry until the whole struct has been processed. 8352 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 8353 DeferredInfo; 8354 MapCombinedInfoTy UseDevicePtrCombinedInfo; 8355 8356 for (const auto *C : 8357 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 8358 for (const auto L : C->component_lists()) { 8359 OMPClauseMappableExprCommon::MappableExprComponentListRef Components = 8360 std::get<1>(L); 8361 assert(!Components.empty() && 8362 "Not expecting empty list of components!"); 8363 const ValueDecl *VD = Components.back().getAssociatedDeclaration(); 8364 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8365 const Expr *IE = Components.back().getAssociatedExpression(); 8366 // If the first component is a member expression, we have to look into 8367 // 'this', which maps to null in the map of map information. Otherwise 8368 // look directly for the information. 8369 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8370 8371 // We potentially have map information for this declaration already. 8372 // Look for the first set of components that refer to it. 8373 if (It != Info.end()) { 8374 auto *CI = llvm::find_if(It->second, [VD](const MapInfo &MI) { 8375 return MI.Components.back().getAssociatedDeclaration() == VD; 8376 }); 8377 // If we found a map entry, signal that the pointer has to be returned 8378 // and move on to the next declaration. 8379 // Exclude cases where the base pointer is mapped as array subscript, 8380 // array section or array shaping. The base address is passed as a 8381 // pointer to base in this case and cannot be used as a base for 8382 // use_device_ptr list item. 8383 if (CI != It->second.end()) { 8384 auto PrevCI = std::next(CI->Components.rbegin()); 8385 const auto *VarD = dyn_cast<VarDecl>(VD); 8386 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8387 isa<MemberExpr>(IE) || 8388 !VD->getType().getNonReferenceType()->isPointerType() || 8389 PrevCI == CI->Components.rend() || 8390 isa<MemberExpr>(PrevCI->getAssociatedExpression()) || !VarD || 8391 VarD->hasLocalStorage()) { 8392 CI->ReturnDevicePointer = true; 8393 continue; 8394 } 8395 } 8396 } 8397 8398 // We didn't find any match in our map information - generate a zero 8399 // size array section - if the pointer is a struct member we defer this 8400 // action until the whole struct has been processed. 8401 if (isa<MemberExpr>(IE)) { 8402 // Insert the pointer into Info to be processed by 8403 // generateInfoForComponentList. Because it is a member pointer 8404 // without a pointee, no entry will be generated for it, therefore 8405 // we need to generate one after the whole struct has been processed. 8406 // Nonetheless, generateInfoForComponentList must be called to take 8407 // the pointer into account for the calculation of the range of the 8408 // partial struct. 8409 InfoGen(nullptr, Components, OMPC_MAP_unknown, llvm::None, llvm::None, 8410 /*ReturnDevicePointer=*/false, C->isImplicit(), nullptr); 8411 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/false); 8412 } else { 8413 llvm::Value *Ptr = 8414 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8415 UseDevicePtrCombinedInfo.Exprs.push_back(VD); 8416 UseDevicePtrCombinedInfo.BasePointers.emplace_back(Ptr, VD); 8417 UseDevicePtrCombinedInfo.Pointers.push_back(Ptr); 8418 UseDevicePtrCombinedInfo.Sizes.push_back( 8419 llvm::Constant::getNullValue(CGF.Int64Ty)); 8420 UseDevicePtrCombinedInfo.Types.push_back( 8421 OMP_MAP_RETURN_PARAM | 8422 (NotTargetParams ? OMP_MAP_NONE : OMP_MAP_TARGET_PARAM)); 8423 UseDevicePtrCombinedInfo.Mappers.push_back(nullptr); 8424 } 8425 } 8426 } 8427 8428 // Look at the use_device_addr clause information and mark the existing map 8429 // entries as such. If there is no map information for an entry in the 8430 // use_device_addr list, we create one with map type 'alloc' and zero size 8431 // section. It is the user fault if that was not mapped before. If there is 8432 // no map information and the pointer is a struct member, then we defer the 8433 // emission of that entry until the whole struct has been processed. 8434 llvm::SmallDenseSet<CanonicalDeclPtr<const Decl>, 4> Processed; 8435 for (const auto *C : 8436 CurExecDir->getClausesOfKind<OMPUseDeviceAddrClause>()) { 8437 for (const auto L : C->component_lists()) { 8438 assert(!std::get<1>(L).empty() && 8439 "Not expecting empty list of components!"); 8440 const ValueDecl *VD = std::get<1>(L).back().getAssociatedDeclaration(); 8441 if (!Processed.insert(VD).second) 8442 continue; 8443 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8444 const Expr *IE = std::get<1>(L).back().getAssociatedExpression(); 8445 // If the first component is a member expression, we have to look into 8446 // 'this', which maps to null in the map of map information. Otherwise 8447 // look directly for the information. 8448 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8449 8450 // We potentially have map information for this declaration already. 8451 // Look for the first set of components that refer to it. 8452 if (It != Info.end()) { 8453 auto *CI = llvm::find_if(It->second, [VD](const MapInfo &MI) { 8454 return MI.Components.back().getAssociatedDeclaration() == VD; 8455 }); 8456 // If we found a map entry, signal that the pointer has to be returned 8457 // and move on to the next declaration. 8458 if (CI != It->second.end()) { 8459 CI->ReturnDevicePointer = true; 8460 continue; 8461 } 8462 } 8463 8464 // We didn't find any match in our map information - generate a zero 8465 // size array section - if the pointer is a struct member we defer this 8466 // action until the whole struct has been processed. 8467 if (isa<MemberExpr>(IE)) { 8468 // Insert the pointer into Info to be processed by 8469 // generateInfoForComponentList. Because it is a member pointer 8470 // without a pointee, no entry will be generated for it, therefore 8471 // we need to generate one after the whole struct has been processed. 8472 // Nonetheless, generateInfoForComponentList must be called to take 8473 // the pointer into account for the calculation of the range of the 8474 // partial struct. 8475 InfoGen(nullptr, std::get<1>(L), OMPC_MAP_unknown, llvm::None, 8476 llvm::None, /*ReturnDevicePointer=*/false, C->isImplicit(), 8477 nullptr, nullptr, /*ForDeviceAddr=*/true); 8478 DeferredInfo[nullptr].emplace_back(IE, VD, /*ForDeviceAddr=*/true); 8479 } else { 8480 llvm::Value *Ptr; 8481 if (IE->isGLValue()) 8482 Ptr = CGF.EmitLValue(IE).getPointer(CGF); 8483 else 8484 Ptr = CGF.EmitScalarExpr(IE); 8485 CombinedInfo.Exprs.push_back(VD); 8486 CombinedInfo.BasePointers.emplace_back(Ptr, VD); 8487 CombinedInfo.Pointers.push_back(Ptr); 8488 CombinedInfo.Sizes.push_back( 8489 llvm::Constant::getNullValue(CGF.Int64Ty)); 8490 CombinedInfo.Types.push_back( 8491 OMP_MAP_RETURN_PARAM | 8492 (NotTargetParams ? OMP_MAP_NONE : OMP_MAP_TARGET_PARAM)); 8493 CombinedInfo.Mappers.push_back(nullptr); 8494 } 8495 } 8496 } 8497 8498 for (const auto &M : Info) { 8499 // We need to know when we generate information for the first component 8500 // associated with a capture, because the mapping flags depend on it. 8501 bool IsFirstComponentList = !NotTargetParams; 8502 8503 // Underlying variable declaration used in the map clause. 8504 const ValueDecl *VD = std::get<0>(M); 8505 8506 // Temporary generated information. 8507 MapCombinedInfoTy CurInfo; 8508 StructRangeInfoTy PartialStruct; 8509 8510 for (const MapInfo &L : M.second) { 8511 assert(!L.Components.empty() && 8512 "Not expecting declaration with no component lists."); 8513 8514 // Remember the current base pointer index. 8515 unsigned CurrentBasePointersIdx = CurInfo.BasePointers.size(); 8516 CurInfo.NonContigInfo.IsNonContiguous = 8517 L.Components.back().isNonContiguous(); 8518 generateInfoForComponentList( 8519 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components, CurInfo, 8520 PartialStruct, IsFirstComponentList, L.IsImplicit, L.Mapper, 8521 L.ForDeviceAddr, VD, L.VarRef); 8522 8523 // If this entry relates with a device pointer, set the relevant 8524 // declaration and add the 'return pointer' flag. 8525 if (L.ReturnDevicePointer) { 8526 assert(CurInfo.BasePointers.size() > CurrentBasePointersIdx && 8527 "Unexpected number of mapped base pointers."); 8528 8529 const ValueDecl *RelevantVD = 8530 L.Components.back().getAssociatedDeclaration(); 8531 assert(RelevantVD && 8532 "No relevant declaration related with device pointer??"); 8533 8534 CurInfo.BasePointers[CurrentBasePointersIdx].setDevicePtrDecl( 8535 RelevantVD); 8536 CurInfo.Types[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8537 } 8538 IsFirstComponentList = false; 8539 } 8540 8541 // Append any pending zero-length pointers which are struct members and 8542 // used with use_device_ptr or use_device_addr. 8543 auto CI = DeferredInfo.find(M.first); 8544 if (CI != DeferredInfo.end()) { 8545 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8546 llvm::Value *BasePtr; 8547 llvm::Value *Ptr; 8548 if (L.ForDeviceAddr) { 8549 if (L.IE->isGLValue()) 8550 Ptr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8551 else 8552 Ptr = this->CGF.EmitScalarExpr(L.IE); 8553 BasePtr = Ptr; 8554 // Entry is RETURN_PARAM. Also, set the placeholder value 8555 // MEMBER_OF=FFFF so that the entry is later updated with the 8556 // correct value of MEMBER_OF. 8557 CurInfo.Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_MEMBER_OF); 8558 } else { 8559 BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8560 Ptr = this->CGF.EmitLoadOfScalar(this->CGF.EmitLValue(L.IE), 8561 L.IE->getExprLoc()); 8562 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8563 // value MEMBER_OF=FFFF so that the entry is later updated with the 8564 // correct value of MEMBER_OF. 8565 CurInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8566 OMP_MAP_MEMBER_OF); 8567 } 8568 CurInfo.Exprs.push_back(L.VD); 8569 CurInfo.BasePointers.emplace_back(BasePtr, L.VD); 8570 CurInfo.Pointers.push_back(Ptr); 8571 CurInfo.Sizes.push_back( 8572 llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8573 CurInfo.Mappers.push_back(nullptr); 8574 } 8575 } 8576 8577 // If there is an entry in PartialStruct it means we have a struct with 8578 // individual members mapped. Emit an extra combined entry. 8579 if (PartialStruct.Base.isValid()) 8580 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD, 8581 NotTargetParams); 8582 8583 // We need to append the results of this capture to what we already have. 8584 CombinedInfo.append(CurInfo); 8585 } 8586 // Append data for use_device_ptr clauses. 8587 CombinedInfo.append(UseDevicePtrCombinedInfo); 8588 } 8589 8590 /// Generate all the base pointers, section pointers, sizes, map types, and 8591 /// mappers for the extracted map clauses of user-defined mapper (all included 8592 /// in \a CombinedInfo). 8593 void generateAllInfoForMapper(MapCombinedInfoTy &CombinedInfo) const { 8594 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8595 "Expect a declare mapper directive"); 8596 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8597 // We have to process the component lists that relate with the same 8598 // declaration in a single chunk so that we can generate the map flags 8599 // correctly. Therefore, we organize all lists in a map. 8600 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8601 8602 // Fill the information map for map clauses. 8603 for (const auto *C : CurMapperDir->clauselists()) { 8604 const auto *MC = cast<OMPMapClause>(C); 8605 const auto *EI = MC->getVarRefs().begin(); 8606 for (const auto L : MC->component_lists()) { 8607 // The Expression is not correct if the mapping is implicit 8608 const Expr *E = (MC->getMapLoc().isValid()) ? *EI : nullptr; 8609 const ValueDecl *VD = 8610 std::get<0>(L) ? cast<ValueDecl>(std::get<0>(L)->getCanonicalDecl()) 8611 : nullptr; 8612 // Get the corresponding user-defined mapper. 8613 Info[VD].emplace_back(std::get<1>(L), MC->getMapType(), 8614 MC->getMapTypeModifiers(), llvm::None, 8615 /*ReturnDevicePointer=*/false, MC->isImplicit(), 8616 std::get<2>(L), E); 8617 ++EI; 8618 } 8619 } 8620 8621 for (const auto &M : Info) { 8622 // We need to know when we generate information for the first component 8623 // associated with a capture, because the mapping flags depend on it. 8624 bool IsFirstComponentList = true; 8625 8626 // Underlying variable declaration used in the map clause. 8627 const ValueDecl *VD = std::get<0>(M); 8628 8629 // Temporary generated information. 8630 MapCombinedInfoTy CurInfo; 8631 StructRangeInfoTy PartialStruct; 8632 8633 for (const MapInfo &L : M.second) { 8634 assert(!L.Components.empty() && 8635 "Not expecting declaration with no component lists."); 8636 generateInfoForComponentList( 8637 L.MapType, L.MapModifiers, L.MotionModifiers, L.Components, CurInfo, 8638 PartialStruct, IsFirstComponentList, L.IsImplicit, L.Mapper, 8639 L.ForDeviceAddr, VD, L.VarRef); 8640 IsFirstComponentList = false; 8641 } 8642 8643 // If there is an entry in PartialStruct it means we have a struct with 8644 // individual members mapped. Emit an extra combined entry. 8645 if (PartialStruct.Base.isValid()) { 8646 CurInfo.NonContigInfo.Dims.push_back(0); 8647 emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct, VD); 8648 } 8649 8650 // We need to append the results of this capture to what we already have. 8651 CombinedInfo.append(CurInfo); 8652 } 8653 } 8654 8655 /// Emit capture info for lambdas for variables captured by reference. 8656 void generateInfoForLambdaCaptures( 8657 const ValueDecl *VD, llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 8658 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8659 const auto *RD = VD->getType() 8660 .getCanonicalType() 8661 .getNonReferenceType() 8662 ->getAsCXXRecordDecl(); 8663 if (!RD || !RD->isLambda()) 8664 return; 8665 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8666 LValue VDLVal = CGF.MakeAddrLValue( 8667 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8668 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8669 FieldDecl *ThisCapture = nullptr; 8670 RD->getCaptureFields(Captures, ThisCapture); 8671 if (ThisCapture) { 8672 LValue ThisLVal = 8673 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8674 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8675 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8676 VDLVal.getPointer(CGF)); 8677 CombinedInfo.Exprs.push_back(VD); 8678 CombinedInfo.BasePointers.push_back(ThisLVal.getPointer(CGF)); 8679 CombinedInfo.Pointers.push_back(ThisLValVal.getPointer(CGF)); 8680 CombinedInfo.Sizes.push_back( 8681 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8682 CGF.Int64Ty, /*isSigned=*/true)); 8683 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8684 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8685 CombinedInfo.Mappers.push_back(nullptr); 8686 } 8687 for (const LambdaCapture &LC : RD->captures()) { 8688 if (!LC.capturesVariable()) 8689 continue; 8690 const VarDecl *VD = LC.getCapturedVar(); 8691 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8692 continue; 8693 auto It = Captures.find(VD); 8694 assert(It != Captures.end() && "Found lambda capture without field."); 8695 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8696 if (LC.getCaptureKind() == LCK_ByRef) { 8697 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8698 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8699 VDLVal.getPointer(CGF)); 8700 CombinedInfo.Exprs.push_back(VD); 8701 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 8702 CombinedInfo.Pointers.push_back(VarLValVal.getPointer(CGF)); 8703 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8704 CGF.getTypeSize( 8705 VD->getType().getCanonicalType().getNonReferenceType()), 8706 CGF.Int64Ty, /*isSigned=*/true)); 8707 } else { 8708 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8709 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8710 VDLVal.getPointer(CGF)); 8711 CombinedInfo.Exprs.push_back(VD); 8712 CombinedInfo.BasePointers.push_back(VarLVal.getPointer(CGF)); 8713 CombinedInfo.Pointers.push_back(VarRVal.getScalarVal()); 8714 CombinedInfo.Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8715 } 8716 CombinedInfo.Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8717 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8718 CombinedInfo.Mappers.push_back(nullptr); 8719 } 8720 } 8721 8722 /// Set correct indices for lambdas captures. 8723 void adjustMemberOfForLambdaCaptures( 8724 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8725 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8726 MapFlagsArrayTy &Types) const { 8727 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8728 // Set correct member_of idx for all implicit lambda captures. 8729 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8730 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8731 continue; 8732 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8733 assert(BasePtr && "Unable to find base lambda address."); 8734 int TgtIdx = -1; 8735 for (unsigned J = I; J > 0; --J) { 8736 unsigned Idx = J - 1; 8737 if (Pointers[Idx] != BasePtr) 8738 continue; 8739 TgtIdx = Idx; 8740 break; 8741 } 8742 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8743 // All other current entries will be MEMBER_OF the combined entry 8744 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8745 // 0xFFFF in the MEMBER_OF field). 8746 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8747 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8748 } 8749 } 8750 8751 /// Generate the base pointers, section pointers, sizes, map types, and 8752 /// mappers associated to a given capture (all included in \a CombinedInfo). 8753 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8754 llvm::Value *Arg, MapCombinedInfoTy &CombinedInfo, 8755 StructRangeInfoTy &PartialStruct) const { 8756 assert(!Cap->capturesVariableArrayType() && 8757 "Not expecting to generate map info for a variable array type!"); 8758 8759 // We need to know when we generating information for the first component 8760 const ValueDecl *VD = Cap->capturesThis() 8761 ? nullptr 8762 : Cap->getCapturedVar()->getCanonicalDecl(); 8763 8764 // If this declaration appears in a is_device_ptr clause we just have to 8765 // pass the pointer by value. If it is a reference to a declaration, we just 8766 // pass its value. 8767 if (DevPointersMap.count(VD)) { 8768 CombinedInfo.Exprs.push_back(VD); 8769 CombinedInfo.BasePointers.emplace_back(Arg, VD); 8770 CombinedInfo.Pointers.push_back(Arg); 8771 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8772 CGF.getTypeSize(CGF.getContext().VoidPtrTy), CGF.Int64Ty, 8773 /*isSigned=*/true)); 8774 CombinedInfo.Types.push_back( 8775 (Cap->capturesVariable() ? OMP_MAP_TO : OMP_MAP_LITERAL) | 8776 OMP_MAP_TARGET_PARAM); 8777 CombinedInfo.Mappers.push_back(nullptr); 8778 return; 8779 } 8780 8781 using MapData = 8782 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8783 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool, 8784 const ValueDecl *, const Expr *>; 8785 SmallVector<MapData, 4> DeclComponentLists; 8786 assert(CurDir.is<const OMPExecutableDirective *>() && 8787 "Expect a executable directive"); 8788 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8789 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8790 const auto *EI = C->getVarRefs().begin(); 8791 for (const auto L : C->decl_component_lists(VD)) { 8792 const ValueDecl *VDecl, *Mapper; 8793 // The Expression is not correct if the mapping is implicit 8794 const Expr *E = (C->getMapLoc().isValid()) ? *EI : nullptr; 8795 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8796 std::tie(VDecl, Components, Mapper) = L; 8797 assert(VDecl == VD && "We got information for the wrong declaration??"); 8798 assert(!Components.empty() && 8799 "Not expecting declaration with no component lists."); 8800 DeclComponentLists.emplace_back(Components, C->getMapType(), 8801 C->getMapTypeModifiers(), 8802 C->isImplicit(), Mapper, E); 8803 ++EI; 8804 } 8805 } 8806 8807 // Find overlapping elements (including the offset from the base element). 8808 llvm::SmallDenseMap< 8809 const MapData *, 8810 llvm::SmallVector< 8811 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8812 4> 8813 OverlappedData; 8814 size_t Count = 0; 8815 for (const MapData &L : DeclComponentLists) { 8816 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8817 OpenMPMapClauseKind MapType; 8818 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8819 bool IsImplicit; 8820 const ValueDecl *Mapper; 8821 const Expr *VarRef; 8822 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 8823 L; 8824 ++Count; 8825 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8826 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8827 std::tie(Components1, MapType, MapModifiers, IsImplicit, Mapper, 8828 VarRef) = L1; 8829 auto CI = Components.rbegin(); 8830 auto CE = Components.rend(); 8831 auto SI = Components1.rbegin(); 8832 auto SE = Components1.rend(); 8833 for (; CI != CE && SI != SE; ++CI, ++SI) { 8834 if (CI->getAssociatedExpression()->getStmtClass() != 8835 SI->getAssociatedExpression()->getStmtClass()) 8836 break; 8837 // Are we dealing with different variables/fields? 8838 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8839 break; 8840 } 8841 // Found overlapping if, at least for one component, reached the head of 8842 // the components list. 8843 if (CI == CE || SI == SE) { 8844 assert((CI != CE || SI != SE) && 8845 "Unexpected full match of the mapping components."); 8846 const MapData &BaseData = CI == CE ? L : L1; 8847 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8848 SI == SE ? Components : Components1; 8849 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8850 OverlappedElements.getSecond().push_back(SubData); 8851 } 8852 } 8853 } 8854 // Sort the overlapped elements for each item. 8855 llvm::SmallVector<const FieldDecl *, 4> Layout; 8856 if (!OverlappedData.empty()) { 8857 if (const auto *CRD = 8858 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8859 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8860 else { 8861 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8862 Layout.append(RD->field_begin(), RD->field_end()); 8863 } 8864 } 8865 for (auto &Pair : OverlappedData) { 8866 llvm::sort( 8867 Pair.getSecond(), 8868 [&Layout]( 8869 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8870 OMPClauseMappableExprCommon::MappableExprComponentListRef 8871 Second) { 8872 auto CI = First.rbegin(); 8873 auto CE = First.rend(); 8874 auto SI = Second.rbegin(); 8875 auto SE = Second.rend(); 8876 for (; CI != CE && SI != SE; ++CI, ++SI) { 8877 if (CI->getAssociatedExpression()->getStmtClass() != 8878 SI->getAssociatedExpression()->getStmtClass()) 8879 break; 8880 // Are we dealing with different variables/fields? 8881 if (CI->getAssociatedDeclaration() != 8882 SI->getAssociatedDeclaration()) 8883 break; 8884 } 8885 8886 // Lists contain the same elements. 8887 if (CI == CE && SI == SE) 8888 return false; 8889 8890 // List with less elements is less than list with more elements. 8891 if (CI == CE || SI == SE) 8892 return CI == CE; 8893 8894 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8895 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8896 if (FD1->getParent() == FD2->getParent()) 8897 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8898 const auto It = 8899 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8900 return FD == FD1 || FD == FD2; 8901 }); 8902 return *It == FD1; 8903 }); 8904 } 8905 8906 // Associated with a capture, because the mapping flags depend on it. 8907 // Go through all of the elements with the overlapped elements. 8908 for (const auto &Pair : OverlappedData) { 8909 const MapData &L = *Pair.getFirst(); 8910 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8911 OpenMPMapClauseKind MapType; 8912 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8913 bool IsImplicit; 8914 const ValueDecl *Mapper; 8915 const Expr *VarRef; 8916 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 8917 L; 8918 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8919 OverlappedComponents = Pair.getSecond(); 8920 bool IsFirstComponentList = true; 8921 generateInfoForComponentList( 8922 MapType, MapModifiers, llvm::None, Components, CombinedInfo, 8923 PartialStruct, IsFirstComponentList, IsImplicit, Mapper, 8924 /*ForDeviceAddr=*/false, VD, VarRef, OverlappedComponents); 8925 } 8926 // Go through other elements without overlapped elements. 8927 bool IsFirstComponentList = OverlappedData.empty(); 8928 for (const MapData &L : DeclComponentLists) { 8929 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8930 OpenMPMapClauseKind MapType; 8931 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8932 bool IsImplicit; 8933 const ValueDecl *Mapper; 8934 const Expr *VarRef; 8935 std::tie(Components, MapType, MapModifiers, IsImplicit, Mapper, VarRef) = 8936 L; 8937 auto It = OverlappedData.find(&L); 8938 if (It == OverlappedData.end()) 8939 generateInfoForComponentList(MapType, MapModifiers, llvm::None, 8940 Components, CombinedInfo, PartialStruct, 8941 IsFirstComponentList, IsImplicit, Mapper, 8942 /*ForDeviceAddr=*/false, VD, VarRef); 8943 IsFirstComponentList = false; 8944 } 8945 } 8946 8947 /// Generate the default map information for a given capture \a CI, 8948 /// record field declaration \a RI and captured value \a CV. 8949 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8950 const FieldDecl &RI, llvm::Value *CV, 8951 MapCombinedInfoTy &CombinedInfo) const { 8952 bool IsImplicit = true; 8953 // Do the default mapping. 8954 if (CI.capturesThis()) { 8955 CombinedInfo.Exprs.push_back(nullptr); 8956 CombinedInfo.BasePointers.push_back(CV); 8957 CombinedInfo.Pointers.push_back(CV); 8958 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8959 CombinedInfo.Sizes.push_back( 8960 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8961 CGF.Int64Ty, /*isSigned=*/true)); 8962 // Default map type. 8963 CombinedInfo.Types.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8964 } else if (CI.capturesVariableByCopy()) { 8965 const VarDecl *VD = CI.getCapturedVar(); 8966 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 8967 CombinedInfo.BasePointers.push_back(CV); 8968 CombinedInfo.Pointers.push_back(CV); 8969 if (!RI.getType()->isAnyPointerType()) { 8970 // We have to signal to the runtime captures passed by value that are 8971 // not pointers. 8972 CombinedInfo.Types.push_back(OMP_MAP_LITERAL); 8973 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8974 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8975 } else { 8976 // Pointers are implicitly mapped with a zero size and no flags 8977 // (other than first map that is added for all implicit maps). 8978 CombinedInfo.Types.push_back(OMP_MAP_NONE); 8979 CombinedInfo.Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8980 } 8981 auto I = FirstPrivateDecls.find(VD); 8982 if (I != FirstPrivateDecls.end()) 8983 IsImplicit = I->getSecond(); 8984 } else { 8985 assert(CI.capturesVariable() && "Expected captured reference."); 8986 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8987 QualType ElementType = PtrTy->getPointeeType(); 8988 CombinedInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 8989 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8990 // The default map type for a scalar/complex type is 'to' because by 8991 // default the value doesn't have to be retrieved. For an aggregate 8992 // type, the default is 'tofrom'. 8993 CombinedInfo.Types.push_back(getMapModifiersForPrivateClauses(CI)); 8994 const VarDecl *VD = CI.getCapturedVar(); 8995 auto I = FirstPrivateDecls.find(VD); 8996 if (I != FirstPrivateDecls.end() && 8997 VD->getType().isConstant(CGF.getContext())) { 8998 llvm::Constant *Addr = 8999 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 9000 // Copy the value of the original variable to the new global copy. 9001 CGF.Builder.CreateMemCpy( 9002 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 9003 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 9004 CombinedInfo.Sizes.back(), /*IsVolatile=*/false); 9005 // Use new global variable as the base pointers. 9006 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9007 CombinedInfo.BasePointers.push_back(Addr); 9008 CombinedInfo.Pointers.push_back(Addr); 9009 } else { 9010 CombinedInfo.Exprs.push_back(VD->getCanonicalDecl()); 9011 CombinedInfo.BasePointers.push_back(CV); 9012 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 9013 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 9014 CV, ElementType, CGF.getContext().getDeclAlign(VD), 9015 AlignmentSource::Decl)); 9016 CombinedInfo.Pointers.push_back(PtrAddr.getPointer()); 9017 } else { 9018 CombinedInfo.Pointers.push_back(CV); 9019 } 9020 } 9021 if (I != FirstPrivateDecls.end()) 9022 IsImplicit = I->getSecond(); 9023 } 9024 // Every default map produces a single argument which is a target parameter. 9025 CombinedInfo.Types.back() |= OMP_MAP_TARGET_PARAM; 9026 9027 // Add flag stating this is an implicit map. 9028 if (IsImplicit) 9029 CombinedInfo.Types.back() |= OMP_MAP_IMPLICIT; 9030 9031 // No user-defined mapper for default mapping. 9032 CombinedInfo.Mappers.push_back(nullptr); 9033 } 9034 }; 9035 } // anonymous namespace 9036 9037 static void emitNonContiguousDescriptor( 9038 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9039 CGOpenMPRuntime::TargetDataInfo &Info) { 9040 CodeGenModule &CGM = CGF.CGM; 9041 MappableExprsHandler::MapCombinedInfoTy::StructNonContiguousInfo 9042 &NonContigInfo = CombinedInfo.NonContigInfo; 9043 9044 // Build an array of struct descriptor_dim and then assign it to 9045 // offload_args. 9046 // 9047 // struct descriptor_dim { 9048 // uint64_t offset; 9049 // uint64_t count; 9050 // uint64_t stride 9051 // }; 9052 ASTContext &C = CGF.getContext(); 9053 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 9054 RecordDecl *RD; 9055 RD = C.buildImplicitRecord("descriptor_dim"); 9056 RD->startDefinition(); 9057 addFieldToRecordDecl(C, RD, Int64Ty); 9058 addFieldToRecordDecl(C, RD, Int64Ty); 9059 addFieldToRecordDecl(C, RD, Int64Ty); 9060 RD->completeDefinition(); 9061 QualType DimTy = C.getRecordType(RD); 9062 9063 enum { OffsetFD = 0, CountFD, StrideFD }; 9064 // We need two index variable here since the size of "Dims" is the same as the 9065 // size of Components, however, the size of offset, count, and stride is equal 9066 // to the size of base declaration that is non-contiguous. 9067 for (unsigned I = 0, L = 0, E = NonContigInfo.Dims.size(); I < E; ++I) { 9068 // Skip emitting ir if dimension size is 1 since it cannot be 9069 // non-contiguous. 9070 if (NonContigInfo.Dims[I] == 1) 9071 continue; 9072 llvm::APInt Size(/*numBits=*/32, NonContigInfo.Dims[I]); 9073 QualType ArrayTy = 9074 C.getConstantArrayType(DimTy, Size, nullptr, ArrayType::Normal, 0); 9075 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 9076 for (unsigned II = 0, EE = NonContigInfo.Dims[I]; II < EE; ++II) { 9077 unsigned RevIdx = EE - II - 1; 9078 LValue DimsLVal = CGF.MakeAddrLValue( 9079 CGF.Builder.CreateConstArrayGEP(DimsAddr, II), DimTy); 9080 // Offset 9081 LValue OffsetLVal = CGF.EmitLValueForField( 9082 DimsLVal, *std::next(RD->field_begin(), OffsetFD)); 9083 CGF.EmitStoreOfScalar(NonContigInfo.Offsets[L][RevIdx], OffsetLVal); 9084 // Count 9085 LValue CountLVal = CGF.EmitLValueForField( 9086 DimsLVal, *std::next(RD->field_begin(), CountFD)); 9087 CGF.EmitStoreOfScalar(NonContigInfo.Counts[L][RevIdx], CountLVal); 9088 // Stride 9089 LValue StrideLVal = CGF.EmitLValueForField( 9090 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 9091 CGF.EmitStoreOfScalar(NonContigInfo.Strides[L][RevIdx], StrideLVal); 9092 } 9093 // args[I] = &dims 9094 Address DAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9095 DimsAddr, CGM.Int8PtrTy); 9096 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9097 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9098 Info.PointersArray, 0, I); 9099 Address PAddr(P, CGF.getPointerAlign()); 9100 CGF.Builder.CreateStore(DAddr.getPointer(), PAddr); 9101 ++L; 9102 } 9103 } 9104 9105 /// Emit a string constant containing the names of the values mapped to the 9106 /// offloading runtime library. 9107 llvm::Constant * 9108 emitMappingInformation(CodeGenFunction &CGF, llvm::OpenMPIRBuilder &OMPBuilder, 9109 MappableExprsHandler::MappingExprInfo &MapExprs) { 9110 llvm::Constant *SrcLocStr; 9111 if (!MapExprs.getMapDecl()) { 9112 SrcLocStr = OMPBuilder.getOrCreateDefaultSrcLocStr(); 9113 } else { 9114 std::string ExprName = ""; 9115 if (MapExprs.getMapExpr()) { 9116 PrintingPolicy P(CGF.getContext().getLangOpts()); 9117 llvm::raw_string_ostream OS(ExprName); 9118 MapExprs.getMapExpr()->printPretty(OS, nullptr, P); 9119 OS.flush(); 9120 } else { 9121 ExprName = MapExprs.getMapDecl()->getNameAsString(); 9122 } 9123 9124 SourceLocation Loc = MapExprs.getMapDecl()->getLocation(); 9125 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 9126 const char *FileName = PLoc.getFilename(); 9127 unsigned Line = PLoc.getLine(); 9128 unsigned Column = PLoc.getColumn(); 9129 SrcLocStr = OMPBuilder.getOrCreateSrcLocStr(FileName, ExprName.c_str(), 9130 Line, Column); 9131 } 9132 9133 return SrcLocStr; 9134 } 9135 9136 /// Emit the arrays used to pass the captures and map information to the 9137 /// offloading runtime library. If there is no map or capture information, 9138 /// return nullptr by reference. 9139 static void emitOffloadingArrays( 9140 CodeGenFunction &CGF, MappableExprsHandler::MapCombinedInfoTy &CombinedInfo, 9141 CGOpenMPRuntime::TargetDataInfo &Info, llvm::OpenMPIRBuilder &OMPBuilder, 9142 bool IsNonContiguous = false) { 9143 CodeGenModule &CGM = CGF.CGM; 9144 ASTContext &Ctx = CGF.getContext(); 9145 9146 // Reset the array information. 9147 Info.clearArrayInfo(); 9148 Info.NumberOfPtrs = CombinedInfo.BasePointers.size(); 9149 9150 if (Info.NumberOfPtrs) { 9151 // Detect if we have any capture size requiring runtime evaluation of the 9152 // size so that a constant array could be eventually used. 9153 bool hasRuntimeEvaluationCaptureSize = false; 9154 for (llvm::Value *S : CombinedInfo.Sizes) 9155 if (!isa<llvm::Constant>(S)) { 9156 hasRuntimeEvaluationCaptureSize = true; 9157 break; 9158 } 9159 9160 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 9161 QualType PointerArrayType = Ctx.getConstantArrayType( 9162 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 9163 /*IndexTypeQuals=*/0); 9164 9165 Info.BasePointersArray = 9166 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 9167 Info.PointersArray = 9168 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 9169 Address MappersArray = 9170 CGF.CreateMemTemp(PointerArrayType, ".offload_mappers"); 9171 Info.MappersArray = MappersArray.getPointer(); 9172 9173 // If we don't have any VLA types or other types that require runtime 9174 // evaluation, we can use a constant array for the map sizes, otherwise we 9175 // need to fill up the arrays as we do for the pointers. 9176 QualType Int64Ty = 9177 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 9178 if (hasRuntimeEvaluationCaptureSize) { 9179 QualType SizeArrayType = Ctx.getConstantArrayType( 9180 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 9181 /*IndexTypeQuals=*/0); 9182 Info.SizesArray = 9183 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 9184 } else { 9185 // We expect all the sizes to be constant, so we collect them to create 9186 // a constant array. 9187 SmallVector<llvm::Constant *, 16> ConstSizes; 9188 for (unsigned I = 0, E = CombinedInfo.Sizes.size(); I < E; ++I) { 9189 if (IsNonContiguous && 9190 (CombinedInfo.Types[I] & MappableExprsHandler::OMP_MAP_NON_CONTIG)) { 9191 ConstSizes.push_back(llvm::ConstantInt::get( 9192 CGF.Int64Ty, CombinedInfo.NonContigInfo.Dims[I])); 9193 } else { 9194 ConstSizes.push_back(cast<llvm::Constant>(CombinedInfo.Sizes[I])); 9195 } 9196 } 9197 9198 auto *SizesArrayInit = llvm::ConstantArray::get( 9199 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 9200 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 9201 auto *SizesArrayGbl = new llvm::GlobalVariable( 9202 CGM.getModule(), SizesArrayInit->getType(), 9203 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 9204 SizesArrayInit, Name); 9205 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 9206 Info.SizesArray = SizesArrayGbl; 9207 } 9208 9209 // The map types are always constant so we don't need to generate code to 9210 // fill arrays. Instead, we create an array constant. 9211 SmallVector<uint64_t, 4> Mapping(CombinedInfo.Types.size(), 0); 9212 llvm::copy(CombinedInfo.Types, Mapping.begin()); 9213 llvm::Constant *MapTypesArrayInit = 9214 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 9215 std::string MaptypesName = 9216 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 9217 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 9218 CGM.getModule(), MapTypesArrayInit->getType(), 9219 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 9220 MapTypesArrayInit, MaptypesName); 9221 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 9222 Info.MapTypesArray = MapTypesArrayGbl; 9223 9224 // The information types are only built if there is debug information 9225 // requested. 9226 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) { 9227 Info.MapNamesArray = llvm::Constant::getNullValue( 9228 llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo()); 9229 } else { 9230 auto fillInfoMap = [&](MappableExprsHandler::MappingExprInfo &MapExpr) { 9231 return emitMappingInformation(CGF, OMPBuilder, MapExpr); 9232 }; 9233 SmallVector<llvm::Constant *, 4> InfoMap(CombinedInfo.Exprs.size()); 9234 llvm::transform(CombinedInfo.Exprs, InfoMap.begin(), fillInfoMap); 9235 9236 llvm::Constant *MapNamesArrayInit = llvm::ConstantArray::get( 9237 llvm::ArrayType::get( 9238 llvm::Type::getInt8Ty(CGF.Builder.getContext())->getPointerTo(), 9239 CombinedInfo.Exprs.size()), 9240 InfoMap); 9241 auto *MapNamesArrayGbl = new llvm::GlobalVariable( 9242 CGM.getModule(), MapNamesArrayInit->getType(), 9243 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 9244 MapNamesArrayInit, 9245 CGM.getOpenMPRuntime().getName({"offload_mapnames"})); 9246 Info.MapNamesArray = MapNamesArrayGbl; 9247 } 9248 9249 // If there's a present map type modifier, it must not be applied to the end 9250 // of a region, so generate a separate map type array in that case. 9251 if (Info.separateBeginEndCalls()) { 9252 bool EndMapTypesDiffer = false; 9253 for (uint64_t &Type : Mapping) { 9254 if (Type & MappableExprsHandler::OMP_MAP_PRESENT) { 9255 Type &= ~MappableExprsHandler::OMP_MAP_PRESENT; 9256 EndMapTypesDiffer = true; 9257 } 9258 } 9259 if (EndMapTypesDiffer) { 9260 MapTypesArrayInit = 9261 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 9262 MaptypesName = CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 9263 MapTypesArrayGbl = new llvm::GlobalVariable( 9264 CGM.getModule(), MapTypesArrayInit->getType(), 9265 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 9266 MapTypesArrayInit, MaptypesName); 9267 MapTypesArrayGbl->setUnnamedAddr( 9268 llvm::GlobalValue::UnnamedAddr::Global); 9269 Info.MapTypesArrayEnd = MapTypesArrayGbl; 9270 } 9271 } 9272 9273 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 9274 llvm::Value *BPVal = *CombinedInfo.BasePointers[I]; 9275 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 9276 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9277 Info.BasePointersArray, 0, I); 9278 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9279 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9280 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9281 CGF.Builder.CreateStore(BPVal, BPAddr); 9282 9283 if (Info.requiresDevicePointerInfo()) 9284 if (const ValueDecl *DevVD = 9285 CombinedInfo.BasePointers[I].getDevicePtrDecl()) 9286 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 9287 9288 llvm::Value *PVal = CombinedInfo.Pointers[I]; 9289 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 9290 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9291 Info.PointersArray, 0, I); 9292 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 9293 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 9294 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 9295 CGF.Builder.CreateStore(PVal, PAddr); 9296 9297 if (hasRuntimeEvaluationCaptureSize) { 9298 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 9299 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9300 Info.SizesArray, 9301 /*Idx0=*/0, 9302 /*Idx1=*/I); 9303 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 9304 CGF.Builder.CreateStore(CGF.Builder.CreateIntCast(CombinedInfo.Sizes[I], 9305 CGM.Int64Ty, 9306 /*isSigned=*/true), 9307 SAddr); 9308 } 9309 9310 // Fill up the mapper array. 9311 llvm::Value *MFunc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 9312 if (CombinedInfo.Mappers[I]) { 9313 MFunc = CGM.getOpenMPRuntime().getOrCreateUserDefinedMapperFunc( 9314 cast<OMPDeclareMapperDecl>(CombinedInfo.Mappers[I])); 9315 MFunc = CGF.Builder.CreatePointerCast(MFunc, CGM.VoidPtrTy); 9316 Info.HasMapper = true; 9317 } 9318 Address MAddr = CGF.Builder.CreateConstArrayGEP(MappersArray, I); 9319 CGF.Builder.CreateStore(MFunc, MAddr); 9320 } 9321 } 9322 9323 if (!IsNonContiguous || CombinedInfo.NonContigInfo.Offsets.empty() || 9324 Info.NumberOfPtrs == 0) 9325 return; 9326 9327 emitNonContiguousDescriptor(CGF, CombinedInfo, Info); 9328 } 9329 9330 namespace { 9331 /// Additional arguments for emitOffloadingArraysArgument function. 9332 struct ArgumentsOptions { 9333 bool ForEndCall = false; 9334 ArgumentsOptions() = default; 9335 ArgumentsOptions(bool ForEndCall) : ForEndCall(ForEndCall) {} 9336 }; 9337 } // namespace 9338 9339 /// Emit the arguments to be passed to the runtime library based on the 9340 /// arrays of base pointers, pointers, sizes, map types, and mappers. If 9341 /// ForEndCall, emit map types to be passed for the end of the region instead of 9342 /// the beginning. 9343 static void emitOffloadingArraysArgument( 9344 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 9345 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 9346 llvm::Value *&MapTypesArrayArg, llvm::Value *&MapNamesArrayArg, 9347 llvm::Value *&MappersArrayArg, CGOpenMPRuntime::TargetDataInfo &Info, 9348 const ArgumentsOptions &Options = ArgumentsOptions()) { 9349 assert((!Options.ForEndCall || Info.separateBeginEndCalls()) && 9350 "expected region end call to runtime only when end call is separate"); 9351 CodeGenModule &CGM = CGF.CGM; 9352 if (Info.NumberOfPtrs) { 9353 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9354 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9355 Info.BasePointersArray, 9356 /*Idx0=*/0, /*Idx1=*/0); 9357 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9358 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9359 Info.PointersArray, 9360 /*Idx0=*/0, 9361 /*Idx1=*/0); 9362 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9363 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 9364 /*Idx0=*/0, /*Idx1=*/0); 9365 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9366 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 9367 Options.ForEndCall && Info.MapTypesArrayEnd ? Info.MapTypesArrayEnd 9368 : Info.MapTypesArray, 9369 /*Idx0=*/0, 9370 /*Idx1=*/0); 9371 9372 // Only emit the mapper information arrays if debug information is 9373 // requested. 9374 if (CGF.CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo) 9375 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9376 else 9377 MapNamesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 9378 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 9379 Info.MapNamesArray, 9380 /*Idx0=*/0, 9381 /*Idx1=*/0); 9382 // If there is no user-defined mapper, set the mapper array to nullptr to 9383 // avoid an unnecessary data privatization 9384 if (!Info.HasMapper) 9385 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9386 else 9387 MappersArrayArg = 9388 CGF.Builder.CreatePointerCast(Info.MappersArray, CGM.VoidPtrPtrTy); 9389 } else { 9390 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9391 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9392 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9393 MapTypesArrayArg = 9394 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 9395 MapNamesArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9396 MappersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 9397 } 9398 } 9399 9400 /// Check for inner distribute directive. 9401 static const OMPExecutableDirective * 9402 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 9403 const auto *CS = D.getInnermostCapturedStmt(); 9404 const auto *Body = 9405 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 9406 const Stmt *ChildStmt = 9407 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9408 9409 if (const auto *NestedDir = 9410 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9411 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 9412 switch (D.getDirectiveKind()) { 9413 case OMPD_target: 9414 if (isOpenMPDistributeDirective(DKind)) 9415 return NestedDir; 9416 if (DKind == OMPD_teams) { 9417 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 9418 /*IgnoreCaptured=*/true); 9419 if (!Body) 9420 return nullptr; 9421 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9422 if (const auto *NND = 9423 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9424 DKind = NND->getDirectiveKind(); 9425 if (isOpenMPDistributeDirective(DKind)) 9426 return NND; 9427 } 9428 } 9429 return nullptr; 9430 case OMPD_target_teams: 9431 if (isOpenMPDistributeDirective(DKind)) 9432 return NestedDir; 9433 return nullptr; 9434 case OMPD_target_parallel: 9435 case OMPD_target_simd: 9436 case OMPD_target_parallel_for: 9437 case OMPD_target_parallel_for_simd: 9438 return nullptr; 9439 case OMPD_target_teams_distribute: 9440 case OMPD_target_teams_distribute_simd: 9441 case OMPD_target_teams_distribute_parallel_for: 9442 case OMPD_target_teams_distribute_parallel_for_simd: 9443 case OMPD_parallel: 9444 case OMPD_for: 9445 case OMPD_parallel_for: 9446 case OMPD_parallel_master: 9447 case OMPD_parallel_sections: 9448 case OMPD_for_simd: 9449 case OMPD_parallel_for_simd: 9450 case OMPD_cancel: 9451 case OMPD_cancellation_point: 9452 case OMPD_ordered: 9453 case OMPD_threadprivate: 9454 case OMPD_allocate: 9455 case OMPD_task: 9456 case OMPD_simd: 9457 case OMPD_sections: 9458 case OMPD_section: 9459 case OMPD_single: 9460 case OMPD_master: 9461 case OMPD_critical: 9462 case OMPD_taskyield: 9463 case OMPD_barrier: 9464 case OMPD_taskwait: 9465 case OMPD_taskgroup: 9466 case OMPD_atomic: 9467 case OMPD_flush: 9468 case OMPD_depobj: 9469 case OMPD_scan: 9470 case OMPD_teams: 9471 case OMPD_target_data: 9472 case OMPD_target_exit_data: 9473 case OMPD_target_enter_data: 9474 case OMPD_distribute: 9475 case OMPD_distribute_simd: 9476 case OMPD_distribute_parallel_for: 9477 case OMPD_distribute_parallel_for_simd: 9478 case OMPD_teams_distribute: 9479 case OMPD_teams_distribute_simd: 9480 case OMPD_teams_distribute_parallel_for: 9481 case OMPD_teams_distribute_parallel_for_simd: 9482 case OMPD_target_update: 9483 case OMPD_declare_simd: 9484 case OMPD_declare_variant: 9485 case OMPD_begin_declare_variant: 9486 case OMPD_end_declare_variant: 9487 case OMPD_declare_target: 9488 case OMPD_end_declare_target: 9489 case OMPD_declare_reduction: 9490 case OMPD_declare_mapper: 9491 case OMPD_taskloop: 9492 case OMPD_taskloop_simd: 9493 case OMPD_master_taskloop: 9494 case OMPD_master_taskloop_simd: 9495 case OMPD_parallel_master_taskloop: 9496 case OMPD_parallel_master_taskloop_simd: 9497 case OMPD_requires: 9498 case OMPD_unknown: 9499 default: 9500 llvm_unreachable("Unexpected directive."); 9501 } 9502 } 9503 9504 return nullptr; 9505 } 9506 9507 /// Emit the user-defined mapper function. The code generation follows the 9508 /// pattern in the example below. 9509 /// \code 9510 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 9511 /// void *base, void *begin, 9512 /// int64_t size, int64_t type) { 9513 /// // Allocate space for an array section first. 9514 /// if (size > 1 && !maptype.IsDelete) 9515 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9516 /// size*sizeof(Ty), clearToFrom(type)); 9517 /// // Map members. 9518 /// for (unsigned i = 0; i < size; i++) { 9519 /// // For each component specified by this mapper: 9520 /// for (auto c : all_components) { 9521 /// if (c.hasMapper()) 9522 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 9523 /// c.arg_type); 9524 /// else 9525 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 9526 /// c.arg_begin, c.arg_size, c.arg_type); 9527 /// } 9528 /// } 9529 /// // Delete the array section. 9530 /// if (size > 1 && maptype.IsDelete) 9531 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9532 /// size*sizeof(Ty), clearToFrom(type)); 9533 /// } 9534 /// \endcode 9535 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 9536 CodeGenFunction *CGF) { 9537 if (UDMMap.count(D) > 0) 9538 return; 9539 ASTContext &C = CGM.getContext(); 9540 QualType Ty = D->getType(); 9541 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 9542 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 9543 auto *MapperVarDecl = 9544 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 9545 SourceLocation Loc = D->getLocation(); 9546 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 9547 9548 // Prepare mapper function arguments and attributes. 9549 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9550 C.VoidPtrTy, ImplicitParamDecl::Other); 9551 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9552 ImplicitParamDecl::Other); 9553 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9554 C.VoidPtrTy, ImplicitParamDecl::Other); 9555 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9556 ImplicitParamDecl::Other); 9557 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9558 ImplicitParamDecl::Other); 9559 FunctionArgList Args; 9560 Args.push_back(&HandleArg); 9561 Args.push_back(&BaseArg); 9562 Args.push_back(&BeginArg); 9563 Args.push_back(&SizeArg); 9564 Args.push_back(&TypeArg); 9565 const CGFunctionInfo &FnInfo = 9566 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 9567 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 9568 SmallString<64> TyStr; 9569 llvm::raw_svector_ostream Out(TyStr); 9570 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 9571 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 9572 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 9573 Name, &CGM.getModule()); 9574 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 9575 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 9576 // Start the mapper function code generation. 9577 CodeGenFunction MapperCGF(CGM); 9578 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 9579 // Compute the starting and end addreses of array elements. 9580 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 9581 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 9582 C.getPointerType(Int64Ty), Loc); 9583 // Convert the size in bytes into the number of array elements. 9584 Size = MapperCGF.Builder.CreateExactUDiv( 9585 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9586 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 9587 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 9588 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 9589 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 9590 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 9591 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 9592 C.getPointerType(Int64Ty), Loc); 9593 // Prepare common arguments for array initiation and deletion. 9594 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 9595 MapperCGF.GetAddrOfLocalVar(&HandleArg), 9596 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9597 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 9598 MapperCGF.GetAddrOfLocalVar(&BaseArg), 9599 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9600 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 9601 MapperCGF.GetAddrOfLocalVar(&BeginArg), 9602 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9603 9604 // Emit array initiation if this is an array section and \p MapType indicates 9605 // that memory allocation is required. 9606 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 9607 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9608 ElementSize, HeadBB, /*IsInit=*/true); 9609 9610 // Emit a for loop to iterate through SizeArg of elements and map all of them. 9611 9612 // Emit the loop header block. 9613 MapperCGF.EmitBlock(HeadBB); 9614 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 9615 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 9616 // Evaluate whether the initial condition is satisfied. 9617 llvm::Value *IsEmpty = 9618 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 9619 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 9620 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 9621 9622 // Emit the loop body block. 9623 MapperCGF.EmitBlock(BodyBB); 9624 llvm::BasicBlock *LastBB = BodyBB; 9625 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 9626 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 9627 PtrPHI->addIncoming(PtrBegin, EntryBB); 9628 Address PtrCurrent = 9629 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 9630 .getAlignment() 9631 .alignmentOfArrayElement(ElementSize)); 9632 // Privatize the declared variable of mapper to be the current array element. 9633 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 9634 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 9635 return MapperCGF 9636 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 9637 .getAddress(MapperCGF); 9638 }); 9639 (void)Scope.Privatize(); 9640 9641 // Get map clause information. Fill up the arrays with all mapped variables. 9642 MappableExprsHandler::MapCombinedInfoTy Info; 9643 MappableExprsHandler MEHandler(*D, MapperCGF); 9644 MEHandler.generateAllInfoForMapper(Info); 9645 9646 // Call the runtime API __tgt_mapper_num_components to get the number of 9647 // pre-existing components. 9648 llvm::Value *OffloadingArgs[] = {Handle}; 9649 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 9650 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 9651 OMPRTL___tgt_mapper_num_components), 9652 OffloadingArgs); 9653 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 9654 PreviousSize, 9655 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 9656 9657 // Fill up the runtime mapper handle for all components. 9658 for (unsigned I = 0; I < Info.BasePointers.size(); ++I) { 9659 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 9660 *Info.BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9661 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9662 Info.Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9663 llvm::Value *CurSizeArg = Info.Sizes[I]; 9664 9665 // Extract the MEMBER_OF field from the map type. 9666 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 9667 MapperCGF.EmitBlock(MemberBB); 9668 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(Info.Types[I]); 9669 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 9670 OriMapType, 9671 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 9672 llvm::BasicBlock *MemberCombineBB = 9673 MapperCGF.createBasicBlock("omp.member.combine"); 9674 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 9675 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 9676 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 9677 // Add the number of pre-existing components to the MEMBER_OF field if it 9678 // is valid. 9679 MapperCGF.EmitBlock(MemberCombineBB); 9680 llvm::Value *CombinedMember = 9681 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9682 // Do nothing if it is not a member of previous components. 9683 MapperCGF.EmitBlock(TypeBB); 9684 llvm::PHINode *MemberMapType = 9685 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 9686 MemberMapType->addIncoming(OriMapType, MemberBB); 9687 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 9688 9689 // Combine the map type inherited from user-defined mapper with that 9690 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9691 // bits of the \a MapType, which is the input argument of the mapper 9692 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9693 // bits of MemberMapType. 9694 // [OpenMP 5.0], 1.2.6. map-type decay. 9695 // | alloc | to | from | tofrom | release | delete 9696 // ---------------------------------------------------------- 9697 // alloc | alloc | alloc | alloc | alloc | release | delete 9698 // to | alloc | to | alloc | to | release | delete 9699 // from | alloc | alloc | from | from | release | delete 9700 // tofrom | alloc | to | from | tofrom | release | delete 9701 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9702 MapType, 9703 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9704 MappableExprsHandler::OMP_MAP_FROM)); 9705 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9706 llvm::BasicBlock *AllocElseBB = 9707 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9708 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9709 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9710 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9711 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9712 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9713 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9714 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9715 MapperCGF.EmitBlock(AllocBB); 9716 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9717 MemberMapType, 9718 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9719 MappableExprsHandler::OMP_MAP_FROM))); 9720 MapperCGF.Builder.CreateBr(EndBB); 9721 MapperCGF.EmitBlock(AllocElseBB); 9722 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9723 LeftToFrom, 9724 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9725 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9726 // In case of to, clear OMP_MAP_FROM. 9727 MapperCGF.EmitBlock(ToBB); 9728 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9729 MemberMapType, 9730 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9731 MapperCGF.Builder.CreateBr(EndBB); 9732 MapperCGF.EmitBlock(ToElseBB); 9733 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9734 LeftToFrom, 9735 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9736 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9737 // In case of from, clear OMP_MAP_TO. 9738 MapperCGF.EmitBlock(FromBB); 9739 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9740 MemberMapType, 9741 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9742 // In case of tofrom, do nothing. 9743 MapperCGF.EmitBlock(EndBB); 9744 LastBB = EndBB; 9745 llvm::PHINode *CurMapType = 9746 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9747 CurMapType->addIncoming(AllocMapType, AllocBB); 9748 CurMapType->addIncoming(ToMapType, ToBB); 9749 CurMapType->addIncoming(FromMapType, FromBB); 9750 CurMapType->addIncoming(MemberMapType, ToElseBB); 9751 9752 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9753 CurSizeArg, CurMapType}; 9754 if (Info.Mappers[I]) { 9755 // Call the corresponding mapper function. 9756 llvm::Function *MapperFunc = getOrCreateUserDefinedMapperFunc( 9757 cast<OMPDeclareMapperDecl>(Info.Mappers[I])); 9758 assert(MapperFunc && "Expect a valid mapper function is available."); 9759 MapperCGF.EmitNounwindRuntimeCall(MapperFunc, OffloadingArgs); 9760 } else { 9761 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9762 // data structure. 9763 MapperCGF.EmitRuntimeCall( 9764 OMPBuilder.getOrCreateRuntimeFunction( 9765 CGM.getModule(), OMPRTL___tgt_push_mapper_component), 9766 OffloadingArgs); 9767 } 9768 } 9769 9770 // Update the pointer to point to the next element that needs to be mapped, 9771 // and check whether we have mapped all elements. 9772 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9773 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9774 PtrPHI->addIncoming(PtrNext, LastBB); 9775 llvm::Value *IsDone = 9776 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9777 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9778 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9779 9780 MapperCGF.EmitBlock(ExitBB); 9781 // Emit array deletion if this is an array section and \p MapType indicates 9782 // that deletion is required. 9783 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9784 ElementSize, DoneBB, /*IsInit=*/false); 9785 9786 // Emit the function exit block. 9787 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9788 MapperCGF.FinishFunction(); 9789 UDMMap.try_emplace(D, Fn); 9790 if (CGF) { 9791 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9792 Decls.second.push_back(D); 9793 } 9794 } 9795 9796 /// Emit the array initialization or deletion portion for user-defined mapper 9797 /// code generation. First, it evaluates whether an array section is mapped and 9798 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9799 /// true, and \a MapType indicates to not delete this array, array 9800 /// initialization code is generated. If \a IsInit is false, and \a MapType 9801 /// indicates to not this array, array deletion code is generated. 9802 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9803 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9804 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9805 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9806 StringRef Prefix = IsInit ? ".init" : ".del"; 9807 9808 // Evaluate if this is an array section. 9809 llvm::BasicBlock *IsDeleteBB = 9810 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"})); 9811 llvm::BasicBlock *BodyBB = 9812 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 9813 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9814 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9815 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9816 9817 // Evaluate if we are going to delete this section. 9818 MapperCGF.EmitBlock(IsDeleteBB); 9819 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9820 MapType, 9821 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9822 llvm::Value *DeleteCond; 9823 if (IsInit) { 9824 DeleteCond = MapperCGF.Builder.CreateIsNull( 9825 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9826 } else { 9827 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9828 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9829 } 9830 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9831 9832 MapperCGF.EmitBlock(BodyBB); 9833 // Get the array size by multiplying element size and element number (i.e., \p 9834 // Size). 9835 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9836 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9837 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9838 // memory allocation/deletion purpose only. 9839 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9840 MapType, 9841 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9842 MappableExprsHandler::OMP_MAP_FROM))); 9843 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9844 // data structure. 9845 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9846 MapperCGF.EmitRuntimeCall( 9847 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 9848 OMPRTL___tgt_push_mapper_component), 9849 OffloadingArgs); 9850 } 9851 9852 llvm::Function *CGOpenMPRuntime::getOrCreateUserDefinedMapperFunc( 9853 const OMPDeclareMapperDecl *D) { 9854 auto I = UDMMap.find(D); 9855 if (I != UDMMap.end()) 9856 return I->second; 9857 emitUserDefinedMapper(D); 9858 return UDMMap.lookup(D); 9859 } 9860 9861 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9862 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9863 llvm::Value *DeviceID, 9864 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9865 const OMPLoopDirective &D)> 9866 SizeEmitter) { 9867 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9868 const OMPExecutableDirective *TD = &D; 9869 // Get nested teams distribute kind directive, if any. 9870 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9871 TD = getNestedDistributeDirective(CGM.getContext(), D); 9872 if (!TD) 9873 return; 9874 const auto *LD = cast<OMPLoopDirective>(TD); 9875 auto &&CodeGen = [LD, DeviceID, SizeEmitter, &D, this](CodeGenFunction &CGF, 9876 PrePostActionTy &) { 9877 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9878 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 9879 llvm::Value *Args[] = {RTLoc, DeviceID, NumIterations}; 9880 CGF.EmitRuntimeCall( 9881 OMPBuilder.getOrCreateRuntimeFunction( 9882 CGM.getModule(), OMPRTL___kmpc_push_target_tripcount), 9883 Args); 9884 } 9885 }; 9886 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9887 } 9888 9889 void CGOpenMPRuntime::emitTargetCall( 9890 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9891 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9892 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 9893 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9894 const OMPLoopDirective &D)> 9895 SizeEmitter) { 9896 if (!CGF.HaveInsertPoint()) 9897 return; 9898 9899 assert(OutlinedFn && "Invalid outlined function!"); 9900 9901 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 9902 D.hasClausesOfKind<OMPNowaitClause>(); 9903 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9904 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9905 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9906 PrePostActionTy &) { 9907 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9908 }; 9909 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9910 9911 CodeGenFunction::OMPTargetDataInfo InputInfo; 9912 llvm::Value *MapTypesArray = nullptr; 9913 llvm::Value *MapNamesArray = nullptr; 9914 // Fill up the pointer arrays and transfer execution to the device. 9915 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9916 &MapTypesArray, &MapNamesArray, &CS, RequiresOuterTask, 9917 &CapturedVars, 9918 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9919 if (Device.getInt() == OMPC_DEVICE_ancestor) { 9920 // Reverse offloading is not supported, so just execute on the host. 9921 if (RequiresOuterTask) { 9922 CapturedVars.clear(); 9923 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9924 } 9925 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9926 return; 9927 } 9928 9929 // On top of the arrays that were filled up, the target offloading call 9930 // takes as arguments the device id as well as the host pointer. The host 9931 // pointer is used by the runtime library to identify the current target 9932 // region, so it only has to be unique and not necessarily point to 9933 // anything. It could be the pointer to the outlined function that 9934 // implements the target region, but we aren't using that so that the 9935 // compiler doesn't need to keep that, and could therefore inline the host 9936 // function if proven worthwhile during optimization. 9937 9938 // From this point on, we need to have an ID of the target region defined. 9939 assert(OutlinedFnID && "Invalid outlined function ID!"); 9940 9941 // Emit device ID if any. 9942 llvm::Value *DeviceID; 9943 if (Device.getPointer()) { 9944 assert((Device.getInt() == OMPC_DEVICE_unknown || 9945 Device.getInt() == OMPC_DEVICE_device_num) && 9946 "Expected device_num modifier."); 9947 llvm::Value *DevVal = CGF.EmitScalarExpr(Device.getPointer()); 9948 DeviceID = 9949 CGF.Builder.CreateIntCast(DevVal, 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 = 9956 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9957 9958 // Return value of the runtime offloading call. 9959 llvm::Value *Return; 9960 9961 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9962 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9963 9964 // Source location for the ident struct 9965 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 9966 9967 // Emit tripcount for the target loop-based directive. 9968 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9969 9970 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9971 // The target region is an outlined function launched by the runtime 9972 // via calls __tgt_target() or __tgt_target_teams(). 9973 // 9974 // __tgt_target() launches a target region with one team and one thread, 9975 // executing a serial region. This master thread may in turn launch 9976 // more threads within its team upon encountering a parallel region, 9977 // however, no additional teams can be launched on the device. 9978 // 9979 // __tgt_target_teams() launches a target region with one or more teams, 9980 // each with one or more threads. This call is required for target 9981 // constructs such as: 9982 // 'target teams' 9983 // 'target' / 'teams' 9984 // 'target teams distribute parallel for' 9985 // 'target parallel' 9986 // and so on. 9987 // 9988 // Note that on the host and CPU targets, the runtime implementation of 9989 // these calls simply call the outlined function without forking threads. 9990 // The outlined functions themselves have runtime calls to 9991 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9992 // the compiler in emitTeamsCall() and emitParallelCall(). 9993 // 9994 // In contrast, on the NVPTX target, the implementation of 9995 // __tgt_target_teams() launches a GPU kernel with the requested number 9996 // of teams and threads so no additional calls to the runtime are required. 9997 if (NumTeams) { 9998 // If we have NumTeams defined this means that we have an enclosed teams 9999 // region. Therefore we also expect to have NumThreads defined. These two 10000 // values should be defined in the presence of a teams directive, 10001 // regardless of having any clauses associated. If the user is using teams 10002 // but no clauses, these two values will be the default that should be 10003 // passed to the runtime library - a 32-bit integer with the value zero. 10004 assert(NumThreads && "Thread limit expression should be available along " 10005 "with number of teams."); 10006 llvm::Value *OffloadingArgs[] = {RTLoc, 10007 DeviceID, 10008 OutlinedFnID, 10009 PointerNum, 10010 InputInfo.BasePointersArray.getPointer(), 10011 InputInfo.PointersArray.getPointer(), 10012 InputInfo.SizesArray.getPointer(), 10013 MapTypesArray, 10014 MapNamesArray, 10015 InputInfo.MappersArray.getPointer(), 10016 NumTeams, 10017 NumThreads}; 10018 Return = CGF.EmitRuntimeCall( 10019 OMPBuilder.getOrCreateRuntimeFunction( 10020 CGM.getModule(), HasNowait 10021 ? OMPRTL___tgt_target_teams_nowait_mapper 10022 : OMPRTL___tgt_target_teams_mapper), 10023 OffloadingArgs); 10024 } else { 10025 llvm::Value *OffloadingArgs[] = {RTLoc, 10026 DeviceID, 10027 OutlinedFnID, 10028 PointerNum, 10029 InputInfo.BasePointersArray.getPointer(), 10030 InputInfo.PointersArray.getPointer(), 10031 InputInfo.SizesArray.getPointer(), 10032 MapTypesArray, 10033 MapNamesArray, 10034 InputInfo.MappersArray.getPointer()}; 10035 Return = CGF.EmitRuntimeCall( 10036 OMPBuilder.getOrCreateRuntimeFunction( 10037 CGM.getModule(), HasNowait ? OMPRTL___tgt_target_nowait_mapper 10038 : OMPRTL___tgt_target_mapper), 10039 OffloadingArgs); 10040 } 10041 10042 // Check the error code and execute the host version if required. 10043 llvm::BasicBlock *OffloadFailedBlock = 10044 CGF.createBasicBlock("omp_offload.failed"); 10045 llvm::BasicBlock *OffloadContBlock = 10046 CGF.createBasicBlock("omp_offload.cont"); 10047 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 10048 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 10049 10050 CGF.EmitBlock(OffloadFailedBlock); 10051 if (RequiresOuterTask) { 10052 CapturedVars.clear(); 10053 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10054 } 10055 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10056 CGF.EmitBranch(OffloadContBlock); 10057 10058 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 10059 }; 10060 10061 // Notify that the host version must be executed. 10062 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 10063 RequiresOuterTask](CodeGenFunction &CGF, 10064 PrePostActionTy &) { 10065 if (RequiresOuterTask) { 10066 CapturedVars.clear(); 10067 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 10068 } 10069 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 10070 }; 10071 10072 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 10073 &MapNamesArray, &CapturedVars, RequiresOuterTask, 10074 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 10075 // Fill up the arrays with all the captured variables. 10076 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 10077 10078 // Get mappable expression information. 10079 MappableExprsHandler MEHandler(D, CGF); 10080 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 10081 llvm::DenseSet<CanonicalDeclPtr<const Decl>> MappedVarSet; 10082 10083 auto RI = CS.getCapturedRecordDecl()->field_begin(); 10084 auto CV = CapturedVars.begin(); 10085 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 10086 CE = CS.capture_end(); 10087 CI != CE; ++CI, ++RI, ++CV) { 10088 MappableExprsHandler::MapCombinedInfoTy CurInfo; 10089 MappableExprsHandler::StructRangeInfoTy PartialStruct; 10090 10091 // VLA sizes are passed to the outlined region by copy and do not have map 10092 // information associated. 10093 if (CI->capturesVariableArrayType()) { 10094 CurInfo.Exprs.push_back(nullptr); 10095 CurInfo.BasePointers.push_back(*CV); 10096 CurInfo.Pointers.push_back(*CV); 10097 CurInfo.Sizes.push_back(CGF.Builder.CreateIntCast( 10098 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 10099 // Copy to the device as an argument. No need to retrieve it. 10100 CurInfo.Types.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 10101 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 10102 MappableExprsHandler::OMP_MAP_IMPLICIT); 10103 CurInfo.Mappers.push_back(nullptr); 10104 } else { 10105 // If we have any information in the map clause, we use it, otherwise we 10106 // just do a default mapping. 10107 MEHandler.generateInfoForCapture(CI, *CV, CurInfo, PartialStruct); 10108 if (!CI->capturesThis()) 10109 MappedVarSet.insert(CI->getCapturedVar()); 10110 else 10111 MappedVarSet.insert(nullptr); 10112 if (CurInfo.BasePointers.empty() && !PartialStruct.Base.isValid()) 10113 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurInfo); 10114 // Generate correct mapping for variables captured by reference in 10115 // lambdas. 10116 if (CI->capturesVariable()) 10117 MEHandler.generateInfoForLambdaCaptures(CI->getCapturedVar(), *CV, 10118 CurInfo, LambdaPointers); 10119 } 10120 // We expect to have at least an element of information for this capture. 10121 assert((!CurInfo.BasePointers.empty() || PartialStruct.Base.isValid()) && 10122 "Non-existing map pointer for capture!"); 10123 assert(CurInfo.BasePointers.size() == CurInfo.Pointers.size() && 10124 CurInfo.BasePointers.size() == CurInfo.Sizes.size() && 10125 CurInfo.BasePointers.size() == CurInfo.Types.size() && 10126 CurInfo.BasePointers.size() == CurInfo.Mappers.size() && 10127 "Inconsistent map information sizes!"); 10128 10129 // If there is an entry in PartialStruct it means we have a struct with 10130 // individual members mapped. Emit an extra combined entry. 10131 if (PartialStruct.Base.isValid()) 10132 MEHandler.emitCombinedEntry(CombinedInfo, CurInfo.Types, PartialStruct); 10133 10134 // We need to append the results of this capture to what we already have. 10135 CombinedInfo.append(CurInfo); 10136 } 10137 // Adjust MEMBER_OF flags for the lambdas captures. 10138 MEHandler.adjustMemberOfForLambdaCaptures( 10139 LambdaPointers, CombinedInfo.BasePointers, CombinedInfo.Pointers, 10140 CombinedInfo.Types); 10141 // Map any list items in a map clause that were not captures because they 10142 // weren't referenced within the construct. 10143 MEHandler.generateAllInfo(CombinedInfo, /*NotTargetParams=*/true, 10144 MappedVarSet); 10145 10146 TargetDataInfo Info; 10147 // Fill up the arrays and create the arguments. 10148 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder); 10149 emitOffloadingArraysArgument( 10150 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 10151 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 10152 {/*ForEndTask=*/false}); 10153 10154 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10155 InputInfo.BasePointersArray = 10156 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10157 InputInfo.PointersArray = 10158 Address(Info.PointersArray, CGM.getPointerAlign()); 10159 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 10160 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 10161 MapTypesArray = Info.MapTypesArray; 10162 MapNamesArray = Info.MapNamesArray; 10163 if (RequiresOuterTask) 10164 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10165 else 10166 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10167 }; 10168 10169 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 10170 CodeGenFunction &CGF, PrePostActionTy &) { 10171 if (RequiresOuterTask) { 10172 CodeGenFunction::OMPTargetDataInfo InputInfo; 10173 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 10174 } else { 10175 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 10176 } 10177 }; 10178 10179 // If we have a target function ID it means that we need to support 10180 // offloading, otherwise, just execute on the host. We need to execute on host 10181 // regardless of the conditional in the if clause if, e.g., the user do not 10182 // specify target triples. 10183 if (OutlinedFnID) { 10184 if (IfCond) { 10185 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 10186 } else { 10187 RegionCodeGenTy ThenRCG(TargetThenGen); 10188 ThenRCG(CGF); 10189 } 10190 } else { 10191 RegionCodeGenTy ElseRCG(TargetElseGen); 10192 ElseRCG(CGF); 10193 } 10194 } 10195 10196 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 10197 StringRef ParentName) { 10198 if (!S) 10199 return; 10200 10201 // Codegen OMP target directives that offload compute to the device. 10202 bool RequiresDeviceCodegen = 10203 isa<OMPExecutableDirective>(S) && 10204 isOpenMPTargetExecutionDirective( 10205 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 10206 10207 if (RequiresDeviceCodegen) { 10208 const auto &E = *cast<OMPExecutableDirective>(S); 10209 unsigned DeviceID; 10210 unsigned FileID; 10211 unsigned Line; 10212 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 10213 FileID, Line); 10214 10215 // Is this a target region that should not be emitted as an entry point? If 10216 // so just signal we are done with this target region. 10217 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 10218 ParentName, Line)) 10219 return; 10220 10221 switch (E.getDirectiveKind()) { 10222 case OMPD_target: 10223 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 10224 cast<OMPTargetDirective>(E)); 10225 break; 10226 case OMPD_target_parallel: 10227 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 10228 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 10229 break; 10230 case OMPD_target_teams: 10231 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 10232 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 10233 break; 10234 case OMPD_target_teams_distribute: 10235 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 10236 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 10237 break; 10238 case OMPD_target_teams_distribute_simd: 10239 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 10240 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 10241 break; 10242 case OMPD_target_parallel_for: 10243 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 10244 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 10245 break; 10246 case OMPD_target_parallel_for_simd: 10247 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 10248 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 10249 break; 10250 case OMPD_target_simd: 10251 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 10252 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 10253 break; 10254 case OMPD_target_teams_distribute_parallel_for: 10255 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 10256 CGM, ParentName, 10257 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 10258 break; 10259 case OMPD_target_teams_distribute_parallel_for_simd: 10260 CodeGenFunction:: 10261 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 10262 CGM, ParentName, 10263 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 10264 break; 10265 case OMPD_parallel: 10266 case OMPD_for: 10267 case OMPD_parallel_for: 10268 case OMPD_parallel_master: 10269 case OMPD_parallel_sections: 10270 case OMPD_for_simd: 10271 case OMPD_parallel_for_simd: 10272 case OMPD_cancel: 10273 case OMPD_cancellation_point: 10274 case OMPD_ordered: 10275 case OMPD_threadprivate: 10276 case OMPD_allocate: 10277 case OMPD_task: 10278 case OMPD_simd: 10279 case OMPD_sections: 10280 case OMPD_section: 10281 case OMPD_single: 10282 case OMPD_master: 10283 case OMPD_critical: 10284 case OMPD_taskyield: 10285 case OMPD_barrier: 10286 case OMPD_taskwait: 10287 case OMPD_taskgroup: 10288 case OMPD_atomic: 10289 case OMPD_flush: 10290 case OMPD_depobj: 10291 case OMPD_scan: 10292 case OMPD_teams: 10293 case OMPD_target_data: 10294 case OMPD_target_exit_data: 10295 case OMPD_target_enter_data: 10296 case OMPD_distribute: 10297 case OMPD_distribute_simd: 10298 case OMPD_distribute_parallel_for: 10299 case OMPD_distribute_parallel_for_simd: 10300 case OMPD_teams_distribute: 10301 case OMPD_teams_distribute_simd: 10302 case OMPD_teams_distribute_parallel_for: 10303 case OMPD_teams_distribute_parallel_for_simd: 10304 case OMPD_target_update: 10305 case OMPD_declare_simd: 10306 case OMPD_declare_variant: 10307 case OMPD_begin_declare_variant: 10308 case OMPD_end_declare_variant: 10309 case OMPD_declare_target: 10310 case OMPD_end_declare_target: 10311 case OMPD_declare_reduction: 10312 case OMPD_declare_mapper: 10313 case OMPD_taskloop: 10314 case OMPD_taskloop_simd: 10315 case OMPD_master_taskloop: 10316 case OMPD_master_taskloop_simd: 10317 case OMPD_parallel_master_taskloop: 10318 case OMPD_parallel_master_taskloop_simd: 10319 case OMPD_requires: 10320 case OMPD_unknown: 10321 default: 10322 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 10323 } 10324 return; 10325 } 10326 10327 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 10328 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 10329 return; 10330 10331 scanForTargetRegionsFunctions(E->getRawStmt(), ParentName); 10332 return; 10333 } 10334 10335 // If this is a lambda function, look into its body. 10336 if (const auto *L = dyn_cast<LambdaExpr>(S)) 10337 S = L->getBody(); 10338 10339 // Keep looking for target regions recursively. 10340 for (const Stmt *II : S->children()) 10341 scanForTargetRegionsFunctions(II, ParentName); 10342 } 10343 10344 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 10345 // If emitting code for the host, we do not process FD here. Instead we do 10346 // the normal code generation. 10347 if (!CGM.getLangOpts().OpenMPIsDevice) { 10348 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 10349 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10350 OMPDeclareTargetDeclAttr::getDeviceType(FD); 10351 // Do not emit device_type(nohost) functions for the host. 10352 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 10353 return true; 10354 } 10355 return false; 10356 } 10357 10358 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 10359 // Try to detect target regions in the function. 10360 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 10361 StringRef Name = CGM.getMangledName(GD); 10362 scanForTargetRegionsFunctions(FD->getBody(), Name); 10363 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 10364 OMPDeclareTargetDeclAttr::getDeviceType(FD); 10365 // Do not emit device_type(nohost) functions for the host. 10366 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 10367 return true; 10368 } 10369 10370 // Do not to emit function if it is not marked as declare target. 10371 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 10372 AlreadyEmittedTargetDecls.count(VD) == 0; 10373 } 10374 10375 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 10376 if (!CGM.getLangOpts().OpenMPIsDevice) 10377 return false; 10378 10379 // Check if there are Ctors/Dtors in this declaration and look for target 10380 // regions in it. We use the complete variant to produce the kernel name 10381 // mangling. 10382 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 10383 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 10384 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 10385 StringRef ParentName = 10386 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 10387 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 10388 } 10389 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 10390 StringRef ParentName = 10391 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 10392 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 10393 } 10394 } 10395 10396 // Do not to emit variable if it is not marked as declare target. 10397 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10398 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 10399 cast<VarDecl>(GD.getDecl())); 10400 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 10401 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10402 HasRequiresUnifiedSharedMemory)) { 10403 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 10404 return true; 10405 } 10406 return false; 10407 } 10408 10409 llvm::Constant * 10410 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 10411 const VarDecl *VD) { 10412 assert(VD->getType().isConstant(CGM.getContext()) && 10413 "Expected constant variable."); 10414 StringRef VarName; 10415 llvm::Constant *Addr; 10416 llvm::GlobalValue::LinkageTypes Linkage; 10417 QualType Ty = VD->getType(); 10418 SmallString<128> Buffer; 10419 { 10420 unsigned DeviceID; 10421 unsigned FileID; 10422 unsigned Line; 10423 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 10424 FileID, Line); 10425 llvm::raw_svector_ostream OS(Buffer); 10426 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 10427 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 10428 VarName = OS.str(); 10429 } 10430 Linkage = llvm::GlobalValue::InternalLinkage; 10431 Addr = 10432 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 10433 getDefaultFirstprivateAddressSpace()); 10434 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 10435 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 10436 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 10437 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10438 VarName, Addr, VarSize, 10439 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 10440 return Addr; 10441 } 10442 10443 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 10444 llvm::Constant *Addr) { 10445 if (CGM.getLangOpts().OMPTargetTriples.empty() && 10446 !CGM.getLangOpts().OpenMPIsDevice) 10447 return; 10448 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10449 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10450 if (!Res) { 10451 if (CGM.getLangOpts().OpenMPIsDevice) { 10452 // Register non-target variables being emitted in device code (debug info 10453 // may cause this). 10454 StringRef VarName = CGM.getMangledName(VD); 10455 EmittedNonTargetVariables.try_emplace(VarName, Addr); 10456 } 10457 return; 10458 } 10459 // Register declare target variables. 10460 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 10461 StringRef VarName; 10462 CharUnits VarSize; 10463 llvm::GlobalValue::LinkageTypes Linkage; 10464 10465 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10466 !HasRequiresUnifiedSharedMemory) { 10467 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10468 VarName = CGM.getMangledName(VD); 10469 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 10470 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 10471 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 10472 } else { 10473 VarSize = CharUnits::Zero(); 10474 } 10475 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 10476 // Temp solution to prevent optimizations of the internal variables. 10477 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 10478 std::string RefName = getName({VarName, "ref"}); 10479 if (!CGM.GetGlobalValue(RefName)) { 10480 llvm::Constant *AddrRef = 10481 getOrCreateInternalVariable(Addr->getType(), RefName); 10482 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 10483 GVAddrRef->setConstant(/*Val=*/true); 10484 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 10485 GVAddrRef->setInitializer(Addr); 10486 CGM.addCompilerUsedGlobal(GVAddrRef); 10487 } 10488 } 10489 } else { 10490 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 10491 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10492 HasRequiresUnifiedSharedMemory)) && 10493 "Declare target attribute must link or to with unified memory."); 10494 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 10495 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 10496 else 10497 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10498 10499 if (CGM.getLangOpts().OpenMPIsDevice) { 10500 VarName = Addr->getName(); 10501 Addr = nullptr; 10502 } else { 10503 VarName = getAddrOfDeclareTargetVar(VD).getName(); 10504 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 10505 } 10506 VarSize = CGM.getPointerSize(); 10507 Linkage = llvm::GlobalValue::WeakAnyLinkage; 10508 } 10509 10510 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10511 VarName, Addr, VarSize, Flags, Linkage); 10512 } 10513 10514 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 10515 if (isa<FunctionDecl>(GD.getDecl()) || 10516 isa<OMPDeclareReductionDecl>(GD.getDecl())) 10517 return emitTargetFunctions(GD); 10518 10519 return emitTargetGlobalVariable(GD); 10520 } 10521 10522 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 10523 for (const VarDecl *VD : DeferredGlobalVariables) { 10524 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10525 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10526 if (!Res) 10527 continue; 10528 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10529 !HasRequiresUnifiedSharedMemory) { 10530 CGM.EmitGlobal(VD); 10531 } else { 10532 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 10533 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10534 HasRequiresUnifiedSharedMemory)) && 10535 "Expected link clause or to clause with unified memory."); 10536 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 10537 } 10538 } 10539 } 10540 10541 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 10542 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 10543 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 10544 " Expected target-based directive."); 10545 } 10546 10547 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 10548 for (const OMPClause *Clause : D->clauselists()) { 10549 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 10550 HasRequiresUnifiedSharedMemory = true; 10551 } else if (const auto *AC = 10552 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 10553 switch (AC->getAtomicDefaultMemOrderKind()) { 10554 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 10555 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 10556 break; 10557 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 10558 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 10559 break; 10560 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 10561 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 10562 break; 10563 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 10564 break; 10565 } 10566 } 10567 } 10568 } 10569 10570 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 10571 return RequiresAtomicOrdering; 10572 } 10573 10574 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 10575 LangAS &AS) { 10576 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 10577 return false; 10578 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 10579 switch(A->getAllocatorType()) { 10580 case OMPAllocateDeclAttr::OMPNullMemAlloc: 10581 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 10582 // Not supported, fallback to the default mem space. 10583 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 10584 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 10585 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 10586 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 10587 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 10588 case OMPAllocateDeclAttr::OMPConstMemAlloc: 10589 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 10590 AS = LangAS::Default; 10591 return true; 10592 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 10593 llvm_unreachable("Expected predefined allocator for the variables with the " 10594 "static storage."); 10595 } 10596 return false; 10597 } 10598 10599 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 10600 return HasRequiresUnifiedSharedMemory; 10601 } 10602 10603 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 10604 CodeGenModule &CGM) 10605 : CGM(CGM) { 10606 if (CGM.getLangOpts().OpenMPIsDevice) { 10607 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 10608 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 10609 } 10610 } 10611 10612 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 10613 if (CGM.getLangOpts().OpenMPIsDevice) 10614 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 10615 } 10616 10617 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 10618 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 10619 return true; 10620 10621 const auto *D = cast<FunctionDecl>(GD.getDecl()); 10622 // Do not to emit function if it is marked as declare target as it was already 10623 // emitted. 10624 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 10625 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 10626 if (auto *F = dyn_cast_or_null<llvm::Function>( 10627 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 10628 return !F->isDeclaration(); 10629 return false; 10630 } 10631 return true; 10632 } 10633 10634 return !AlreadyEmittedTargetDecls.insert(D).second; 10635 } 10636 10637 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 10638 // If we don't have entries or if we are emitting code for the device, we 10639 // don't need to do anything. 10640 if (CGM.getLangOpts().OMPTargetTriples.empty() || 10641 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 10642 (OffloadEntriesInfoManager.empty() && 10643 !HasEmittedDeclareTargetRegion && 10644 !HasEmittedTargetRegion)) 10645 return nullptr; 10646 10647 // Create and register the function that handles the requires directives. 10648 ASTContext &C = CGM.getContext(); 10649 10650 llvm::Function *RequiresRegFn; 10651 { 10652 CodeGenFunction CGF(CGM); 10653 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 10654 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 10655 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 10656 RequiresRegFn = CGM.CreateGlobalInitOrCleanUpFunction(FTy, ReqName, FI); 10657 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 10658 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 10659 // TODO: check for other requires clauses. 10660 // The requires directive takes effect only when a target region is 10661 // present in the compilation unit. Otherwise it is ignored and not 10662 // passed to the runtime. This avoids the runtime from throwing an error 10663 // for mismatching requires clauses across compilation units that don't 10664 // contain at least 1 target region. 10665 assert((HasEmittedTargetRegion || 10666 HasEmittedDeclareTargetRegion || 10667 !OffloadEntriesInfoManager.empty()) && 10668 "Target or declare target region expected."); 10669 if (HasRequiresUnifiedSharedMemory) 10670 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 10671 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 10672 CGM.getModule(), OMPRTL___tgt_register_requires), 10673 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 10674 CGF.FinishFunction(); 10675 } 10676 return RequiresRegFn; 10677 } 10678 10679 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 10680 const OMPExecutableDirective &D, 10681 SourceLocation Loc, 10682 llvm::Function *OutlinedFn, 10683 ArrayRef<llvm::Value *> CapturedVars) { 10684 if (!CGF.HaveInsertPoint()) 10685 return; 10686 10687 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10688 CodeGenFunction::RunCleanupsScope Scope(CGF); 10689 10690 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 10691 llvm::Value *Args[] = { 10692 RTLoc, 10693 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 10694 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 10695 llvm::SmallVector<llvm::Value *, 16> RealArgs; 10696 RealArgs.append(std::begin(Args), std::end(Args)); 10697 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 10698 10699 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 10700 CGM.getModule(), OMPRTL___kmpc_fork_teams); 10701 CGF.EmitRuntimeCall(RTLFn, RealArgs); 10702 } 10703 10704 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 10705 const Expr *NumTeams, 10706 const Expr *ThreadLimit, 10707 SourceLocation Loc) { 10708 if (!CGF.HaveInsertPoint()) 10709 return; 10710 10711 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10712 10713 llvm::Value *NumTeamsVal = 10714 NumTeams 10715 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 10716 CGF.CGM.Int32Ty, /* isSigned = */ true) 10717 : CGF.Builder.getInt32(0); 10718 10719 llvm::Value *ThreadLimitVal = 10720 ThreadLimit 10721 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 10722 CGF.CGM.Int32Ty, /* isSigned = */ true) 10723 : CGF.Builder.getInt32(0); 10724 10725 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 10726 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 10727 ThreadLimitVal}; 10728 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 10729 CGM.getModule(), OMPRTL___kmpc_push_num_teams), 10730 PushNumTeamsArgs); 10731 } 10732 10733 void CGOpenMPRuntime::emitTargetDataCalls( 10734 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10735 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 10736 if (!CGF.HaveInsertPoint()) 10737 return; 10738 10739 // Action used to replace the default codegen action and turn privatization 10740 // off. 10741 PrePostActionTy NoPrivAction; 10742 10743 // Generate the code for the opening of the data environment. Capture all the 10744 // arguments of the runtime call by reference because they are used in the 10745 // closing of the region. 10746 auto &&BeginThenGen = [this, &D, Device, &Info, 10747 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 10748 // Fill up the arrays with all the mapped variables. 10749 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 10750 10751 // Get map clause information. 10752 MappableExprsHandler MEHandler(D, CGF); 10753 MEHandler.generateAllInfo(CombinedInfo); 10754 10755 // Fill up the arrays and create the arguments. 10756 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 10757 /*IsNonContiguous=*/true); 10758 10759 llvm::Value *BasePointersArrayArg = nullptr; 10760 llvm::Value *PointersArrayArg = nullptr; 10761 llvm::Value *SizesArrayArg = nullptr; 10762 llvm::Value *MapTypesArrayArg = nullptr; 10763 llvm::Value *MapNamesArrayArg = nullptr; 10764 llvm::Value *MappersArrayArg = nullptr; 10765 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10766 SizesArrayArg, MapTypesArrayArg, 10767 MapNamesArrayArg, MappersArrayArg, Info); 10768 10769 // Emit device ID if any. 10770 llvm::Value *DeviceID = nullptr; 10771 if (Device) { 10772 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10773 CGF.Int64Ty, /*isSigned=*/true); 10774 } else { 10775 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10776 } 10777 10778 // Emit the number of elements in the offloading arrays. 10779 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10780 // 10781 // Source location for the ident struct 10782 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10783 10784 llvm::Value *OffloadingArgs[] = {RTLoc, 10785 DeviceID, 10786 PointerNum, 10787 BasePointersArrayArg, 10788 PointersArrayArg, 10789 SizesArrayArg, 10790 MapTypesArrayArg, 10791 MapNamesArrayArg, 10792 MappersArrayArg}; 10793 CGF.EmitRuntimeCall( 10794 OMPBuilder.getOrCreateRuntimeFunction( 10795 CGM.getModule(), OMPRTL___tgt_target_data_begin_mapper), 10796 OffloadingArgs); 10797 10798 // If device pointer privatization is required, emit the body of the region 10799 // here. It will have to be duplicated: with and without privatization. 10800 if (!Info.CaptureDeviceAddrMap.empty()) 10801 CodeGen(CGF); 10802 }; 10803 10804 // Generate code for the closing of the data region. 10805 auto &&EndThenGen = [this, Device, &Info, &D](CodeGenFunction &CGF, 10806 PrePostActionTy &) { 10807 assert(Info.isValid() && "Invalid data environment closing arguments."); 10808 10809 llvm::Value *BasePointersArrayArg = nullptr; 10810 llvm::Value *PointersArrayArg = nullptr; 10811 llvm::Value *SizesArrayArg = nullptr; 10812 llvm::Value *MapTypesArrayArg = nullptr; 10813 llvm::Value *MapNamesArrayArg = nullptr; 10814 llvm::Value *MappersArrayArg = nullptr; 10815 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10816 SizesArrayArg, MapTypesArrayArg, 10817 MapNamesArrayArg, MappersArrayArg, Info, 10818 {/*ForEndCall=*/true}); 10819 10820 // Emit device ID if any. 10821 llvm::Value *DeviceID = nullptr; 10822 if (Device) { 10823 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10824 CGF.Int64Ty, /*isSigned=*/true); 10825 } else { 10826 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10827 } 10828 10829 // Emit the number of elements in the offloading arrays. 10830 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10831 10832 // Source location for the ident struct 10833 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10834 10835 llvm::Value *OffloadingArgs[] = {RTLoc, 10836 DeviceID, 10837 PointerNum, 10838 BasePointersArrayArg, 10839 PointersArrayArg, 10840 SizesArrayArg, 10841 MapTypesArrayArg, 10842 MapNamesArrayArg, 10843 MappersArrayArg}; 10844 CGF.EmitRuntimeCall( 10845 OMPBuilder.getOrCreateRuntimeFunction( 10846 CGM.getModule(), OMPRTL___tgt_target_data_end_mapper), 10847 OffloadingArgs); 10848 }; 10849 10850 // If we need device pointer privatization, we need to emit the body of the 10851 // region with no privatization in the 'else' branch of the conditional. 10852 // Otherwise, we don't have to do anything. 10853 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10854 PrePostActionTy &) { 10855 if (!Info.CaptureDeviceAddrMap.empty()) { 10856 CodeGen.setAction(NoPrivAction); 10857 CodeGen(CGF); 10858 } 10859 }; 10860 10861 // We don't have to do anything to close the region if the if clause evaluates 10862 // to false. 10863 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10864 10865 if (IfCond) { 10866 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10867 } else { 10868 RegionCodeGenTy RCG(BeginThenGen); 10869 RCG(CGF); 10870 } 10871 10872 // If we don't require privatization of device pointers, we emit the body in 10873 // between the runtime calls. This avoids duplicating the body code. 10874 if (Info.CaptureDeviceAddrMap.empty()) { 10875 CodeGen.setAction(NoPrivAction); 10876 CodeGen(CGF); 10877 } 10878 10879 if (IfCond) { 10880 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10881 } else { 10882 RegionCodeGenTy RCG(EndThenGen); 10883 RCG(CGF); 10884 } 10885 } 10886 10887 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10888 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10889 const Expr *Device) { 10890 if (!CGF.HaveInsertPoint()) 10891 return; 10892 10893 assert((isa<OMPTargetEnterDataDirective>(D) || 10894 isa<OMPTargetExitDataDirective>(D) || 10895 isa<OMPTargetUpdateDirective>(D)) && 10896 "Expecting either target enter, exit data, or update directives."); 10897 10898 CodeGenFunction::OMPTargetDataInfo InputInfo; 10899 llvm::Value *MapTypesArray = nullptr; 10900 llvm::Value *MapNamesArray = nullptr; 10901 // Generate the code for the opening of the data environment. 10902 auto &&ThenGen = [this, &D, Device, &InputInfo, &MapTypesArray, 10903 &MapNamesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10904 // Emit device ID if any. 10905 llvm::Value *DeviceID = nullptr; 10906 if (Device) { 10907 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10908 CGF.Int64Ty, /*isSigned=*/true); 10909 } else { 10910 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10911 } 10912 10913 // Emit the number of elements in the offloading arrays. 10914 llvm::Constant *PointerNum = 10915 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10916 10917 // Source location for the ident struct 10918 llvm::Value *RTLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 10919 10920 llvm::Value *OffloadingArgs[] = {RTLoc, 10921 DeviceID, 10922 PointerNum, 10923 InputInfo.BasePointersArray.getPointer(), 10924 InputInfo.PointersArray.getPointer(), 10925 InputInfo.SizesArray.getPointer(), 10926 MapTypesArray, 10927 MapNamesArray, 10928 InputInfo.MappersArray.getPointer()}; 10929 10930 // Select the right runtime function call for each standalone 10931 // directive. 10932 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10933 RuntimeFunction RTLFn; 10934 switch (D.getDirectiveKind()) { 10935 case OMPD_target_enter_data: 10936 RTLFn = HasNowait ? OMPRTL___tgt_target_data_begin_nowait_mapper 10937 : OMPRTL___tgt_target_data_begin_mapper; 10938 break; 10939 case OMPD_target_exit_data: 10940 RTLFn = HasNowait ? OMPRTL___tgt_target_data_end_nowait_mapper 10941 : OMPRTL___tgt_target_data_end_mapper; 10942 break; 10943 case OMPD_target_update: 10944 RTLFn = HasNowait ? OMPRTL___tgt_target_data_update_nowait_mapper 10945 : OMPRTL___tgt_target_data_update_mapper; 10946 break; 10947 case OMPD_parallel: 10948 case OMPD_for: 10949 case OMPD_parallel_for: 10950 case OMPD_parallel_master: 10951 case OMPD_parallel_sections: 10952 case OMPD_for_simd: 10953 case OMPD_parallel_for_simd: 10954 case OMPD_cancel: 10955 case OMPD_cancellation_point: 10956 case OMPD_ordered: 10957 case OMPD_threadprivate: 10958 case OMPD_allocate: 10959 case OMPD_task: 10960 case OMPD_simd: 10961 case OMPD_sections: 10962 case OMPD_section: 10963 case OMPD_single: 10964 case OMPD_master: 10965 case OMPD_critical: 10966 case OMPD_taskyield: 10967 case OMPD_barrier: 10968 case OMPD_taskwait: 10969 case OMPD_taskgroup: 10970 case OMPD_atomic: 10971 case OMPD_flush: 10972 case OMPD_depobj: 10973 case OMPD_scan: 10974 case OMPD_teams: 10975 case OMPD_target_data: 10976 case OMPD_distribute: 10977 case OMPD_distribute_simd: 10978 case OMPD_distribute_parallel_for: 10979 case OMPD_distribute_parallel_for_simd: 10980 case OMPD_teams_distribute: 10981 case OMPD_teams_distribute_simd: 10982 case OMPD_teams_distribute_parallel_for: 10983 case OMPD_teams_distribute_parallel_for_simd: 10984 case OMPD_declare_simd: 10985 case OMPD_declare_variant: 10986 case OMPD_begin_declare_variant: 10987 case OMPD_end_declare_variant: 10988 case OMPD_declare_target: 10989 case OMPD_end_declare_target: 10990 case OMPD_declare_reduction: 10991 case OMPD_declare_mapper: 10992 case OMPD_taskloop: 10993 case OMPD_taskloop_simd: 10994 case OMPD_master_taskloop: 10995 case OMPD_master_taskloop_simd: 10996 case OMPD_parallel_master_taskloop: 10997 case OMPD_parallel_master_taskloop_simd: 10998 case OMPD_target: 10999 case OMPD_target_simd: 11000 case OMPD_target_teams_distribute: 11001 case OMPD_target_teams_distribute_simd: 11002 case OMPD_target_teams_distribute_parallel_for: 11003 case OMPD_target_teams_distribute_parallel_for_simd: 11004 case OMPD_target_teams: 11005 case OMPD_target_parallel: 11006 case OMPD_target_parallel_for: 11007 case OMPD_target_parallel_for_simd: 11008 case OMPD_requires: 11009 case OMPD_unknown: 11010 default: 11011 llvm_unreachable("Unexpected standalone target data directive."); 11012 break; 11013 } 11014 CGF.EmitRuntimeCall( 11015 OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), RTLFn), 11016 OffloadingArgs); 11017 }; 11018 11019 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 11020 &MapNamesArray](CodeGenFunction &CGF, 11021 PrePostActionTy &) { 11022 // Fill up the arrays with all the mapped variables. 11023 MappableExprsHandler::MapCombinedInfoTy CombinedInfo; 11024 11025 // Get map clause information. 11026 MappableExprsHandler MEHandler(D, CGF); 11027 MEHandler.generateAllInfo(CombinedInfo); 11028 11029 TargetDataInfo Info; 11030 // Fill up the arrays and create the arguments. 11031 emitOffloadingArrays(CGF, CombinedInfo, Info, OMPBuilder, 11032 /*IsNonContiguous=*/true); 11033 bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>() || 11034 D.hasClausesOfKind<OMPNowaitClause>(); 11035 emitOffloadingArraysArgument( 11036 CGF, Info.BasePointersArray, Info.PointersArray, Info.SizesArray, 11037 Info.MapTypesArray, Info.MapNamesArray, Info.MappersArray, Info, 11038 {/*ForEndTask=*/false}); 11039 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 11040 InputInfo.BasePointersArray = 11041 Address(Info.BasePointersArray, CGM.getPointerAlign()); 11042 InputInfo.PointersArray = 11043 Address(Info.PointersArray, CGM.getPointerAlign()); 11044 InputInfo.SizesArray = 11045 Address(Info.SizesArray, CGM.getPointerAlign()); 11046 InputInfo.MappersArray = Address(Info.MappersArray, CGM.getPointerAlign()); 11047 MapTypesArray = Info.MapTypesArray; 11048 MapNamesArray = Info.MapNamesArray; 11049 if (RequiresOuterTask) 11050 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 11051 else 11052 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 11053 }; 11054 11055 if (IfCond) { 11056 emitIfClause(CGF, IfCond, TargetThenGen, 11057 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 11058 } else { 11059 RegionCodeGenTy ThenRCG(TargetThenGen); 11060 ThenRCG(CGF); 11061 } 11062 } 11063 11064 namespace { 11065 /// Kind of parameter in a function with 'declare simd' directive. 11066 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 11067 /// Attribute set of the parameter. 11068 struct ParamAttrTy { 11069 ParamKindTy Kind = Vector; 11070 llvm::APSInt StrideOrArg; 11071 llvm::APSInt Alignment; 11072 }; 11073 } // namespace 11074 11075 static unsigned evaluateCDTSize(const FunctionDecl *FD, 11076 ArrayRef<ParamAttrTy> ParamAttrs) { 11077 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 11078 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 11079 // of that clause. The VLEN value must be power of 2. 11080 // In other case the notion of the function`s "characteristic data type" (CDT) 11081 // is used to compute the vector length. 11082 // CDT is defined in the following order: 11083 // a) For non-void function, the CDT is the return type. 11084 // b) If the function has any non-uniform, non-linear parameters, then the 11085 // CDT is the type of the first such parameter. 11086 // c) If the CDT determined by a) or b) above is struct, union, or class 11087 // type which is pass-by-value (except for the type that maps to the 11088 // built-in complex data type), the characteristic data type is int. 11089 // d) If none of the above three cases is applicable, the CDT is int. 11090 // The VLEN is then determined based on the CDT and the size of vector 11091 // register of that ISA for which current vector version is generated. The 11092 // VLEN is computed using the formula below: 11093 // VLEN = sizeof(vector_register) / sizeof(CDT), 11094 // where vector register size specified in section 3.2.1 Registers and the 11095 // Stack Frame of original AMD64 ABI document. 11096 QualType RetType = FD->getReturnType(); 11097 if (RetType.isNull()) 11098 return 0; 11099 ASTContext &C = FD->getASTContext(); 11100 QualType CDT; 11101 if (!RetType.isNull() && !RetType->isVoidType()) { 11102 CDT = RetType; 11103 } else { 11104 unsigned Offset = 0; 11105 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 11106 if (ParamAttrs[Offset].Kind == Vector) 11107 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 11108 ++Offset; 11109 } 11110 if (CDT.isNull()) { 11111 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11112 if (ParamAttrs[I + Offset].Kind == Vector) { 11113 CDT = FD->getParamDecl(I)->getType(); 11114 break; 11115 } 11116 } 11117 } 11118 } 11119 if (CDT.isNull()) 11120 CDT = C.IntTy; 11121 CDT = CDT->getCanonicalTypeUnqualified(); 11122 if (CDT->isRecordType() || CDT->isUnionType()) 11123 CDT = C.IntTy; 11124 return C.getTypeSize(CDT); 11125 } 11126 11127 static void 11128 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 11129 const llvm::APSInt &VLENVal, 11130 ArrayRef<ParamAttrTy> ParamAttrs, 11131 OMPDeclareSimdDeclAttr::BranchStateTy State) { 11132 struct ISADataTy { 11133 char ISA; 11134 unsigned VecRegSize; 11135 }; 11136 ISADataTy ISAData[] = { 11137 { 11138 'b', 128 11139 }, // SSE 11140 { 11141 'c', 256 11142 }, // AVX 11143 { 11144 'd', 256 11145 }, // AVX2 11146 { 11147 'e', 512 11148 }, // AVX512 11149 }; 11150 llvm::SmallVector<char, 2> Masked; 11151 switch (State) { 11152 case OMPDeclareSimdDeclAttr::BS_Undefined: 11153 Masked.push_back('N'); 11154 Masked.push_back('M'); 11155 break; 11156 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11157 Masked.push_back('N'); 11158 break; 11159 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11160 Masked.push_back('M'); 11161 break; 11162 } 11163 for (char Mask : Masked) { 11164 for (const ISADataTy &Data : ISAData) { 11165 SmallString<256> Buffer; 11166 llvm::raw_svector_ostream Out(Buffer); 11167 Out << "_ZGV" << Data.ISA << Mask; 11168 if (!VLENVal) { 11169 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 11170 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 11171 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 11172 } else { 11173 Out << VLENVal; 11174 } 11175 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 11176 switch (ParamAttr.Kind){ 11177 case LinearWithVarStride: 11178 Out << 's' << ParamAttr.StrideOrArg; 11179 break; 11180 case Linear: 11181 Out << 'l'; 11182 if (ParamAttr.StrideOrArg != 1) 11183 Out << ParamAttr.StrideOrArg; 11184 break; 11185 case Uniform: 11186 Out << 'u'; 11187 break; 11188 case Vector: 11189 Out << 'v'; 11190 break; 11191 } 11192 if (!!ParamAttr.Alignment) 11193 Out << 'a' << ParamAttr.Alignment; 11194 } 11195 Out << '_' << Fn->getName(); 11196 Fn->addFnAttr(Out.str()); 11197 } 11198 } 11199 } 11200 11201 // This are the Functions that are needed to mangle the name of the 11202 // vector functions generated by the compiler, according to the rules 11203 // defined in the "Vector Function ABI specifications for AArch64", 11204 // available at 11205 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 11206 11207 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 11208 /// 11209 /// TODO: Need to implement the behavior for reference marked with a 11210 /// var or no linear modifiers (1.b in the section). For this, we 11211 /// need to extend ParamKindTy to support the linear modifiers. 11212 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 11213 QT = QT.getCanonicalType(); 11214 11215 if (QT->isVoidType()) 11216 return false; 11217 11218 if (Kind == ParamKindTy::Uniform) 11219 return false; 11220 11221 if (Kind == ParamKindTy::Linear) 11222 return false; 11223 11224 // TODO: Handle linear references with modifiers 11225 11226 if (Kind == ParamKindTy::LinearWithVarStride) 11227 return false; 11228 11229 return true; 11230 } 11231 11232 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 11233 static bool getAArch64PBV(QualType QT, ASTContext &C) { 11234 QT = QT.getCanonicalType(); 11235 unsigned Size = C.getTypeSize(QT); 11236 11237 // Only scalars and complex within 16 bytes wide set PVB to true. 11238 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 11239 return false; 11240 11241 if (QT->isFloatingType()) 11242 return true; 11243 11244 if (QT->isIntegerType()) 11245 return true; 11246 11247 if (QT->isPointerType()) 11248 return true; 11249 11250 // TODO: Add support for complex types (section 3.1.2, item 2). 11251 11252 return false; 11253 } 11254 11255 /// Computes the lane size (LS) of a return type or of an input parameter, 11256 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 11257 /// TODO: Add support for references, section 3.2.1, item 1. 11258 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 11259 if (!getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 11260 QualType PTy = QT.getCanonicalType()->getPointeeType(); 11261 if (getAArch64PBV(PTy, C)) 11262 return C.getTypeSize(PTy); 11263 } 11264 if (getAArch64PBV(QT, C)) 11265 return C.getTypeSize(QT); 11266 11267 return C.getTypeSize(C.getUIntPtrType()); 11268 } 11269 11270 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 11271 // signature of the scalar function, as defined in 3.2.2 of the 11272 // AAVFABI. 11273 static std::tuple<unsigned, unsigned, bool> 11274 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 11275 QualType RetType = FD->getReturnType().getCanonicalType(); 11276 11277 ASTContext &C = FD->getASTContext(); 11278 11279 bool OutputBecomesInput = false; 11280 11281 llvm::SmallVector<unsigned, 8> Sizes; 11282 if (!RetType->isVoidType()) { 11283 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 11284 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 11285 OutputBecomesInput = true; 11286 } 11287 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 11288 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 11289 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 11290 } 11291 11292 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 11293 // The LS of a function parameter / return value can only be a power 11294 // of 2, starting from 8 bits, up to 128. 11295 assert(std::all_of(Sizes.begin(), Sizes.end(), 11296 [](unsigned Size) { 11297 return Size == 8 || Size == 16 || Size == 32 || 11298 Size == 64 || Size == 128; 11299 }) && 11300 "Invalid size"); 11301 11302 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 11303 *std::max_element(std::begin(Sizes), std::end(Sizes)), 11304 OutputBecomesInput); 11305 } 11306 11307 /// Mangle the parameter part of the vector function name according to 11308 /// their OpenMP classification. The mangling function is defined in 11309 /// section 3.5 of the AAVFABI. 11310 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 11311 SmallString<256> Buffer; 11312 llvm::raw_svector_ostream Out(Buffer); 11313 for (const auto &ParamAttr : ParamAttrs) { 11314 switch (ParamAttr.Kind) { 11315 case LinearWithVarStride: 11316 Out << "ls" << ParamAttr.StrideOrArg; 11317 break; 11318 case Linear: 11319 Out << 'l'; 11320 // Don't print the step value if it is not present or if it is 11321 // equal to 1. 11322 if (ParamAttr.StrideOrArg != 1) 11323 Out << ParamAttr.StrideOrArg; 11324 break; 11325 case Uniform: 11326 Out << 'u'; 11327 break; 11328 case Vector: 11329 Out << 'v'; 11330 break; 11331 } 11332 11333 if (!!ParamAttr.Alignment) 11334 Out << 'a' << ParamAttr.Alignment; 11335 } 11336 11337 return std::string(Out.str()); 11338 } 11339 11340 // Function used to add the attribute. The parameter `VLEN` is 11341 // templated to allow the use of "x" when targeting scalable functions 11342 // for SVE. 11343 template <typename T> 11344 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 11345 char ISA, StringRef ParSeq, 11346 StringRef MangledName, bool OutputBecomesInput, 11347 llvm::Function *Fn) { 11348 SmallString<256> Buffer; 11349 llvm::raw_svector_ostream Out(Buffer); 11350 Out << Prefix << ISA << LMask << VLEN; 11351 if (OutputBecomesInput) 11352 Out << "v"; 11353 Out << ParSeq << "_" << MangledName; 11354 Fn->addFnAttr(Out.str()); 11355 } 11356 11357 // Helper function to generate the Advanced SIMD names depending on 11358 // the value of the NDS when simdlen is not present. 11359 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 11360 StringRef Prefix, char ISA, 11361 StringRef ParSeq, StringRef MangledName, 11362 bool OutputBecomesInput, 11363 llvm::Function *Fn) { 11364 switch (NDS) { 11365 case 8: 11366 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11367 OutputBecomesInput, Fn); 11368 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 11369 OutputBecomesInput, Fn); 11370 break; 11371 case 16: 11372 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11373 OutputBecomesInput, Fn); 11374 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 11375 OutputBecomesInput, Fn); 11376 break; 11377 case 32: 11378 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11379 OutputBecomesInput, Fn); 11380 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 11381 OutputBecomesInput, Fn); 11382 break; 11383 case 64: 11384 case 128: 11385 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 11386 OutputBecomesInput, Fn); 11387 break; 11388 default: 11389 llvm_unreachable("Scalar type is too wide."); 11390 } 11391 } 11392 11393 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 11394 static void emitAArch64DeclareSimdFunction( 11395 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 11396 ArrayRef<ParamAttrTy> ParamAttrs, 11397 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 11398 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 11399 11400 // Get basic data for building the vector signature. 11401 const auto Data = getNDSWDS(FD, ParamAttrs); 11402 const unsigned NDS = std::get<0>(Data); 11403 const unsigned WDS = std::get<1>(Data); 11404 const bool OutputBecomesInput = std::get<2>(Data); 11405 11406 // Check the values provided via `simdlen` by the user. 11407 // 1. A `simdlen(1)` doesn't produce vector signatures, 11408 if (UserVLEN == 1) { 11409 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11410 DiagnosticsEngine::Warning, 11411 "The clause simdlen(1) has no effect when targeting aarch64."); 11412 CGM.getDiags().Report(SLoc, DiagID); 11413 return; 11414 } 11415 11416 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 11417 // Advanced SIMD output. 11418 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 11419 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11420 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 11421 "power of 2 when targeting Advanced SIMD."); 11422 CGM.getDiags().Report(SLoc, DiagID); 11423 return; 11424 } 11425 11426 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 11427 // limits. 11428 if (ISA == 's' && UserVLEN != 0) { 11429 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 11430 unsigned DiagID = CGM.getDiags().getCustomDiagID( 11431 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 11432 "lanes in the architectural constraints " 11433 "for SVE (min is 128-bit, max is " 11434 "2048-bit, by steps of 128-bit)"); 11435 CGM.getDiags().Report(SLoc, DiagID) << WDS; 11436 return; 11437 } 11438 } 11439 11440 // Sort out parameter sequence. 11441 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 11442 StringRef Prefix = "_ZGV"; 11443 // Generate simdlen from user input (if any). 11444 if (UserVLEN) { 11445 if (ISA == 's') { 11446 // SVE generates only a masked function. 11447 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11448 OutputBecomesInput, Fn); 11449 } else { 11450 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11451 // Advanced SIMD generates one or two functions, depending on 11452 // the `[not]inbranch` clause. 11453 switch (State) { 11454 case OMPDeclareSimdDeclAttr::BS_Undefined: 11455 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11456 OutputBecomesInput, Fn); 11457 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11458 OutputBecomesInput, Fn); 11459 break; 11460 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11461 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 11462 OutputBecomesInput, Fn); 11463 break; 11464 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11465 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 11466 OutputBecomesInput, Fn); 11467 break; 11468 } 11469 } 11470 } else { 11471 // If no user simdlen is provided, follow the AAVFABI rules for 11472 // generating the vector length. 11473 if (ISA == 's') { 11474 // SVE, section 3.4.1, item 1. 11475 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 11476 OutputBecomesInput, Fn); 11477 } else { 11478 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 11479 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 11480 // two vector names depending on the use of the clause 11481 // `[not]inbranch`. 11482 switch (State) { 11483 case OMPDeclareSimdDeclAttr::BS_Undefined: 11484 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11485 OutputBecomesInput, Fn); 11486 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11487 OutputBecomesInput, Fn); 11488 break; 11489 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 11490 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 11491 OutputBecomesInput, Fn); 11492 break; 11493 case OMPDeclareSimdDeclAttr::BS_Inbranch: 11494 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 11495 OutputBecomesInput, Fn); 11496 break; 11497 } 11498 } 11499 } 11500 } 11501 11502 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 11503 llvm::Function *Fn) { 11504 ASTContext &C = CGM.getContext(); 11505 FD = FD->getMostRecentDecl(); 11506 // Map params to their positions in function decl. 11507 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 11508 if (isa<CXXMethodDecl>(FD)) 11509 ParamPositions.try_emplace(FD, 0); 11510 unsigned ParamPos = ParamPositions.size(); 11511 for (const ParmVarDecl *P : FD->parameters()) { 11512 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 11513 ++ParamPos; 11514 } 11515 while (FD) { 11516 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 11517 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 11518 // Mark uniform parameters. 11519 for (const Expr *E : Attr->uniforms()) { 11520 E = E->IgnoreParenImpCasts(); 11521 unsigned Pos; 11522 if (isa<CXXThisExpr>(E)) { 11523 Pos = ParamPositions[FD]; 11524 } else { 11525 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11526 ->getCanonicalDecl(); 11527 Pos = ParamPositions[PVD]; 11528 } 11529 ParamAttrs[Pos].Kind = Uniform; 11530 } 11531 // Get alignment info. 11532 auto NI = Attr->alignments_begin(); 11533 for (const Expr *E : Attr->aligneds()) { 11534 E = E->IgnoreParenImpCasts(); 11535 unsigned Pos; 11536 QualType ParmTy; 11537 if (isa<CXXThisExpr>(E)) { 11538 Pos = ParamPositions[FD]; 11539 ParmTy = E->getType(); 11540 } else { 11541 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11542 ->getCanonicalDecl(); 11543 Pos = ParamPositions[PVD]; 11544 ParmTy = PVD->getType(); 11545 } 11546 ParamAttrs[Pos].Alignment = 11547 (*NI) 11548 ? (*NI)->EvaluateKnownConstInt(C) 11549 : llvm::APSInt::getUnsigned( 11550 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 11551 .getQuantity()); 11552 ++NI; 11553 } 11554 // Mark linear parameters. 11555 auto SI = Attr->steps_begin(); 11556 auto MI = Attr->modifiers_begin(); 11557 for (const Expr *E : Attr->linears()) { 11558 E = E->IgnoreParenImpCasts(); 11559 unsigned Pos; 11560 // Rescaling factor needed to compute the linear parameter 11561 // value in the mangled name. 11562 unsigned PtrRescalingFactor = 1; 11563 if (isa<CXXThisExpr>(E)) { 11564 Pos = ParamPositions[FD]; 11565 } else { 11566 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11567 ->getCanonicalDecl(); 11568 Pos = ParamPositions[PVD]; 11569 if (auto *P = dyn_cast<PointerType>(PVD->getType())) 11570 PtrRescalingFactor = CGM.getContext() 11571 .getTypeSizeInChars(P->getPointeeType()) 11572 .getQuantity(); 11573 } 11574 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 11575 ParamAttr.Kind = Linear; 11576 // Assuming a stride of 1, for `linear` without modifiers. 11577 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned(1); 11578 if (*SI) { 11579 Expr::EvalResult Result; 11580 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 11581 if (const auto *DRE = 11582 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 11583 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 11584 ParamAttr.Kind = LinearWithVarStride; 11585 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 11586 ParamPositions[StridePVD->getCanonicalDecl()]); 11587 } 11588 } 11589 } else { 11590 ParamAttr.StrideOrArg = Result.Val.getInt(); 11591 } 11592 } 11593 // If we are using a linear clause on a pointer, we need to 11594 // rescale the value of linear_step with the byte size of the 11595 // pointee type. 11596 if (Linear == ParamAttr.Kind) 11597 ParamAttr.StrideOrArg = ParamAttr.StrideOrArg * PtrRescalingFactor; 11598 ++SI; 11599 ++MI; 11600 } 11601 llvm::APSInt VLENVal; 11602 SourceLocation ExprLoc; 11603 const Expr *VLENExpr = Attr->getSimdlen(); 11604 if (VLENExpr) { 11605 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 11606 ExprLoc = VLENExpr->getExprLoc(); 11607 } 11608 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 11609 if (CGM.getTriple().isX86()) { 11610 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 11611 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 11612 unsigned VLEN = VLENVal.getExtValue(); 11613 StringRef MangledName = Fn->getName(); 11614 if (CGM.getTarget().hasFeature("sve")) 11615 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11616 MangledName, 's', 128, Fn, ExprLoc); 11617 if (CGM.getTarget().hasFeature("neon")) 11618 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11619 MangledName, 'n', 128, Fn, ExprLoc); 11620 } 11621 } 11622 FD = FD->getPreviousDecl(); 11623 } 11624 } 11625 11626 namespace { 11627 /// Cleanup action for doacross support. 11628 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 11629 public: 11630 static const int DoacrossFinArgs = 2; 11631 11632 private: 11633 llvm::FunctionCallee RTLFn; 11634 llvm::Value *Args[DoacrossFinArgs]; 11635 11636 public: 11637 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 11638 ArrayRef<llvm::Value *> CallArgs) 11639 : RTLFn(RTLFn) { 11640 assert(CallArgs.size() == DoacrossFinArgs); 11641 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11642 } 11643 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11644 if (!CGF.HaveInsertPoint()) 11645 return; 11646 CGF.EmitRuntimeCall(RTLFn, Args); 11647 } 11648 }; 11649 } // namespace 11650 11651 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11652 const OMPLoopDirective &D, 11653 ArrayRef<Expr *> NumIterations) { 11654 if (!CGF.HaveInsertPoint()) 11655 return; 11656 11657 ASTContext &C = CGM.getContext(); 11658 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 11659 RecordDecl *RD; 11660 if (KmpDimTy.isNull()) { 11661 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 11662 // kmp_int64 lo; // lower 11663 // kmp_int64 up; // upper 11664 // kmp_int64 st; // stride 11665 // }; 11666 RD = C.buildImplicitRecord("kmp_dim"); 11667 RD->startDefinition(); 11668 addFieldToRecordDecl(C, RD, Int64Ty); 11669 addFieldToRecordDecl(C, RD, Int64Ty); 11670 addFieldToRecordDecl(C, RD, Int64Ty); 11671 RD->completeDefinition(); 11672 KmpDimTy = C.getRecordType(RD); 11673 } else { 11674 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 11675 } 11676 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 11677 QualType ArrayTy = 11678 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 11679 11680 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 11681 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 11682 enum { LowerFD = 0, UpperFD, StrideFD }; 11683 // Fill dims with data. 11684 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 11685 LValue DimsLVal = CGF.MakeAddrLValue( 11686 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 11687 // dims.upper = num_iterations; 11688 LValue UpperLVal = CGF.EmitLValueForField( 11689 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 11690 llvm::Value *NumIterVal = CGF.EmitScalarConversion( 11691 CGF.EmitScalarExpr(NumIterations[I]), NumIterations[I]->getType(), 11692 Int64Ty, NumIterations[I]->getExprLoc()); 11693 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 11694 // dims.stride = 1; 11695 LValue StrideLVal = CGF.EmitLValueForField( 11696 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 11697 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 11698 StrideLVal); 11699 } 11700 11701 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 11702 // kmp_int32 num_dims, struct kmp_dim * dims); 11703 llvm::Value *Args[] = { 11704 emitUpdateLocation(CGF, D.getBeginLoc()), 11705 getThreadID(CGF, D.getBeginLoc()), 11706 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 11707 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11708 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 11709 CGM.VoidPtrTy)}; 11710 11711 llvm::FunctionCallee RTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11712 CGM.getModule(), OMPRTL___kmpc_doacross_init); 11713 CGF.EmitRuntimeCall(RTLFn, Args); 11714 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 11715 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 11716 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11717 CGM.getModule(), OMPRTL___kmpc_doacross_fini); 11718 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11719 llvm::makeArrayRef(FiniArgs)); 11720 } 11721 11722 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11723 const OMPDependClause *C) { 11724 QualType Int64Ty = 11725 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 11726 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 11727 QualType ArrayTy = CGM.getContext().getConstantArrayType( 11728 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 11729 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 11730 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 11731 const Expr *CounterVal = C->getLoopData(I); 11732 assert(CounterVal); 11733 llvm::Value *CntVal = CGF.EmitScalarConversion( 11734 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 11735 CounterVal->getExprLoc()); 11736 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 11737 /*Volatile=*/false, Int64Ty); 11738 } 11739 llvm::Value *Args[] = { 11740 emitUpdateLocation(CGF, C->getBeginLoc()), 11741 getThreadID(CGF, C->getBeginLoc()), 11742 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 11743 llvm::FunctionCallee RTLFn; 11744 if (C->getDependencyKind() == OMPC_DEPEND_source) { 11745 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 11746 OMPRTL___kmpc_doacross_post); 11747 } else { 11748 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 11749 RTLFn = OMPBuilder.getOrCreateRuntimeFunction(CGM.getModule(), 11750 OMPRTL___kmpc_doacross_wait); 11751 } 11752 CGF.EmitRuntimeCall(RTLFn, Args); 11753 } 11754 11755 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 11756 llvm::FunctionCallee Callee, 11757 ArrayRef<llvm::Value *> Args) const { 11758 assert(Loc.isValid() && "Outlined function call location must be valid."); 11759 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 11760 11761 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 11762 if (Fn->doesNotThrow()) { 11763 CGF.EmitNounwindRuntimeCall(Fn, Args); 11764 return; 11765 } 11766 } 11767 CGF.EmitRuntimeCall(Callee, Args); 11768 } 11769 11770 void CGOpenMPRuntime::emitOutlinedFunctionCall( 11771 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 11772 ArrayRef<llvm::Value *> Args) const { 11773 emitCall(CGF, Loc, OutlinedFn, Args); 11774 } 11775 11776 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 11777 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 11778 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 11779 HasEmittedDeclareTargetRegion = true; 11780 } 11781 11782 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 11783 const VarDecl *NativeParam, 11784 const VarDecl *TargetParam) const { 11785 return CGF.GetAddrOfLocalVar(NativeParam); 11786 } 11787 11788 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11789 const VarDecl *VD) { 11790 if (!VD) 11791 return Address::invalid(); 11792 Address UntiedAddr = Address::invalid(); 11793 Address UntiedRealAddr = Address::invalid(); 11794 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 11795 if (It != FunctionToUntiedTaskStackMap.end()) { 11796 const UntiedLocalVarsAddressesMap &UntiedData = 11797 UntiedLocalVarsStack[It->second]; 11798 auto I = UntiedData.find(VD); 11799 if (I != UntiedData.end()) { 11800 UntiedAddr = I->second.first; 11801 UntiedRealAddr = I->second.second; 11802 } 11803 } 11804 const VarDecl *CVD = VD->getCanonicalDecl(); 11805 if (CVD->hasAttr<OMPAllocateDeclAttr>()) { 11806 // Use the default allocation. 11807 if (!isAllocatableDecl(VD)) 11808 return UntiedAddr; 11809 llvm::Value *Size; 11810 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11811 if (CVD->getType()->isVariablyModifiedType()) { 11812 Size = CGF.getTypeSize(CVD->getType()); 11813 // Align the size: ((size + align - 1) / align) * align 11814 Size = CGF.Builder.CreateNUWAdd( 11815 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11816 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11817 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11818 } else { 11819 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11820 Size = CGM.getSize(Sz.alignTo(Align)); 11821 } 11822 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11823 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 11824 assert(AA->getAllocator() && 11825 "Expected allocator expression for non-default allocator."); 11826 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11827 // According to the standard, the original allocator type is a enum 11828 // (integer). Convert to pointer type, if required. 11829 Allocator = CGF.EmitScalarConversion( 11830 Allocator, AA->getAllocator()->getType(), CGF.getContext().VoidPtrTy, 11831 AA->getAllocator()->getExprLoc()); 11832 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11833 11834 llvm::Value *Addr = 11835 CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( 11836 CGM.getModule(), OMPRTL___kmpc_alloc), 11837 Args, getName({CVD->getName(), ".void.addr"})); 11838 llvm::FunctionCallee FiniRTLFn = OMPBuilder.getOrCreateRuntimeFunction( 11839 CGM.getModule(), OMPRTL___kmpc_free); 11840 QualType Ty = CGM.getContext().getPointerType(CVD->getType()); 11841 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11842 Addr, CGF.ConvertTypeForMem(Ty), getName({CVD->getName(), ".addr"})); 11843 if (UntiedAddr.isValid()) 11844 CGF.EmitStoreOfScalar(Addr, UntiedAddr, /*Volatile=*/false, Ty); 11845 11846 // Cleanup action for allocate support. 11847 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 11848 llvm::FunctionCallee RTLFn; 11849 unsigned LocEncoding; 11850 Address Addr; 11851 const Expr *Allocator; 11852 11853 public: 11854 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, unsigned LocEncoding, 11855 Address Addr, const Expr *Allocator) 11856 : RTLFn(RTLFn), LocEncoding(LocEncoding), Addr(Addr), 11857 Allocator(Allocator) {} 11858 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11859 if (!CGF.HaveInsertPoint()) 11860 return; 11861 llvm::Value *Args[3]; 11862 Args[0] = CGF.CGM.getOpenMPRuntime().getThreadID( 11863 CGF, SourceLocation::getFromRawEncoding(LocEncoding)); 11864 Args[1] = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11865 Addr.getPointer(), CGF.VoidPtrTy); 11866 llvm::Value *AllocVal = CGF.EmitScalarExpr(Allocator); 11867 // According to the standard, the original allocator type is a enum 11868 // (integer). Convert to pointer type, if required. 11869 AllocVal = CGF.EmitScalarConversion(AllocVal, Allocator->getType(), 11870 CGF.getContext().VoidPtrTy, 11871 Allocator->getExprLoc()); 11872 Args[2] = AllocVal; 11873 11874 CGF.EmitRuntimeCall(RTLFn, Args); 11875 } 11876 }; 11877 Address VDAddr = 11878 UntiedRealAddr.isValid() ? UntiedRealAddr : Address(Addr, Align); 11879 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>( 11880 NormalAndEHCleanup, FiniRTLFn, CVD->getLocation().getRawEncoding(), 11881 VDAddr, AA->getAllocator()); 11882 if (UntiedRealAddr.isValid()) 11883 if (auto *Region = 11884 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 11885 Region->emitUntiedSwitch(CGF); 11886 return VDAddr; 11887 } 11888 return UntiedAddr; 11889 } 11890 11891 bool CGOpenMPRuntime::isLocalVarInUntiedTask(CodeGenFunction &CGF, 11892 const VarDecl *VD) const { 11893 auto It = FunctionToUntiedTaskStackMap.find(CGF.CurFn); 11894 if (It == FunctionToUntiedTaskStackMap.end()) 11895 return false; 11896 return UntiedLocalVarsStack[It->second].count(VD) > 0; 11897 } 11898 11899 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 11900 CodeGenModule &CGM, const OMPLoopDirective &S) 11901 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 11902 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11903 if (!NeedToPush) 11904 return; 11905 NontemporalDeclsSet &DS = 11906 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 11907 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 11908 for (const Stmt *Ref : C->private_refs()) { 11909 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 11910 const ValueDecl *VD; 11911 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 11912 VD = DRE->getDecl(); 11913 } else { 11914 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 11915 assert((ME->isImplicitCXXThis() || 11916 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 11917 "Expected member of current class."); 11918 VD = ME->getMemberDecl(); 11919 } 11920 DS.insert(VD); 11921 } 11922 } 11923 } 11924 11925 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 11926 if (!NeedToPush) 11927 return; 11928 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 11929 } 11930 11931 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::UntiedTaskLocalDeclsRAII( 11932 CodeGenFunction &CGF, 11933 const llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, 11934 std::pair<Address, Address>> &LocalVars) 11935 : CGM(CGF.CGM), NeedToPush(!LocalVars.empty()) { 11936 if (!NeedToPush) 11937 return; 11938 CGM.getOpenMPRuntime().FunctionToUntiedTaskStackMap.try_emplace( 11939 CGF.CurFn, CGM.getOpenMPRuntime().UntiedLocalVarsStack.size()); 11940 CGM.getOpenMPRuntime().UntiedLocalVarsStack.push_back(LocalVars); 11941 } 11942 11943 CGOpenMPRuntime::UntiedTaskLocalDeclsRAII::~UntiedTaskLocalDeclsRAII() { 11944 if (!NeedToPush) 11945 return; 11946 CGM.getOpenMPRuntime().UntiedLocalVarsStack.pop_back(); 11947 } 11948 11949 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 11950 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11951 11952 return llvm::any_of( 11953 CGM.getOpenMPRuntime().NontemporalDeclsStack, 11954 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 11955 } 11956 11957 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 11958 const OMPExecutableDirective &S, 11959 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 11960 const { 11961 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 11962 // Vars in target/task regions must be excluded completely. 11963 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 11964 isOpenMPTaskingDirective(S.getDirectiveKind())) { 11965 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11966 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 11967 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 11968 for (const CapturedStmt::Capture &Cap : CS->captures()) { 11969 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 11970 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 11971 } 11972 } 11973 // Exclude vars in private clauses. 11974 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 11975 for (const Expr *Ref : C->varlists()) { 11976 if (!Ref->getType()->isScalarType()) 11977 continue; 11978 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11979 if (!DRE) 11980 continue; 11981 NeedToCheckForLPCs.insert(DRE->getDecl()); 11982 } 11983 } 11984 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 11985 for (const Expr *Ref : C->varlists()) { 11986 if (!Ref->getType()->isScalarType()) 11987 continue; 11988 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11989 if (!DRE) 11990 continue; 11991 NeedToCheckForLPCs.insert(DRE->getDecl()); 11992 } 11993 } 11994 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11995 for (const Expr *Ref : C->varlists()) { 11996 if (!Ref->getType()->isScalarType()) 11997 continue; 11998 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11999 if (!DRE) 12000 continue; 12001 NeedToCheckForLPCs.insert(DRE->getDecl()); 12002 } 12003 } 12004 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 12005 for (const Expr *Ref : C->varlists()) { 12006 if (!Ref->getType()->isScalarType()) 12007 continue; 12008 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12009 if (!DRE) 12010 continue; 12011 NeedToCheckForLPCs.insert(DRE->getDecl()); 12012 } 12013 } 12014 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 12015 for (const Expr *Ref : C->varlists()) { 12016 if (!Ref->getType()->isScalarType()) 12017 continue; 12018 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 12019 if (!DRE) 12020 continue; 12021 NeedToCheckForLPCs.insert(DRE->getDecl()); 12022 } 12023 } 12024 for (const Decl *VD : NeedToCheckForLPCs) { 12025 for (const LastprivateConditionalData &Data : 12026 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 12027 if (Data.DeclToUniqueName.count(VD) > 0) { 12028 if (!Data.Disabled) 12029 NeedToAddForLPCsAsDisabled.insert(VD); 12030 break; 12031 } 12032 } 12033 } 12034 } 12035 12036 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12037 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 12038 : CGM(CGF.CGM), 12039 Action((CGM.getLangOpts().OpenMP >= 50 && 12040 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 12041 [](const OMPLastprivateClause *C) { 12042 return C->getKind() == 12043 OMPC_LASTPRIVATE_conditional; 12044 })) 12045 ? ActionToDo::PushAsLastprivateConditional 12046 : ActionToDo::DoNotPush) { 12047 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12048 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 12049 return; 12050 assert(Action == ActionToDo::PushAsLastprivateConditional && 12051 "Expected a push action."); 12052 LastprivateConditionalData &Data = 12053 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12054 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 12055 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 12056 continue; 12057 12058 for (const Expr *Ref : C->varlists()) { 12059 Data.DeclToUniqueName.insert(std::make_pair( 12060 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 12061 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 12062 } 12063 } 12064 Data.IVLVal = IVLVal; 12065 Data.Fn = CGF.CurFn; 12066 } 12067 12068 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 12069 CodeGenFunction &CGF, const OMPExecutableDirective &S) 12070 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 12071 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 12072 if (CGM.getLangOpts().OpenMP < 50) 12073 return; 12074 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 12075 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 12076 if (!NeedToAddForLPCsAsDisabled.empty()) { 12077 Action = ActionToDo::DisableLastprivateConditional; 12078 LastprivateConditionalData &Data = 12079 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 12080 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 12081 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 12082 Data.Fn = CGF.CurFn; 12083 Data.Disabled = true; 12084 } 12085 } 12086 12087 CGOpenMPRuntime::LastprivateConditionalRAII 12088 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 12089 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 12090 return LastprivateConditionalRAII(CGF, S); 12091 } 12092 12093 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 12094 if (CGM.getLangOpts().OpenMP < 50) 12095 return; 12096 if (Action == ActionToDo::DisableLastprivateConditional) { 12097 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12098 "Expected list of disabled private vars."); 12099 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12100 } 12101 if (Action == ActionToDo::PushAsLastprivateConditional) { 12102 assert( 12103 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 12104 "Expected list of lastprivate conditional vars."); 12105 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 12106 } 12107 } 12108 12109 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 12110 const VarDecl *VD) { 12111 ASTContext &C = CGM.getContext(); 12112 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 12113 if (I == LastprivateConditionalToTypes.end()) 12114 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 12115 QualType NewType; 12116 const FieldDecl *VDField; 12117 const FieldDecl *FiredField; 12118 LValue BaseLVal; 12119 auto VI = I->getSecond().find(VD); 12120 if (VI == I->getSecond().end()) { 12121 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 12122 RD->startDefinition(); 12123 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 12124 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 12125 RD->completeDefinition(); 12126 NewType = C.getRecordType(RD); 12127 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 12128 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 12129 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 12130 } else { 12131 NewType = std::get<0>(VI->getSecond()); 12132 VDField = std::get<1>(VI->getSecond()); 12133 FiredField = std::get<2>(VI->getSecond()); 12134 BaseLVal = std::get<3>(VI->getSecond()); 12135 } 12136 LValue FiredLVal = 12137 CGF.EmitLValueForField(BaseLVal, FiredField); 12138 CGF.EmitStoreOfScalar( 12139 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 12140 FiredLVal); 12141 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 12142 } 12143 12144 namespace { 12145 /// Checks if the lastprivate conditional variable is referenced in LHS. 12146 class LastprivateConditionalRefChecker final 12147 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 12148 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 12149 const Expr *FoundE = nullptr; 12150 const Decl *FoundD = nullptr; 12151 StringRef UniqueDeclName; 12152 LValue IVLVal; 12153 llvm::Function *FoundFn = nullptr; 12154 SourceLocation Loc; 12155 12156 public: 12157 bool VisitDeclRefExpr(const DeclRefExpr *E) { 12158 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12159 llvm::reverse(LPM)) { 12160 auto It = D.DeclToUniqueName.find(E->getDecl()); 12161 if (It == D.DeclToUniqueName.end()) 12162 continue; 12163 if (D.Disabled) 12164 return false; 12165 FoundE = E; 12166 FoundD = E->getDecl()->getCanonicalDecl(); 12167 UniqueDeclName = It->second; 12168 IVLVal = D.IVLVal; 12169 FoundFn = D.Fn; 12170 break; 12171 } 12172 return FoundE == E; 12173 } 12174 bool VisitMemberExpr(const MemberExpr *E) { 12175 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 12176 return false; 12177 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 12178 llvm::reverse(LPM)) { 12179 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 12180 if (It == D.DeclToUniqueName.end()) 12181 continue; 12182 if (D.Disabled) 12183 return false; 12184 FoundE = E; 12185 FoundD = E->getMemberDecl()->getCanonicalDecl(); 12186 UniqueDeclName = It->second; 12187 IVLVal = D.IVLVal; 12188 FoundFn = D.Fn; 12189 break; 12190 } 12191 return FoundE == E; 12192 } 12193 bool VisitStmt(const Stmt *S) { 12194 for (const Stmt *Child : S->children()) { 12195 if (!Child) 12196 continue; 12197 if (const auto *E = dyn_cast<Expr>(Child)) 12198 if (!E->isGLValue()) 12199 continue; 12200 if (Visit(Child)) 12201 return true; 12202 } 12203 return false; 12204 } 12205 explicit LastprivateConditionalRefChecker( 12206 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 12207 : LPM(LPM) {} 12208 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 12209 getFoundData() const { 12210 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 12211 } 12212 }; 12213 } // namespace 12214 12215 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 12216 LValue IVLVal, 12217 StringRef UniqueDeclName, 12218 LValue LVal, 12219 SourceLocation Loc) { 12220 // Last updated loop counter for the lastprivate conditional var. 12221 // int<xx> last_iv = 0; 12222 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 12223 llvm::Constant *LastIV = 12224 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 12225 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 12226 IVLVal.getAlignment().getAsAlign()); 12227 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 12228 12229 // Last value of the lastprivate conditional. 12230 // decltype(priv_a) last_a; 12231 llvm::Constant *Last = getOrCreateInternalVariable( 12232 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 12233 cast<llvm::GlobalVariable>(Last)->setAlignment( 12234 LVal.getAlignment().getAsAlign()); 12235 LValue LastLVal = 12236 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 12237 12238 // Global loop counter. Required to handle inner parallel-for regions. 12239 // iv 12240 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 12241 12242 // #pragma omp critical(a) 12243 // if (last_iv <= iv) { 12244 // last_iv = iv; 12245 // last_a = priv_a; 12246 // } 12247 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 12248 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 12249 Action.Enter(CGF); 12250 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 12251 // (last_iv <= iv) ? Check if the variable is updated and store new 12252 // value in global var. 12253 llvm::Value *CmpRes; 12254 if (IVLVal.getType()->isSignedIntegerType()) { 12255 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 12256 } else { 12257 assert(IVLVal.getType()->isUnsignedIntegerType() && 12258 "Loop iteration variable must be integer."); 12259 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 12260 } 12261 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 12262 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 12263 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 12264 // { 12265 CGF.EmitBlock(ThenBB); 12266 12267 // last_iv = iv; 12268 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 12269 12270 // last_a = priv_a; 12271 switch (CGF.getEvaluationKind(LVal.getType())) { 12272 case TEK_Scalar: { 12273 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 12274 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 12275 break; 12276 } 12277 case TEK_Complex: { 12278 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 12279 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 12280 break; 12281 } 12282 case TEK_Aggregate: 12283 llvm_unreachable( 12284 "Aggregates are not supported in lastprivate conditional."); 12285 } 12286 // } 12287 CGF.EmitBranch(ExitBB); 12288 // There is no need to emit line number for unconditional branch. 12289 (void)ApplyDebugLocation::CreateEmpty(CGF); 12290 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 12291 }; 12292 12293 if (CGM.getLangOpts().OpenMPSimd) { 12294 // Do not emit as a critical region as no parallel region could be emitted. 12295 RegionCodeGenTy ThenRCG(CodeGen); 12296 ThenRCG(CGF); 12297 } else { 12298 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 12299 } 12300 } 12301 12302 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 12303 const Expr *LHS) { 12304 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12305 return; 12306 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 12307 if (!Checker.Visit(LHS)) 12308 return; 12309 const Expr *FoundE; 12310 const Decl *FoundD; 12311 StringRef UniqueDeclName; 12312 LValue IVLVal; 12313 llvm::Function *FoundFn; 12314 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 12315 Checker.getFoundData(); 12316 if (FoundFn != CGF.CurFn) { 12317 // Special codegen for inner parallel regions. 12318 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 12319 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 12320 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 12321 "Lastprivate conditional is not found in outer region."); 12322 QualType StructTy = std::get<0>(It->getSecond()); 12323 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 12324 LValue PrivLVal = CGF.EmitLValue(FoundE); 12325 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 12326 PrivLVal.getAddress(CGF), 12327 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 12328 LValue BaseLVal = 12329 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 12330 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 12331 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 12332 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 12333 FiredLVal, llvm::AtomicOrdering::Unordered, 12334 /*IsVolatile=*/true, /*isInit=*/false); 12335 return; 12336 } 12337 12338 // Private address of the lastprivate conditional in the current context. 12339 // priv_a 12340 LValue LVal = CGF.EmitLValue(FoundE); 12341 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 12342 FoundE->getExprLoc()); 12343 } 12344 12345 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 12346 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12347 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 12348 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 12349 return; 12350 auto Range = llvm::reverse(LastprivateConditionalStack); 12351 auto It = llvm::find_if( 12352 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 12353 if (It == Range.end() || It->Fn != CGF.CurFn) 12354 return; 12355 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 12356 assert(LPCI != LastprivateConditionalToTypes.end() && 12357 "Lastprivates must be registered already."); 12358 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 12359 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 12360 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 12361 for (const auto &Pair : It->DeclToUniqueName) { 12362 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 12363 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 12364 continue; 12365 auto I = LPCI->getSecond().find(Pair.first); 12366 assert(I != LPCI->getSecond().end() && 12367 "Lastprivate must be rehistered already."); 12368 // bool Cmp = priv_a.Fired != 0; 12369 LValue BaseLVal = std::get<3>(I->getSecond()); 12370 LValue FiredLVal = 12371 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 12372 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 12373 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 12374 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 12375 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 12376 // if (Cmp) { 12377 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 12378 CGF.EmitBlock(ThenBB); 12379 Address Addr = CGF.GetAddrOfLocalVar(VD); 12380 LValue LVal; 12381 if (VD->getType()->isReferenceType()) 12382 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 12383 AlignmentSource::Decl); 12384 else 12385 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 12386 AlignmentSource::Decl); 12387 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 12388 D.getBeginLoc()); 12389 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 12390 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 12391 // } 12392 } 12393 } 12394 12395 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 12396 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 12397 SourceLocation Loc) { 12398 if (CGF.getLangOpts().OpenMP < 50) 12399 return; 12400 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 12401 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 12402 "Unknown lastprivate conditional variable."); 12403 StringRef UniqueName = It->second; 12404 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 12405 // The variable was not updated in the region - exit. 12406 if (!GV) 12407 return; 12408 LValue LPLVal = CGF.MakeAddrLValue( 12409 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 12410 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 12411 CGF.EmitStoreOfScalar(Res, PrivLVal); 12412 } 12413 12414 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 12415 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12416 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12417 llvm_unreachable("Not supported in SIMD-only mode"); 12418 } 12419 12420 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 12421 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12422 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 12423 llvm_unreachable("Not supported in SIMD-only mode"); 12424 } 12425 12426 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 12427 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 12428 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 12429 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 12430 bool Tied, unsigned &NumberOfParts) { 12431 llvm_unreachable("Not supported in SIMD-only mode"); 12432 } 12433 12434 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 12435 SourceLocation Loc, 12436 llvm::Function *OutlinedFn, 12437 ArrayRef<llvm::Value *> CapturedVars, 12438 const Expr *IfCond) { 12439 llvm_unreachable("Not supported in SIMD-only mode"); 12440 } 12441 12442 void CGOpenMPSIMDRuntime::emitCriticalRegion( 12443 CodeGenFunction &CGF, StringRef CriticalName, 12444 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 12445 const Expr *Hint) { 12446 llvm_unreachable("Not supported in SIMD-only mode"); 12447 } 12448 12449 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 12450 const RegionCodeGenTy &MasterOpGen, 12451 SourceLocation Loc) { 12452 llvm_unreachable("Not supported in SIMD-only mode"); 12453 } 12454 12455 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 12456 SourceLocation Loc) { 12457 llvm_unreachable("Not supported in SIMD-only mode"); 12458 } 12459 12460 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 12461 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 12462 SourceLocation Loc) { 12463 llvm_unreachable("Not supported in SIMD-only mode"); 12464 } 12465 12466 void CGOpenMPSIMDRuntime::emitSingleRegion( 12467 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 12468 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 12469 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 12470 ArrayRef<const Expr *> AssignmentOps) { 12471 llvm_unreachable("Not supported in SIMD-only mode"); 12472 } 12473 12474 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 12475 const RegionCodeGenTy &OrderedOpGen, 12476 SourceLocation Loc, 12477 bool IsThreads) { 12478 llvm_unreachable("Not supported in SIMD-only mode"); 12479 } 12480 12481 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 12482 SourceLocation Loc, 12483 OpenMPDirectiveKind Kind, 12484 bool EmitChecks, 12485 bool ForceSimpleCall) { 12486 llvm_unreachable("Not supported in SIMD-only mode"); 12487 } 12488 12489 void CGOpenMPSIMDRuntime::emitForDispatchInit( 12490 CodeGenFunction &CGF, SourceLocation Loc, 12491 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 12492 bool Ordered, const DispatchRTInput &DispatchValues) { 12493 llvm_unreachable("Not supported in SIMD-only mode"); 12494 } 12495 12496 void CGOpenMPSIMDRuntime::emitForStaticInit( 12497 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 12498 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 12499 llvm_unreachable("Not supported in SIMD-only mode"); 12500 } 12501 12502 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 12503 CodeGenFunction &CGF, SourceLocation Loc, 12504 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 12505 llvm_unreachable("Not supported in SIMD-only mode"); 12506 } 12507 12508 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 12509 SourceLocation Loc, 12510 unsigned IVSize, 12511 bool IVSigned) { 12512 llvm_unreachable("Not supported in SIMD-only mode"); 12513 } 12514 12515 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 12516 SourceLocation Loc, 12517 OpenMPDirectiveKind DKind) { 12518 llvm_unreachable("Not supported in SIMD-only mode"); 12519 } 12520 12521 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 12522 SourceLocation Loc, 12523 unsigned IVSize, bool IVSigned, 12524 Address IL, Address LB, 12525 Address UB, Address ST) { 12526 llvm_unreachable("Not supported in SIMD-only mode"); 12527 } 12528 12529 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 12530 llvm::Value *NumThreads, 12531 SourceLocation Loc) { 12532 llvm_unreachable("Not supported in SIMD-only mode"); 12533 } 12534 12535 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 12536 ProcBindKind ProcBind, 12537 SourceLocation Loc) { 12538 llvm_unreachable("Not supported in SIMD-only mode"); 12539 } 12540 12541 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 12542 const VarDecl *VD, 12543 Address VDAddr, 12544 SourceLocation Loc) { 12545 llvm_unreachable("Not supported in SIMD-only mode"); 12546 } 12547 12548 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 12549 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 12550 CodeGenFunction *CGF) { 12551 llvm_unreachable("Not supported in SIMD-only mode"); 12552 } 12553 12554 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 12555 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 12556 llvm_unreachable("Not supported in SIMD-only mode"); 12557 } 12558 12559 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 12560 ArrayRef<const Expr *> Vars, 12561 SourceLocation Loc, 12562 llvm::AtomicOrdering AO) { 12563 llvm_unreachable("Not supported in SIMD-only mode"); 12564 } 12565 12566 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 12567 const OMPExecutableDirective &D, 12568 llvm::Function *TaskFunction, 12569 QualType SharedsTy, Address Shareds, 12570 const Expr *IfCond, 12571 const OMPTaskDataTy &Data) { 12572 llvm_unreachable("Not supported in SIMD-only mode"); 12573 } 12574 12575 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 12576 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 12577 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 12578 const Expr *IfCond, const OMPTaskDataTy &Data) { 12579 llvm_unreachable("Not supported in SIMD-only mode"); 12580 } 12581 12582 void CGOpenMPSIMDRuntime::emitReduction( 12583 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 12584 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 12585 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 12586 assert(Options.SimpleReduction && "Only simple reduction is expected."); 12587 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 12588 ReductionOps, Options); 12589 } 12590 12591 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 12592 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 12593 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 12594 llvm_unreachable("Not supported in SIMD-only mode"); 12595 } 12596 12597 void CGOpenMPSIMDRuntime::emitTaskReductionFini(CodeGenFunction &CGF, 12598 SourceLocation Loc, 12599 bool IsWorksharingReduction) { 12600 llvm_unreachable("Not supported in SIMD-only mode"); 12601 } 12602 12603 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 12604 SourceLocation Loc, 12605 ReductionCodeGen &RCG, 12606 unsigned N) { 12607 llvm_unreachable("Not supported in SIMD-only mode"); 12608 } 12609 12610 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 12611 SourceLocation Loc, 12612 llvm::Value *ReductionsPtr, 12613 LValue SharedLVal) { 12614 llvm_unreachable("Not supported in SIMD-only mode"); 12615 } 12616 12617 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 12618 SourceLocation Loc) { 12619 llvm_unreachable("Not supported in SIMD-only mode"); 12620 } 12621 12622 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 12623 CodeGenFunction &CGF, SourceLocation Loc, 12624 OpenMPDirectiveKind CancelRegion) { 12625 llvm_unreachable("Not supported in SIMD-only mode"); 12626 } 12627 12628 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 12629 SourceLocation Loc, const Expr *IfCond, 12630 OpenMPDirectiveKind CancelRegion) { 12631 llvm_unreachable("Not supported in SIMD-only mode"); 12632 } 12633 12634 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 12635 const OMPExecutableDirective &D, StringRef ParentName, 12636 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 12637 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 12638 llvm_unreachable("Not supported in SIMD-only mode"); 12639 } 12640 12641 void CGOpenMPSIMDRuntime::emitTargetCall( 12642 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12643 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 12644 llvm::PointerIntPair<const Expr *, 2, OpenMPDeviceClauseModifier> Device, 12645 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 12646 const OMPLoopDirective &D)> 12647 SizeEmitter) { 12648 llvm_unreachable("Not supported in SIMD-only mode"); 12649 } 12650 12651 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 12652 llvm_unreachable("Not supported in SIMD-only mode"); 12653 } 12654 12655 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 12656 llvm_unreachable("Not supported in SIMD-only mode"); 12657 } 12658 12659 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 12660 return false; 12661 } 12662 12663 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 12664 const OMPExecutableDirective &D, 12665 SourceLocation Loc, 12666 llvm::Function *OutlinedFn, 12667 ArrayRef<llvm::Value *> CapturedVars) { 12668 llvm_unreachable("Not supported in SIMD-only mode"); 12669 } 12670 12671 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 12672 const Expr *NumTeams, 12673 const Expr *ThreadLimit, 12674 SourceLocation Loc) { 12675 llvm_unreachable("Not supported in SIMD-only mode"); 12676 } 12677 12678 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 12679 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12680 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 12681 llvm_unreachable("Not supported in SIMD-only mode"); 12682 } 12683 12684 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 12685 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12686 const Expr *Device) { 12687 llvm_unreachable("Not supported in SIMD-only mode"); 12688 } 12689 12690 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12691 const OMPLoopDirective &D, 12692 ArrayRef<Expr *> NumIterations) { 12693 llvm_unreachable("Not supported in SIMD-only mode"); 12694 } 12695 12696 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12697 const OMPDependClause *C) { 12698 llvm_unreachable("Not supported in SIMD-only mode"); 12699 } 12700 12701 const VarDecl * 12702 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 12703 const VarDecl *NativeParam) const { 12704 llvm_unreachable("Not supported in SIMD-only mode"); 12705 } 12706 12707 Address 12708 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 12709 const VarDecl *NativeParam, 12710 const VarDecl *TargetParam) const { 12711 llvm_unreachable("Not supported in SIMD-only mode"); 12712 } 12713