1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides a class for OpenMP runtime code generation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGOpenMPRuntime.h" 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/AST/Attr.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/OpenMPClause.h" 21 #include "clang/AST/StmtOpenMP.h" 22 #include "clang/AST/StmtVisitor.h" 23 #include "clang/Basic/BitmaskEnum.h" 24 #include "clang/Basic/FileManager.h" 25 #include "clang/Basic/OpenMPKinds.h" 26 #include "clang/Basic/SourceManager.h" 27 #include "clang/CodeGen/ConstantInitBuilder.h" 28 #include "llvm/ADT/ArrayRef.h" 29 #include "llvm/ADT/SetOperations.h" 30 #include "llvm/ADT/StringExtras.h" 31 #include "llvm/Bitcode/BitcodeReader.h" 32 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 33 #include "llvm/IR/Constants.h" 34 #include "llvm/IR/DerivedTypes.h" 35 #include "llvm/IR/GlobalValue.h" 36 #include "llvm/IR/Value.h" 37 #include "llvm/Support/AtomicOrdering.h" 38 #include "llvm/Support/Format.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include <cassert> 41 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.EmitBranchThroughCleanup(CGF.ReturnBlock); 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 enum OpenMPRTLFunction { 572 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 573 /// kmpc_micro microtask, ...); 574 OMPRTL__kmpc_fork_call, 575 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 576 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 577 OMPRTL__kmpc_threadprivate_cached, 578 /// Call to void __kmpc_threadprivate_register( ident_t *, 579 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 580 OMPRTL__kmpc_threadprivate_register, 581 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 582 OMPRTL__kmpc_global_thread_num, 583 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 584 // kmp_critical_name *crit); 585 OMPRTL__kmpc_critical, 586 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 587 // global_tid, kmp_critical_name *crit, uintptr_t hint); 588 OMPRTL__kmpc_critical_with_hint, 589 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 590 // kmp_critical_name *crit); 591 OMPRTL__kmpc_end_critical, 592 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 593 // global_tid); 594 OMPRTL__kmpc_cancel_barrier, 595 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 596 OMPRTL__kmpc_barrier, 597 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 598 OMPRTL__kmpc_for_static_fini, 599 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 600 // global_tid); 601 OMPRTL__kmpc_serialized_parallel, 602 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 603 // global_tid); 604 OMPRTL__kmpc_end_serialized_parallel, 605 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 606 // kmp_int32 num_threads); 607 OMPRTL__kmpc_push_num_threads, 608 // Call to void __kmpc_flush(ident_t *loc); 609 OMPRTL__kmpc_flush, 610 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 611 OMPRTL__kmpc_master, 612 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 613 OMPRTL__kmpc_end_master, 614 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 615 // int end_part); 616 OMPRTL__kmpc_omp_taskyield, 617 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 618 OMPRTL__kmpc_single, 619 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 620 OMPRTL__kmpc_end_single, 621 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 622 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 623 // kmp_routine_entry_t *task_entry); 624 OMPRTL__kmpc_omp_task_alloc, 625 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 626 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 627 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 628 // kmp_int64 device_id); 629 OMPRTL__kmpc_omp_target_task_alloc, 630 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 631 // new_task); 632 OMPRTL__kmpc_omp_task, 633 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 634 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 635 // kmp_int32 didit); 636 OMPRTL__kmpc_copyprivate, 637 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 638 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 639 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 640 OMPRTL__kmpc_reduce, 641 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 642 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 643 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 644 // *lck); 645 OMPRTL__kmpc_reduce_nowait, 646 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 647 // kmp_critical_name *lck); 648 OMPRTL__kmpc_end_reduce, 649 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 650 // kmp_critical_name *lck); 651 OMPRTL__kmpc_end_reduce_nowait, 652 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 653 // kmp_task_t * new_task); 654 OMPRTL__kmpc_omp_task_begin_if0, 655 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 656 // kmp_task_t * new_task); 657 OMPRTL__kmpc_omp_task_complete_if0, 658 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 659 OMPRTL__kmpc_ordered, 660 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 661 OMPRTL__kmpc_end_ordered, 662 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 663 // global_tid); 664 OMPRTL__kmpc_omp_taskwait, 665 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 666 OMPRTL__kmpc_taskgroup, 667 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 668 OMPRTL__kmpc_end_taskgroup, 669 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 670 // int proc_bind); 671 OMPRTL__kmpc_push_proc_bind, 672 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 673 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 674 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 675 OMPRTL__kmpc_omp_task_with_deps, 676 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 677 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 678 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 679 OMPRTL__kmpc_omp_wait_deps, 680 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 681 // global_tid, kmp_int32 cncl_kind); 682 OMPRTL__kmpc_cancellationpoint, 683 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 684 // kmp_int32 cncl_kind); 685 OMPRTL__kmpc_cancel, 686 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 687 // kmp_int32 num_teams, kmp_int32 thread_limit); 688 OMPRTL__kmpc_push_num_teams, 689 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 690 // microtask, ...); 691 OMPRTL__kmpc_fork_teams, 692 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 693 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 694 // sched, kmp_uint64 grainsize, void *task_dup); 695 OMPRTL__kmpc_taskloop, 696 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 697 // num_dims, struct kmp_dim *dims); 698 OMPRTL__kmpc_doacross_init, 699 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 700 OMPRTL__kmpc_doacross_fini, 701 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 702 // *vec); 703 OMPRTL__kmpc_doacross_post, 704 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 705 // *vec); 706 OMPRTL__kmpc_doacross_wait, 707 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 708 // *data); 709 OMPRTL__kmpc_task_reduction_init, 710 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 711 // *d); 712 OMPRTL__kmpc_task_reduction_get_th_data, 713 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 714 OMPRTL__kmpc_alloc, 715 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 716 OMPRTL__kmpc_free, 717 718 // 719 // Offloading related calls 720 // 721 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 722 // size); 723 OMPRTL__kmpc_push_target_tripcount, 724 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 725 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 726 // *arg_types); 727 OMPRTL__tgt_target, 728 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 729 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 730 // *arg_types); 731 OMPRTL__tgt_target_nowait, 732 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 733 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 734 // *arg_types, int32_t num_teams, int32_t thread_limit); 735 OMPRTL__tgt_target_teams, 736 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 737 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 738 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 739 OMPRTL__tgt_target_teams_nowait, 740 // Call to void __tgt_register_requires(int64_t flags); 741 OMPRTL__tgt_register_requires, 742 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 743 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 744 OMPRTL__tgt_target_data_begin, 745 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 746 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 747 // *arg_types); 748 OMPRTL__tgt_target_data_begin_nowait, 749 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 750 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 751 OMPRTL__tgt_target_data_end, 752 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 753 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 754 // *arg_types); 755 OMPRTL__tgt_target_data_end_nowait, 756 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 757 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 758 OMPRTL__tgt_target_data_update, 759 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 760 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 761 // *arg_types); 762 OMPRTL__tgt_target_data_update_nowait, 763 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 764 OMPRTL__tgt_mapper_num_components, 765 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 766 // *base, void *begin, int64_t size, int64_t type); 767 OMPRTL__tgt_push_mapper_component, 768 }; 769 770 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 771 /// region. 772 class CleanupTy final : public EHScopeStack::Cleanup { 773 PrePostActionTy *Action; 774 775 public: 776 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 777 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 778 if (!CGF.HaveInsertPoint()) 779 return; 780 Action->Exit(CGF); 781 } 782 }; 783 784 } // anonymous namespace 785 786 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 787 CodeGenFunction::RunCleanupsScope Scope(CGF); 788 if (PrePostAction) { 789 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 790 Callback(CodeGen, CGF, *PrePostAction); 791 } else { 792 PrePostActionTy Action; 793 Callback(CodeGen, CGF, Action); 794 } 795 } 796 797 /// Check if the combiner is a call to UDR combiner and if it is so return the 798 /// UDR decl used for reduction. 799 static const OMPDeclareReductionDecl * 800 getReductionInit(const Expr *ReductionOp) { 801 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 802 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 803 if (const auto *DRE = 804 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 805 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 806 return DRD; 807 return nullptr; 808 } 809 810 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 811 const OMPDeclareReductionDecl *DRD, 812 const Expr *InitOp, 813 Address Private, Address Original, 814 QualType Ty) { 815 if (DRD->getInitializer()) { 816 std::pair<llvm::Function *, llvm::Function *> Reduction = 817 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 818 const auto *CE = cast<CallExpr>(InitOp); 819 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 820 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 821 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 822 const auto *LHSDRE = 823 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 824 const auto *RHSDRE = 825 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 826 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 827 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 828 [=]() { return Private; }); 829 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 830 [=]() { return Original; }); 831 (void)PrivateScope.Privatize(); 832 RValue Func = RValue::get(Reduction.second); 833 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 834 CGF.EmitIgnoredExpr(InitOp); 835 } else { 836 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 837 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 838 auto *GV = new llvm::GlobalVariable( 839 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 840 llvm::GlobalValue::PrivateLinkage, Init, Name); 841 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 842 RValue InitRVal; 843 switch (CGF.getEvaluationKind(Ty)) { 844 case TEK_Scalar: 845 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 846 break; 847 case TEK_Complex: 848 InitRVal = 849 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 850 break; 851 case TEK_Aggregate: 852 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 853 break; 854 } 855 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 856 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 857 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 858 /*IsInitializer=*/false); 859 } 860 } 861 862 /// Emit initialization of arrays of complex types. 863 /// \param DestAddr Address of the array. 864 /// \param Type Type of array. 865 /// \param Init Initial expression of array. 866 /// \param SrcAddr Address of the original array. 867 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 868 QualType Type, bool EmitDeclareReductionInit, 869 const Expr *Init, 870 const OMPDeclareReductionDecl *DRD, 871 Address SrcAddr = Address::invalid()) { 872 // Perform element-by-element initialization. 873 QualType ElementTy; 874 875 // Drill down to the base element type on both arrays. 876 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 877 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 878 DestAddr = 879 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 880 if (DRD) 881 SrcAddr = 882 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 883 884 llvm::Value *SrcBegin = nullptr; 885 if (DRD) 886 SrcBegin = SrcAddr.getPointer(); 887 llvm::Value *DestBegin = DestAddr.getPointer(); 888 // Cast from pointer to array type to pointer to single element. 889 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 890 // The basic structure here is a while-do loop. 891 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 892 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 893 llvm::Value *IsEmpty = 894 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 895 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 896 897 // Enter the loop body, making that address the current address. 898 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 899 CGF.EmitBlock(BodyBB); 900 901 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 902 903 llvm::PHINode *SrcElementPHI = nullptr; 904 Address SrcElementCurrent = Address::invalid(); 905 if (DRD) { 906 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 907 "omp.arraycpy.srcElementPast"); 908 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 909 SrcElementCurrent = 910 Address(SrcElementPHI, 911 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 912 } 913 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 914 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 915 DestElementPHI->addIncoming(DestBegin, EntryBB); 916 Address DestElementCurrent = 917 Address(DestElementPHI, 918 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 919 920 // Emit copy. 921 { 922 CodeGenFunction::RunCleanupsScope InitScope(CGF); 923 if (EmitDeclareReductionInit) { 924 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 925 SrcElementCurrent, ElementTy); 926 } else 927 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 928 /*IsInitializer=*/false); 929 } 930 931 if (DRD) { 932 // Shift the address forward by one element. 933 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 934 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 935 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 936 } 937 938 // Shift the address forward by one element. 939 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 940 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 941 // Check whether we've reached the end. 942 llvm::Value *Done = 943 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 944 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 945 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 946 947 // Done. 948 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 949 } 950 951 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 952 return CGF.EmitOMPSharedLValue(E); 953 } 954 955 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 956 const Expr *E) { 957 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 958 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 959 return LValue(); 960 } 961 962 void ReductionCodeGen::emitAggregateInitialization( 963 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 964 const OMPDeclareReductionDecl *DRD) { 965 // Emit VarDecl with copy init for arrays. 966 // Get the address of the original variable captured in current 967 // captured region. 968 const auto *PrivateVD = 969 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 970 bool EmitDeclareReductionInit = 971 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 972 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 973 EmitDeclareReductionInit, 974 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 975 : PrivateVD->getInit(), 976 DRD, SharedLVal.getAddress(CGF)); 977 } 978 979 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 980 ArrayRef<const Expr *> Privates, 981 ArrayRef<const Expr *> ReductionOps) { 982 ClausesData.reserve(Shareds.size()); 983 SharedAddresses.reserve(Shareds.size()); 984 Sizes.reserve(Shareds.size()); 985 BaseDecls.reserve(Shareds.size()); 986 auto IPriv = Privates.begin(); 987 auto IRed = ReductionOps.begin(); 988 for (const Expr *Ref : Shareds) { 989 ClausesData.emplace_back(Ref, *IPriv, *IRed); 990 std::advance(IPriv, 1); 991 std::advance(IRed, 1); 992 } 993 } 994 995 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 996 assert(SharedAddresses.size() == N && 997 "Number of generated lvalues must be exactly N."); 998 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 999 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 1000 SharedAddresses.emplace_back(First, Second); 1001 } 1002 1003 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 1004 const auto *PrivateVD = 1005 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1006 QualType PrivateType = PrivateVD->getType(); 1007 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1008 if (!PrivateType->isVariablyModifiedType()) { 1009 Sizes.emplace_back( 1010 CGF.getTypeSize( 1011 SharedAddresses[N].first.getType().getNonReferenceType()), 1012 nullptr); 1013 return; 1014 } 1015 llvm::Value *Size; 1016 llvm::Value *SizeInChars; 1017 auto *ElemType = cast<llvm::PointerType>( 1018 SharedAddresses[N].first.getPointer(CGF)->getType()) 1019 ->getElementType(); 1020 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1021 if (AsArraySection) { 1022 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF), 1023 SharedAddresses[N].first.getPointer(CGF)); 1024 Size = CGF.Builder.CreateNUWAdd( 1025 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1026 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1027 } else { 1028 SizeInChars = CGF.getTypeSize( 1029 SharedAddresses[N].first.getType().getNonReferenceType()); 1030 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1031 } 1032 Sizes.emplace_back(SizeInChars, Size); 1033 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1034 CGF, 1035 cast<OpaqueValueExpr>( 1036 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1037 RValue::get(Size)); 1038 CGF.EmitVariablyModifiedType(PrivateType); 1039 } 1040 1041 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1042 llvm::Value *Size) { 1043 const auto *PrivateVD = 1044 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1045 QualType PrivateType = PrivateVD->getType(); 1046 if (!PrivateType->isVariablyModifiedType()) { 1047 assert(!Size && !Sizes[N].second && 1048 "Size should be nullptr for non-variably modified reduction " 1049 "items."); 1050 return; 1051 } 1052 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1053 CGF, 1054 cast<OpaqueValueExpr>( 1055 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1056 RValue::get(Size)); 1057 CGF.EmitVariablyModifiedType(PrivateType); 1058 } 1059 1060 void ReductionCodeGen::emitInitialization( 1061 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1062 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1063 assert(SharedAddresses.size() > N && "No variable was generated"); 1064 const auto *PrivateVD = 1065 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1066 const OMPDeclareReductionDecl *DRD = 1067 getReductionInit(ClausesData[N].ReductionOp); 1068 QualType PrivateType = PrivateVD->getType(); 1069 PrivateAddr = CGF.Builder.CreateElementBitCast( 1070 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1071 QualType SharedType = SharedAddresses[N].first.getType(); 1072 SharedLVal = CGF.MakeAddrLValue( 1073 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 1074 CGF.ConvertTypeForMem(SharedType)), 1075 SharedType, SharedAddresses[N].first.getBaseInfo(), 1076 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1077 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1078 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1079 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1080 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1081 PrivateAddr, SharedLVal.getAddress(CGF), 1082 SharedLVal.getType()); 1083 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1084 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1085 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1086 PrivateVD->getType().getQualifiers(), 1087 /*IsInitializer=*/false); 1088 } 1089 } 1090 1091 bool ReductionCodeGen::needCleanups(unsigned N) { 1092 const auto *PrivateVD = 1093 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1094 QualType PrivateType = PrivateVD->getType(); 1095 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1096 return DTorKind != QualType::DK_none; 1097 } 1098 1099 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1100 Address PrivateAddr) { 1101 const auto *PrivateVD = 1102 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1103 QualType PrivateType = PrivateVD->getType(); 1104 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1105 if (needCleanups(N)) { 1106 PrivateAddr = CGF.Builder.CreateElementBitCast( 1107 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1108 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1109 } 1110 } 1111 1112 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1113 LValue BaseLV) { 1114 BaseTy = BaseTy.getNonReferenceType(); 1115 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1116 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1117 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1118 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 1119 } else { 1120 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 1121 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1122 } 1123 BaseTy = BaseTy->getPointeeType(); 1124 } 1125 return CGF.MakeAddrLValue( 1126 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 1127 CGF.ConvertTypeForMem(ElTy)), 1128 BaseLV.getType(), BaseLV.getBaseInfo(), 1129 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1130 } 1131 1132 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1133 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1134 llvm::Value *Addr) { 1135 Address Tmp = Address::invalid(); 1136 Address TopTmp = Address::invalid(); 1137 Address MostTopTmp = Address::invalid(); 1138 BaseTy = BaseTy.getNonReferenceType(); 1139 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1140 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1141 Tmp = CGF.CreateMemTemp(BaseTy); 1142 if (TopTmp.isValid()) 1143 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1144 else 1145 MostTopTmp = Tmp; 1146 TopTmp = Tmp; 1147 BaseTy = BaseTy->getPointeeType(); 1148 } 1149 llvm::Type *Ty = BaseLVType; 1150 if (Tmp.isValid()) 1151 Ty = Tmp.getElementType(); 1152 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1153 if (Tmp.isValid()) { 1154 CGF.Builder.CreateStore(Addr, Tmp); 1155 return MostTopTmp; 1156 } 1157 return Address(Addr, BaseLVAlignment); 1158 } 1159 1160 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1161 const VarDecl *OrigVD = nullptr; 1162 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1163 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1164 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1165 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1166 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1167 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1168 DE = cast<DeclRefExpr>(Base); 1169 OrigVD = cast<VarDecl>(DE->getDecl()); 1170 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1171 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1172 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1173 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1174 DE = cast<DeclRefExpr>(Base); 1175 OrigVD = cast<VarDecl>(DE->getDecl()); 1176 } 1177 return OrigVD; 1178 } 1179 1180 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1181 Address PrivateAddr) { 1182 const DeclRefExpr *DE; 1183 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1184 BaseDecls.emplace_back(OrigVD); 1185 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1186 LValue BaseLValue = 1187 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1188 OriginalBaseLValue); 1189 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1190 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1191 llvm::Value *PrivatePointer = 1192 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1193 PrivateAddr.getPointer(), 1194 SharedAddresses[N].first.getAddress(CGF).getType()); 1195 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1196 return castToBase(CGF, OrigVD->getType(), 1197 SharedAddresses[N].first.getType(), 1198 OriginalBaseLValue.getAddress(CGF).getType(), 1199 OriginalBaseLValue.getAlignment(), Ptr); 1200 } 1201 BaseDecls.emplace_back( 1202 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1203 return PrivateAddr; 1204 } 1205 1206 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1207 const OMPDeclareReductionDecl *DRD = 1208 getReductionInit(ClausesData[N].ReductionOp); 1209 return DRD && DRD->getInitializer(); 1210 } 1211 1212 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1213 return CGF.EmitLoadOfPointerLValue( 1214 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1215 getThreadIDVariable()->getType()->castAs<PointerType>()); 1216 } 1217 1218 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1219 if (!CGF.HaveInsertPoint()) 1220 return; 1221 // 1.2.2 OpenMP Language Terminology 1222 // Structured block - An executable statement with a single entry at the 1223 // top and a single exit at the bottom. 1224 // The point of exit cannot be a branch out of the structured block. 1225 // longjmp() and throw() must not violate the entry/exit criteria. 1226 CGF.EHStack.pushTerminate(); 1227 CodeGen(CGF); 1228 CGF.EHStack.popTerminate(); 1229 } 1230 1231 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1232 CodeGenFunction &CGF) { 1233 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1234 getThreadIDVariable()->getType(), 1235 AlignmentSource::Decl); 1236 } 1237 1238 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1239 QualType FieldTy) { 1240 auto *Field = FieldDecl::Create( 1241 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1242 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1243 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1244 Field->setAccess(AS_public); 1245 DC->addDecl(Field); 1246 return Field; 1247 } 1248 1249 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1250 StringRef Separator) 1251 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1252 OffloadEntriesInfoManager(CGM) { 1253 ASTContext &C = CGM.getContext(); 1254 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1255 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1256 RD->startDefinition(); 1257 // reserved_1 1258 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1259 // flags 1260 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1261 // reserved_2 1262 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1263 // reserved_3 1264 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1265 // psource 1266 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1267 RD->completeDefinition(); 1268 IdentQTy = C.getRecordType(RD); 1269 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1270 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1271 1272 loadOffloadInfoMetadata(); 1273 } 1274 1275 bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD, 1276 const GlobalDecl &OldGD, 1277 llvm::GlobalValue *OrigAddr, 1278 bool IsForDefinition) { 1279 // Emit at least a definition for the aliasee if the the address of the 1280 // original function is requested. 1281 if (IsForDefinition || OrigAddr) 1282 (void)CGM.GetAddrOfGlobal(NewGD); 1283 StringRef NewMangledName = CGM.getMangledName(NewGD); 1284 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1285 if (Addr && !Addr->isDeclaration()) { 1286 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1287 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(NewGD); 1288 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1289 1290 // Create a reference to the named value. This ensures that it is emitted 1291 // if a deferred decl. 1292 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1293 1294 // Create the new alias itself, but don't set a name yet. 1295 auto *GA = 1296 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1297 1298 if (OrigAddr) { 1299 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1300 1301 GA->takeName(OrigAddr); 1302 OrigAddr->replaceAllUsesWith( 1303 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1304 OrigAddr->eraseFromParent(); 1305 } else { 1306 GA->setName(CGM.getMangledName(OldGD)); 1307 } 1308 1309 // Set attributes which are particular to an alias; this is a 1310 // specialization of the attributes which may be set on a global function. 1311 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1312 D->isWeakImported()) 1313 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1314 1315 CGM.SetCommonAttributes(OldGD, GA); 1316 return true; 1317 } 1318 return false; 1319 } 1320 1321 void CGOpenMPRuntime::clear() { 1322 InternalVars.clear(); 1323 // Clean non-target variable declarations possibly used only in debug info. 1324 for (const auto &Data : EmittedNonTargetVariables) { 1325 if (!Data.getValue().pointsToAliveValue()) 1326 continue; 1327 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1328 if (!GV) 1329 continue; 1330 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1331 continue; 1332 GV->eraseFromParent(); 1333 } 1334 // Emit aliases for the deferred aliasees. 1335 for (const auto &Pair : DeferredVariantFunction) { 1336 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1337 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1338 // If not able to emit alias, just emit original declaration. 1339 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr, 1340 /*IsForDefinition=*/false); 1341 } 1342 } 1343 1344 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1345 SmallString<128> Buffer; 1346 llvm::raw_svector_ostream OS(Buffer); 1347 StringRef Sep = FirstSeparator; 1348 for (StringRef Part : Parts) { 1349 OS << Sep << Part; 1350 Sep = Separator; 1351 } 1352 return std::string(OS.str()); 1353 } 1354 1355 static llvm::Function * 1356 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1357 const Expr *CombinerInitializer, const VarDecl *In, 1358 const VarDecl *Out, bool IsCombiner) { 1359 // void .omp_combiner.(Ty *in, Ty *out); 1360 ASTContext &C = CGM.getContext(); 1361 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1362 FunctionArgList Args; 1363 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1364 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1365 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1366 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1367 Args.push_back(&OmpOutParm); 1368 Args.push_back(&OmpInParm); 1369 const CGFunctionInfo &FnInfo = 1370 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1371 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1372 std::string Name = CGM.getOpenMPRuntime().getName( 1373 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1374 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1375 Name, &CGM.getModule()); 1376 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1377 if (CGM.getLangOpts().Optimize) { 1378 Fn->removeFnAttr(llvm::Attribute::NoInline); 1379 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1380 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1381 } 1382 CodeGenFunction CGF(CGM); 1383 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1384 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1385 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1386 Out->getLocation()); 1387 CodeGenFunction::OMPPrivateScope Scope(CGF); 1388 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1389 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1390 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1391 .getAddress(CGF); 1392 }); 1393 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1394 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1395 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1396 .getAddress(CGF); 1397 }); 1398 (void)Scope.Privatize(); 1399 if (!IsCombiner && Out->hasInit() && 1400 !CGF.isTrivialInitializer(Out->getInit())) { 1401 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1402 Out->getType().getQualifiers(), 1403 /*IsInitializer=*/true); 1404 } 1405 if (CombinerInitializer) 1406 CGF.EmitIgnoredExpr(CombinerInitializer); 1407 Scope.ForceCleanup(); 1408 CGF.FinishFunction(); 1409 return Fn; 1410 } 1411 1412 void CGOpenMPRuntime::emitUserDefinedReduction( 1413 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1414 if (UDRMap.count(D) > 0) 1415 return; 1416 llvm::Function *Combiner = emitCombinerOrInitializer( 1417 CGM, D->getType(), D->getCombiner(), 1418 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1419 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1420 /*IsCombiner=*/true); 1421 llvm::Function *Initializer = nullptr; 1422 if (const Expr *Init = D->getInitializer()) { 1423 Initializer = emitCombinerOrInitializer( 1424 CGM, D->getType(), 1425 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1426 : nullptr, 1427 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1428 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1429 /*IsCombiner=*/false); 1430 } 1431 UDRMap.try_emplace(D, Combiner, Initializer); 1432 if (CGF) { 1433 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1434 Decls.second.push_back(D); 1435 } 1436 } 1437 1438 std::pair<llvm::Function *, llvm::Function *> 1439 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1440 auto I = UDRMap.find(D); 1441 if (I != UDRMap.end()) 1442 return I->second; 1443 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1444 return UDRMap.lookup(D); 1445 } 1446 1447 namespace { 1448 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1449 // Builder if one is present. 1450 struct PushAndPopStackRAII { 1451 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1452 bool HasCancel) 1453 : OMPBuilder(OMPBuilder) { 1454 if (!OMPBuilder) 1455 return; 1456 1457 // The following callback is the crucial part of clangs cleanup process. 1458 // 1459 // NOTE: 1460 // Once the OpenMPIRBuilder is used to create parallel regions (and 1461 // similar), the cancellation destination (Dest below) is determined via 1462 // IP. That means if we have variables to finalize we split the block at IP, 1463 // use the new block (=BB) as destination to build a JumpDest (via 1464 // getJumpDestInCurrentScope(BB)) which then is fed to 1465 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1466 // to push & pop an FinalizationInfo object. 1467 // The FiniCB will still be needed but at the point where the 1468 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1469 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1470 assert(IP.getBlock()->end() == IP.getPoint() && 1471 "Clang CG should cause non-terminated block!"); 1472 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1473 CGF.Builder.restoreIP(IP); 1474 CodeGenFunction::JumpDest Dest = 1475 CGF.getOMPCancelDestination(OMPD_parallel); 1476 CGF.EmitBranchThroughCleanup(Dest); 1477 }; 1478 1479 // TODO: Remove this once we emit parallel regions through the 1480 // OpenMPIRBuilder as it can do this setup internally. 1481 llvm::OpenMPIRBuilder::FinalizationInfo FI( 1482 {FiniCB, OMPD_parallel, HasCancel}); 1483 OMPBuilder->pushFinalizationCB(std::move(FI)); 1484 } 1485 ~PushAndPopStackRAII() { 1486 if (OMPBuilder) 1487 OMPBuilder->popFinalizationCB(); 1488 } 1489 llvm::OpenMPIRBuilder *OMPBuilder; 1490 }; 1491 } // namespace 1492 1493 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1494 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1495 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1496 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1497 assert(ThreadIDVar->getType()->isPointerType() && 1498 "thread id variable must be of type kmp_int32 *"); 1499 CodeGenFunction CGF(CGM, true); 1500 bool HasCancel = false; 1501 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1502 HasCancel = OPD->hasCancel(); 1503 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1504 HasCancel = OPSD->hasCancel(); 1505 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1506 HasCancel = OPFD->hasCancel(); 1507 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1508 HasCancel = OPFD->hasCancel(); 1509 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1510 HasCancel = OPFD->hasCancel(); 1511 else if (const auto *OPFD = 1512 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1513 HasCancel = OPFD->hasCancel(); 1514 else if (const auto *OPFD = 1515 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1516 HasCancel = OPFD->hasCancel(); 1517 1518 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1519 // parallel region to make cancellation barriers work properly. 1520 llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder(); 1521 PushAndPopStackRAII PSR(OMPBuilder, CGF, HasCancel); 1522 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1523 HasCancel, OutlinedHelperName); 1524 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1525 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1526 } 1527 1528 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1529 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1530 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1531 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1532 return emitParallelOrTeamsOutlinedFunction( 1533 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1534 } 1535 1536 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1537 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1538 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1539 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1540 return emitParallelOrTeamsOutlinedFunction( 1541 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1542 } 1543 1544 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1545 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1546 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1547 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1548 bool Tied, unsigned &NumberOfParts) { 1549 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1550 PrePostActionTy &) { 1551 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1552 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1553 llvm::Value *TaskArgs[] = { 1554 UpLoc, ThreadID, 1555 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1556 TaskTVar->getType()->castAs<PointerType>()) 1557 .getPointer(CGF)}; 1558 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1559 }; 1560 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1561 UntiedCodeGen); 1562 CodeGen.setAction(Action); 1563 assert(!ThreadIDVar->getType()->isPointerType() && 1564 "thread id variable must be of type kmp_int32 for tasks"); 1565 const OpenMPDirectiveKind Region = 1566 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1567 : OMPD_task; 1568 const CapturedStmt *CS = D.getCapturedStmt(Region); 1569 bool HasCancel = false; 1570 if (const auto *TD = dyn_cast<OMPTaskDirective>(&D)) 1571 HasCancel = TD->hasCancel(); 1572 else if (const auto *TD = dyn_cast<OMPTaskLoopDirective>(&D)) 1573 HasCancel = TD->hasCancel(); 1574 else if (const auto *TD = dyn_cast<OMPMasterTaskLoopDirective>(&D)) 1575 HasCancel = TD->hasCancel(); 1576 else if (const auto *TD = dyn_cast<OMPParallelMasterTaskLoopDirective>(&D)) 1577 HasCancel = TD->hasCancel(); 1578 1579 CodeGenFunction CGF(CGM, true); 1580 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1581 InnermostKind, HasCancel, Action); 1582 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1583 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1584 if (!Tied) 1585 NumberOfParts = Action.getNumberOfParts(); 1586 return Res; 1587 } 1588 1589 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1590 const RecordDecl *RD, const CGRecordLayout &RL, 1591 ArrayRef<llvm::Constant *> Data) { 1592 llvm::StructType *StructTy = RL.getLLVMType(); 1593 unsigned PrevIdx = 0; 1594 ConstantInitBuilder CIBuilder(CGM); 1595 auto DI = Data.begin(); 1596 for (const FieldDecl *FD : RD->fields()) { 1597 unsigned Idx = RL.getLLVMFieldNo(FD); 1598 // Fill the alignment. 1599 for (unsigned I = PrevIdx; I < Idx; ++I) 1600 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1601 PrevIdx = Idx + 1; 1602 Fields.add(*DI); 1603 ++DI; 1604 } 1605 } 1606 1607 template <class... As> 1608 static llvm::GlobalVariable * 1609 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1610 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1611 As &&... Args) { 1612 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1613 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1614 ConstantInitBuilder CIBuilder(CGM); 1615 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1616 buildStructValue(Fields, CGM, RD, RL, Data); 1617 return Fields.finishAndCreateGlobal( 1618 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1619 std::forward<As>(Args)...); 1620 } 1621 1622 template <typename T> 1623 static void 1624 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1625 ArrayRef<llvm::Constant *> Data, 1626 T &Parent) { 1627 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1628 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1629 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1630 buildStructValue(Fields, CGM, RD, RL, Data); 1631 Fields.finishAndAddTo(Parent); 1632 } 1633 1634 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1635 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1636 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1637 FlagsTy FlagsKey(Flags, Reserved2Flags); 1638 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1639 if (!Entry) { 1640 if (!DefaultOpenMPPSource) { 1641 // Initialize default location for psource field of ident_t structure of 1642 // all ident_t objects. Format is ";file;function;line;column;;". 1643 // Taken from 1644 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1645 DefaultOpenMPPSource = 1646 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1647 DefaultOpenMPPSource = 1648 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1649 } 1650 1651 llvm::Constant *Data[] = { 1652 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1653 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1654 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1655 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1656 llvm::GlobalValue *DefaultOpenMPLocation = 1657 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1658 llvm::GlobalValue::PrivateLinkage); 1659 DefaultOpenMPLocation->setUnnamedAddr( 1660 llvm::GlobalValue::UnnamedAddr::Global); 1661 1662 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1663 } 1664 return Address(Entry, Align); 1665 } 1666 1667 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1668 bool AtCurrentPoint) { 1669 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1670 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1671 1672 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1673 if (AtCurrentPoint) { 1674 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1675 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1676 } else { 1677 Elem.second.ServiceInsertPt = 1678 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1679 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1680 } 1681 } 1682 1683 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1684 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1685 if (Elem.second.ServiceInsertPt) { 1686 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1687 Elem.second.ServiceInsertPt = nullptr; 1688 Ptr->eraseFromParent(); 1689 } 1690 } 1691 1692 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1693 SourceLocation Loc, 1694 unsigned Flags) { 1695 Flags |= OMP_IDENT_KMPC; 1696 // If no debug info is generated - return global default location. 1697 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1698 Loc.isInvalid()) 1699 return getOrCreateDefaultLocation(Flags).getPointer(); 1700 1701 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1702 1703 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1704 Address LocValue = Address::invalid(); 1705 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1706 if (I != OpenMPLocThreadIDMap.end()) 1707 LocValue = Address(I->second.DebugLoc, Align); 1708 1709 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1710 // GetOpenMPThreadID was called before this routine. 1711 if (!LocValue.isValid()) { 1712 // Generate "ident_t .kmpc_loc.addr;" 1713 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1714 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1715 Elem.second.DebugLoc = AI.getPointer(); 1716 LocValue = AI; 1717 1718 if (!Elem.second.ServiceInsertPt) 1719 setLocThreadIdInsertPt(CGF); 1720 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1721 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1722 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1723 CGF.getTypeSize(IdentQTy)); 1724 } 1725 1726 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1727 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1728 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1729 LValue PSource = 1730 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1731 1732 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1733 if (OMPDebugLoc == nullptr) { 1734 SmallString<128> Buffer2; 1735 llvm::raw_svector_ostream OS2(Buffer2); 1736 // Build debug location 1737 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1738 OS2 << ";" << PLoc.getFilename() << ";"; 1739 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1740 OS2 << FD->getQualifiedNameAsString(); 1741 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1742 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1743 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1744 } 1745 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1746 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1747 1748 // Our callers always pass this to a runtime function, so for 1749 // convenience, go ahead and return a naked pointer. 1750 return LocValue.getPointer(); 1751 } 1752 1753 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1754 SourceLocation Loc) { 1755 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1756 1757 llvm::Value *ThreadID = nullptr; 1758 // Check whether we've already cached a load of the thread id in this 1759 // function. 1760 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1761 if (I != OpenMPLocThreadIDMap.end()) { 1762 ThreadID = I->second.ThreadID; 1763 if (ThreadID != nullptr) 1764 return ThreadID; 1765 } 1766 // If exceptions are enabled, do not use parameter to avoid possible crash. 1767 if (auto *OMPRegionInfo = 1768 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1769 if (OMPRegionInfo->getThreadIDVariable()) { 1770 // Check if this an outlined function with thread id passed as argument. 1771 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1772 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1773 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1774 !CGF.getLangOpts().CXXExceptions || 1775 CGF.Builder.GetInsertBlock() == TopBlock || 1776 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1777 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1778 TopBlock || 1779 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1780 CGF.Builder.GetInsertBlock()) { 1781 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1782 // If value loaded in entry block, cache it and use it everywhere in 1783 // function. 1784 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1785 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1786 Elem.second.ThreadID = ThreadID; 1787 } 1788 return ThreadID; 1789 } 1790 } 1791 } 1792 1793 // This is not an outlined function region - need to call __kmpc_int32 1794 // kmpc_global_thread_num(ident_t *loc). 1795 // Generate thread id value and cache this value for use across the 1796 // function. 1797 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1798 if (!Elem.second.ServiceInsertPt) 1799 setLocThreadIdInsertPt(CGF); 1800 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1801 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1802 llvm::CallInst *Call = CGF.Builder.CreateCall( 1803 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1804 emitUpdateLocation(CGF, Loc)); 1805 Call->setCallingConv(CGF.getRuntimeCC()); 1806 Elem.second.ThreadID = Call; 1807 return Call; 1808 } 1809 1810 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1811 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1812 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1813 clearLocThreadIdInsertPt(CGF); 1814 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1815 } 1816 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1817 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1818 UDRMap.erase(D); 1819 FunctionUDRMap.erase(CGF.CurFn); 1820 } 1821 auto I = FunctionUDMMap.find(CGF.CurFn); 1822 if (I != FunctionUDMMap.end()) { 1823 for(const auto *D : I->second) 1824 UDMMap.erase(D); 1825 FunctionUDMMap.erase(I); 1826 } 1827 LastprivateConditionalToTypes.erase(CGF.CurFn); 1828 } 1829 1830 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1831 return IdentTy->getPointerTo(); 1832 } 1833 1834 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1835 if (!Kmpc_MicroTy) { 1836 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1837 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1838 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1839 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1840 } 1841 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1842 } 1843 1844 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1845 llvm::FunctionCallee RTLFn = nullptr; 1846 switch (static_cast<OpenMPRTLFunction>(Function)) { 1847 case OMPRTL__kmpc_fork_call: { 1848 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1849 // microtask, ...); 1850 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1851 getKmpc_MicroPointerTy()}; 1852 auto *FnTy = 1853 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1854 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1855 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1856 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1857 llvm::LLVMContext &Ctx = F->getContext(); 1858 llvm::MDBuilder MDB(Ctx); 1859 // Annotate the callback behavior of the __kmpc_fork_call: 1860 // - The callback callee is argument number 2 (microtask). 1861 // - The first two arguments of the callback callee are unknown (-1). 1862 // - All variadic arguments to the __kmpc_fork_call are passed to the 1863 // callback callee. 1864 F->addMetadata( 1865 llvm::LLVMContext::MD_callback, 1866 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1867 2, {-1, -1}, 1868 /* VarArgsArePassed */ true)})); 1869 } 1870 } 1871 break; 1872 } 1873 case OMPRTL__kmpc_global_thread_num: { 1874 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1875 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1876 auto *FnTy = 1877 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1878 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1879 break; 1880 } 1881 case OMPRTL__kmpc_threadprivate_cached: { 1882 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1883 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1884 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1885 CGM.VoidPtrTy, CGM.SizeTy, 1886 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1887 auto *FnTy = 1888 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1889 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1890 break; 1891 } 1892 case OMPRTL__kmpc_critical: { 1893 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1894 // kmp_critical_name *crit); 1895 llvm::Type *TypeParams[] = { 1896 getIdentTyPointerTy(), CGM.Int32Ty, 1897 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1898 auto *FnTy = 1899 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1900 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1901 break; 1902 } 1903 case OMPRTL__kmpc_critical_with_hint: { 1904 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1905 // kmp_critical_name *crit, uintptr_t hint); 1906 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1907 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1908 CGM.IntPtrTy}; 1909 auto *FnTy = 1910 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1911 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1912 break; 1913 } 1914 case OMPRTL__kmpc_threadprivate_register: { 1915 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1916 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1917 // typedef void *(*kmpc_ctor)(void *); 1918 auto *KmpcCtorTy = 1919 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1920 /*isVarArg*/ false)->getPointerTo(); 1921 // typedef void *(*kmpc_cctor)(void *, void *); 1922 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1923 auto *KmpcCopyCtorTy = 1924 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1925 /*isVarArg*/ false) 1926 ->getPointerTo(); 1927 // typedef void (*kmpc_dtor)(void *); 1928 auto *KmpcDtorTy = 1929 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1930 ->getPointerTo(); 1931 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1932 KmpcCopyCtorTy, KmpcDtorTy}; 1933 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1934 /*isVarArg*/ false); 1935 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1936 break; 1937 } 1938 case OMPRTL__kmpc_end_critical: { 1939 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1940 // kmp_critical_name *crit); 1941 llvm::Type *TypeParams[] = { 1942 getIdentTyPointerTy(), CGM.Int32Ty, 1943 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1944 auto *FnTy = 1945 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1946 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1947 break; 1948 } 1949 case OMPRTL__kmpc_cancel_barrier: { 1950 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1951 // global_tid); 1952 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1953 auto *FnTy = 1954 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1955 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1956 break; 1957 } 1958 case OMPRTL__kmpc_barrier: { 1959 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1960 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1961 auto *FnTy = 1962 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1963 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1964 break; 1965 } 1966 case OMPRTL__kmpc_for_static_fini: { 1967 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1968 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1969 auto *FnTy = 1970 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1971 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1972 break; 1973 } 1974 case OMPRTL__kmpc_push_num_threads: { 1975 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1976 // kmp_int32 num_threads) 1977 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1978 CGM.Int32Ty}; 1979 auto *FnTy = 1980 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1981 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1982 break; 1983 } 1984 case OMPRTL__kmpc_serialized_parallel: { 1985 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1986 // global_tid); 1987 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1988 auto *FnTy = 1989 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1990 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1991 break; 1992 } 1993 case OMPRTL__kmpc_end_serialized_parallel: { 1994 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1995 // global_tid); 1996 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1997 auto *FnTy = 1998 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1999 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 2000 break; 2001 } 2002 case OMPRTL__kmpc_flush: { 2003 // Build void __kmpc_flush(ident_t *loc); 2004 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 2005 auto *FnTy = 2006 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2007 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 2008 break; 2009 } 2010 case OMPRTL__kmpc_master: { 2011 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 2012 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2013 auto *FnTy = 2014 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2015 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 2016 break; 2017 } 2018 case OMPRTL__kmpc_end_master: { 2019 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 2020 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2021 auto *FnTy = 2022 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2023 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 2024 break; 2025 } 2026 case OMPRTL__kmpc_omp_taskyield: { 2027 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 2028 // int end_part); 2029 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2030 auto *FnTy = 2031 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2032 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 2033 break; 2034 } 2035 case OMPRTL__kmpc_single: { 2036 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 2037 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2038 auto *FnTy = 2039 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2040 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 2041 break; 2042 } 2043 case OMPRTL__kmpc_end_single: { 2044 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 2045 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2046 auto *FnTy = 2047 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2048 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 2049 break; 2050 } 2051 case OMPRTL__kmpc_omp_task_alloc: { 2052 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 2053 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2054 // kmp_routine_entry_t *task_entry); 2055 assert(KmpRoutineEntryPtrTy != nullptr && 2056 "Type kmp_routine_entry_t must be created."); 2057 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2058 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 2059 // Return void * and then cast to particular kmp_task_t type. 2060 auto *FnTy = 2061 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2062 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 2063 break; 2064 } 2065 case OMPRTL__kmpc_omp_target_task_alloc: { 2066 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 2067 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2068 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 2069 assert(KmpRoutineEntryPtrTy != nullptr && 2070 "Type kmp_routine_entry_t must be created."); 2071 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2072 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 2073 CGM.Int64Ty}; 2074 // Return void * and then cast to particular kmp_task_t type. 2075 auto *FnTy = 2076 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2077 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2078 break; 2079 } 2080 case OMPRTL__kmpc_omp_task: { 2081 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2082 // *new_task); 2083 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2084 CGM.VoidPtrTy}; 2085 auto *FnTy = 2086 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2087 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2088 break; 2089 } 2090 case OMPRTL__kmpc_copyprivate: { 2091 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2092 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2093 // kmp_int32 didit); 2094 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2095 auto *CpyFnTy = 2096 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2097 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2098 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2099 CGM.Int32Ty}; 2100 auto *FnTy = 2101 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2102 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2103 break; 2104 } 2105 case OMPRTL__kmpc_reduce: { 2106 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2107 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2108 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2109 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2110 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2111 /*isVarArg=*/false); 2112 llvm::Type *TypeParams[] = { 2113 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2114 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2115 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2116 auto *FnTy = 2117 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2118 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2119 break; 2120 } 2121 case OMPRTL__kmpc_reduce_nowait: { 2122 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2123 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2124 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2125 // *lck); 2126 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2127 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2128 /*isVarArg=*/false); 2129 llvm::Type *TypeParams[] = { 2130 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2131 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2132 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2133 auto *FnTy = 2134 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2135 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2136 break; 2137 } 2138 case OMPRTL__kmpc_end_reduce: { 2139 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2140 // kmp_critical_name *lck); 2141 llvm::Type *TypeParams[] = { 2142 getIdentTyPointerTy(), CGM.Int32Ty, 2143 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2144 auto *FnTy = 2145 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2146 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2147 break; 2148 } 2149 case OMPRTL__kmpc_end_reduce_nowait: { 2150 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2151 // kmp_critical_name *lck); 2152 llvm::Type *TypeParams[] = { 2153 getIdentTyPointerTy(), CGM.Int32Ty, 2154 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2155 auto *FnTy = 2156 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2157 RTLFn = 2158 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2159 break; 2160 } 2161 case OMPRTL__kmpc_omp_task_begin_if0: { 2162 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2163 // *new_task); 2164 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2165 CGM.VoidPtrTy}; 2166 auto *FnTy = 2167 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2168 RTLFn = 2169 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2170 break; 2171 } 2172 case OMPRTL__kmpc_omp_task_complete_if0: { 2173 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2174 // *new_task); 2175 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2176 CGM.VoidPtrTy}; 2177 auto *FnTy = 2178 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2179 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2180 /*Name=*/"__kmpc_omp_task_complete_if0"); 2181 break; 2182 } 2183 case OMPRTL__kmpc_ordered: { 2184 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2185 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2186 auto *FnTy = 2187 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2188 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2189 break; 2190 } 2191 case OMPRTL__kmpc_end_ordered: { 2192 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2193 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2194 auto *FnTy = 2195 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2196 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2197 break; 2198 } 2199 case OMPRTL__kmpc_omp_taskwait: { 2200 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2201 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2202 auto *FnTy = 2203 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2204 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2205 break; 2206 } 2207 case OMPRTL__kmpc_taskgroup: { 2208 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2209 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2210 auto *FnTy = 2211 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2212 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2213 break; 2214 } 2215 case OMPRTL__kmpc_end_taskgroup: { 2216 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2217 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2218 auto *FnTy = 2219 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2220 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2221 break; 2222 } 2223 case OMPRTL__kmpc_push_proc_bind: { 2224 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2225 // int proc_bind) 2226 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2227 auto *FnTy = 2228 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2229 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2230 break; 2231 } 2232 case OMPRTL__kmpc_omp_task_with_deps: { 2233 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2234 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2235 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2236 llvm::Type *TypeParams[] = { 2237 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2238 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2239 auto *FnTy = 2240 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2241 RTLFn = 2242 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2243 break; 2244 } 2245 case OMPRTL__kmpc_omp_wait_deps: { 2246 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2247 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2248 // kmp_depend_info_t *noalias_dep_list); 2249 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2250 CGM.Int32Ty, CGM.VoidPtrTy, 2251 CGM.Int32Ty, CGM.VoidPtrTy}; 2252 auto *FnTy = 2253 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2254 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2255 break; 2256 } 2257 case OMPRTL__kmpc_cancellationpoint: { 2258 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2259 // global_tid, kmp_int32 cncl_kind) 2260 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2261 auto *FnTy = 2262 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2263 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2264 break; 2265 } 2266 case OMPRTL__kmpc_cancel: { 2267 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2268 // kmp_int32 cncl_kind) 2269 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2270 auto *FnTy = 2271 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2272 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2273 break; 2274 } 2275 case OMPRTL__kmpc_push_num_teams: { 2276 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2277 // kmp_int32 num_teams, kmp_int32 num_threads) 2278 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2279 CGM.Int32Ty}; 2280 auto *FnTy = 2281 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2282 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2283 break; 2284 } 2285 case OMPRTL__kmpc_fork_teams: { 2286 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2287 // microtask, ...); 2288 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2289 getKmpc_MicroPointerTy()}; 2290 auto *FnTy = 2291 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2292 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2293 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2294 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2295 llvm::LLVMContext &Ctx = F->getContext(); 2296 llvm::MDBuilder MDB(Ctx); 2297 // Annotate the callback behavior of the __kmpc_fork_teams: 2298 // - The callback callee is argument number 2 (microtask). 2299 // - The first two arguments of the callback callee are unknown (-1). 2300 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2301 // callback callee. 2302 F->addMetadata( 2303 llvm::LLVMContext::MD_callback, 2304 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2305 2, {-1, -1}, 2306 /* VarArgsArePassed */ true)})); 2307 } 2308 } 2309 break; 2310 } 2311 case OMPRTL__kmpc_taskloop: { 2312 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2313 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2314 // sched, kmp_uint64 grainsize, void *task_dup); 2315 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2316 CGM.IntTy, 2317 CGM.VoidPtrTy, 2318 CGM.IntTy, 2319 CGM.Int64Ty->getPointerTo(), 2320 CGM.Int64Ty->getPointerTo(), 2321 CGM.Int64Ty, 2322 CGM.IntTy, 2323 CGM.IntTy, 2324 CGM.Int64Ty, 2325 CGM.VoidPtrTy}; 2326 auto *FnTy = 2327 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2328 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2329 break; 2330 } 2331 case OMPRTL__kmpc_doacross_init: { 2332 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2333 // num_dims, struct kmp_dim *dims); 2334 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2335 CGM.Int32Ty, 2336 CGM.Int32Ty, 2337 CGM.VoidPtrTy}; 2338 auto *FnTy = 2339 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2340 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2341 break; 2342 } 2343 case OMPRTL__kmpc_doacross_fini: { 2344 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2345 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2346 auto *FnTy = 2347 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2348 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2349 break; 2350 } 2351 case OMPRTL__kmpc_doacross_post: { 2352 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2353 // *vec); 2354 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2355 CGM.Int64Ty->getPointerTo()}; 2356 auto *FnTy = 2357 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2358 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2359 break; 2360 } 2361 case OMPRTL__kmpc_doacross_wait: { 2362 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2363 // *vec); 2364 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2365 CGM.Int64Ty->getPointerTo()}; 2366 auto *FnTy = 2367 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2368 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2369 break; 2370 } 2371 case OMPRTL__kmpc_task_reduction_init: { 2372 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2373 // *data); 2374 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2375 auto *FnTy = 2376 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2377 RTLFn = 2378 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2379 break; 2380 } 2381 case OMPRTL__kmpc_task_reduction_get_th_data: { 2382 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2383 // *d); 2384 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2385 auto *FnTy = 2386 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2387 RTLFn = CGM.CreateRuntimeFunction( 2388 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2389 break; 2390 } 2391 case OMPRTL__kmpc_alloc: { 2392 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2393 // al); omp_allocator_handle_t type is void *. 2394 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2395 auto *FnTy = 2396 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2397 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2398 break; 2399 } 2400 case OMPRTL__kmpc_free: { 2401 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2402 // al); omp_allocator_handle_t type is void *. 2403 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2404 auto *FnTy = 2405 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2406 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2407 break; 2408 } 2409 case OMPRTL__kmpc_push_target_tripcount: { 2410 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2411 // size); 2412 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2413 llvm::FunctionType *FnTy = 2414 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2415 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2416 break; 2417 } 2418 case OMPRTL__tgt_target: { 2419 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2420 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2421 // *arg_types); 2422 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2423 CGM.VoidPtrTy, 2424 CGM.Int32Ty, 2425 CGM.VoidPtrPtrTy, 2426 CGM.VoidPtrPtrTy, 2427 CGM.Int64Ty->getPointerTo(), 2428 CGM.Int64Ty->getPointerTo()}; 2429 auto *FnTy = 2430 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2431 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2432 break; 2433 } 2434 case OMPRTL__tgt_target_nowait: { 2435 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2436 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2437 // int64_t *arg_types); 2438 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2439 CGM.VoidPtrTy, 2440 CGM.Int32Ty, 2441 CGM.VoidPtrPtrTy, 2442 CGM.VoidPtrPtrTy, 2443 CGM.Int64Ty->getPointerTo(), 2444 CGM.Int64Ty->getPointerTo()}; 2445 auto *FnTy = 2446 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2447 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2448 break; 2449 } 2450 case OMPRTL__tgt_target_teams: { 2451 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2452 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2453 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2454 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2455 CGM.VoidPtrTy, 2456 CGM.Int32Ty, 2457 CGM.VoidPtrPtrTy, 2458 CGM.VoidPtrPtrTy, 2459 CGM.Int64Ty->getPointerTo(), 2460 CGM.Int64Ty->getPointerTo(), 2461 CGM.Int32Ty, 2462 CGM.Int32Ty}; 2463 auto *FnTy = 2464 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2465 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2466 break; 2467 } 2468 case OMPRTL__tgt_target_teams_nowait: { 2469 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2470 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2471 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2472 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2473 CGM.VoidPtrTy, 2474 CGM.Int32Ty, 2475 CGM.VoidPtrPtrTy, 2476 CGM.VoidPtrPtrTy, 2477 CGM.Int64Ty->getPointerTo(), 2478 CGM.Int64Ty->getPointerTo(), 2479 CGM.Int32Ty, 2480 CGM.Int32Ty}; 2481 auto *FnTy = 2482 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2483 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2484 break; 2485 } 2486 case OMPRTL__tgt_register_requires: { 2487 // Build void __tgt_register_requires(int64_t flags); 2488 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2489 auto *FnTy = 2490 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2491 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2492 break; 2493 } 2494 case OMPRTL__tgt_target_data_begin: { 2495 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2496 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2497 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2498 CGM.Int32Ty, 2499 CGM.VoidPtrPtrTy, 2500 CGM.VoidPtrPtrTy, 2501 CGM.Int64Ty->getPointerTo(), 2502 CGM.Int64Ty->getPointerTo()}; 2503 auto *FnTy = 2504 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2505 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2506 break; 2507 } 2508 case OMPRTL__tgt_target_data_begin_nowait: { 2509 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2510 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2511 // *arg_types); 2512 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2513 CGM.Int32Ty, 2514 CGM.VoidPtrPtrTy, 2515 CGM.VoidPtrPtrTy, 2516 CGM.Int64Ty->getPointerTo(), 2517 CGM.Int64Ty->getPointerTo()}; 2518 auto *FnTy = 2519 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2520 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2521 break; 2522 } 2523 case OMPRTL__tgt_target_data_end: { 2524 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2525 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2526 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2527 CGM.Int32Ty, 2528 CGM.VoidPtrPtrTy, 2529 CGM.VoidPtrPtrTy, 2530 CGM.Int64Ty->getPointerTo(), 2531 CGM.Int64Ty->getPointerTo()}; 2532 auto *FnTy = 2533 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2534 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2535 break; 2536 } 2537 case OMPRTL__tgt_target_data_end_nowait: { 2538 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2539 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2540 // *arg_types); 2541 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2542 CGM.Int32Ty, 2543 CGM.VoidPtrPtrTy, 2544 CGM.VoidPtrPtrTy, 2545 CGM.Int64Ty->getPointerTo(), 2546 CGM.Int64Ty->getPointerTo()}; 2547 auto *FnTy = 2548 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2549 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2550 break; 2551 } 2552 case OMPRTL__tgt_target_data_update: { 2553 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2554 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2555 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2556 CGM.Int32Ty, 2557 CGM.VoidPtrPtrTy, 2558 CGM.VoidPtrPtrTy, 2559 CGM.Int64Ty->getPointerTo(), 2560 CGM.Int64Ty->getPointerTo()}; 2561 auto *FnTy = 2562 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2563 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2564 break; 2565 } 2566 case OMPRTL__tgt_target_data_update_nowait: { 2567 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2568 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2569 // *arg_types); 2570 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2571 CGM.Int32Ty, 2572 CGM.VoidPtrPtrTy, 2573 CGM.VoidPtrPtrTy, 2574 CGM.Int64Ty->getPointerTo(), 2575 CGM.Int64Ty->getPointerTo()}; 2576 auto *FnTy = 2577 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2578 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2579 break; 2580 } 2581 case OMPRTL__tgt_mapper_num_components: { 2582 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2583 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2584 auto *FnTy = 2585 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2586 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2587 break; 2588 } 2589 case OMPRTL__tgt_push_mapper_component: { 2590 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2591 // *base, void *begin, int64_t size, int64_t type); 2592 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2593 CGM.Int64Ty, CGM.Int64Ty}; 2594 auto *FnTy = 2595 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2596 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2597 break; 2598 } 2599 } 2600 assert(RTLFn && "Unable to find OpenMP runtime function"); 2601 return RTLFn; 2602 } 2603 2604 llvm::FunctionCallee 2605 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2606 assert((IVSize == 32 || IVSize == 64) && 2607 "IV size is not compatible with the omp runtime"); 2608 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2609 : "__kmpc_for_static_init_4u") 2610 : (IVSigned ? "__kmpc_for_static_init_8" 2611 : "__kmpc_for_static_init_8u"); 2612 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2613 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2614 llvm::Type *TypeParams[] = { 2615 getIdentTyPointerTy(), // loc 2616 CGM.Int32Ty, // tid 2617 CGM.Int32Ty, // schedtype 2618 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2619 PtrTy, // p_lower 2620 PtrTy, // p_upper 2621 PtrTy, // p_stride 2622 ITy, // incr 2623 ITy // chunk 2624 }; 2625 auto *FnTy = 2626 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2627 return CGM.CreateRuntimeFunction(FnTy, Name); 2628 } 2629 2630 llvm::FunctionCallee 2631 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2632 assert((IVSize == 32 || IVSize == 64) && 2633 "IV size is not compatible with the omp runtime"); 2634 StringRef Name = 2635 IVSize == 32 2636 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2637 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2638 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2639 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2640 CGM.Int32Ty, // tid 2641 CGM.Int32Ty, // schedtype 2642 ITy, // lower 2643 ITy, // upper 2644 ITy, // stride 2645 ITy // chunk 2646 }; 2647 auto *FnTy = 2648 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2649 return CGM.CreateRuntimeFunction(FnTy, Name); 2650 } 2651 2652 llvm::FunctionCallee 2653 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2654 assert((IVSize == 32 || IVSize == 64) && 2655 "IV size is not compatible with the omp runtime"); 2656 StringRef Name = 2657 IVSize == 32 2658 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2659 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2660 llvm::Type *TypeParams[] = { 2661 getIdentTyPointerTy(), // loc 2662 CGM.Int32Ty, // tid 2663 }; 2664 auto *FnTy = 2665 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2666 return CGM.CreateRuntimeFunction(FnTy, Name); 2667 } 2668 2669 llvm::FunctionCallee 2670 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2671 assert((IVSize == 32 || IVSize == 64) && 2672 "IV size is not compatible with the omp runtime"); 2673 StringRef Name = 2674 IVSize == 32 2675 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2676 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2677 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2678 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2679 llvm::Type *TypeParams[] = { 2680 getIdentTyPointerTy(), // loc 2681 CGM.Int32Ty, // tid 2682 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2683 PtrTy, // p_lower 2684 PtrTy, // p_upper 2685 PtrTy // p_stride 2686 }; 2687 auto *FnTy = 2688 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2689 return CGM.CreateRuntimeFunction(FnTy, Name); 2690 } 2691 2692 /// Obtain information that uniquely identifies a target entry. This 2693 /// consists of the file and device IDs as well as line number associated with 2694 /// the relevant entry source location. 2695 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2696 unsigned &DeviceID, unsigned &FileID, 2697 unsigned &LineNum) { 2698 SourceManager &SM = C.getSourceManager(); 2699 2700 // The loc should be always valid and have a file ID (the user cannot use 2701 // #pragma directives in macros) 2702 2703 assert(Loc.isValid() && "Source location is expected to be always valid."); 2704 2705 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2706 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2707 2708 llvm::sys::fs::UniqueID ID; 2709 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2710 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2711 << PLoc.getFilename() << EC.message(); 2712 2713 DeviceID = ID.getDevice(); 2714 FileID = ID.getFile(); 2715 LineNum = PLoc.getLine(); 2716 } 2717 2718 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2719 if (CGM.getLangOpts().OpenMPSimd) 2720 return Address::invalid(); 2721 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2722 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2723 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2724 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2725 HasRequiresUnifiedSharedMemory))) { 2726 SmallString<64> PtrName; 2727 { 2728 llvm::raw_svector_ostream OS(PtrName); 2729 OS << CGM.getMangledName(GlobalDecl(VD)); 2730 if (!VD->isExternallyVisible()) { 2731 unsigned DeviceID, FileID, Line; 2732 getTargetEntryUniqueInfo(CGM.getContext(), 2733 VD->getCanonicalDecl()->getBeginLoc(), 2734 DeviceID, FileID, Line); 2735 OS << llvm::format("_%x", FileID); 2736 } 2737 OS << "_decl_tgt_ref_ptr"; 2738 } 2739 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2740 if (!Ptr) { 2741 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2742 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2743 PtrName); 2744 2745 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2746 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2747 2748 if (!CGM.getLangOpts().OpenMPIsDevice) 2749 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2750 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2751 } 2752 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2753 } 2754 return Address::invalid(); 2755 } 2756 2757 llvm::Constant * 2758 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2759 assert(!CGM.getLangOpts().OpenMPUseTLS || 2760 !CGM.getContext().getTargetInfo().isTLSSupported()); 2761 // Lookup the entry, lazily creating it if necessary. 2762 std::string Suffix = getName({"cache", ""}); 2763 return getOrCreateInternalVariable( 2764 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2765 } 2766 2767 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2768 const VarDecl *VD, 2769 Address VDAddr, 2770 SourceLocation Loc) { 2771 if (CGM.getLangOpts().OpenMPUseTLS && 2772 CGM.getContext().getTargetInfo().isTLSSupported()) 2773 return VDAddr; 2774 2775 llvm::Type *VarTy = VDAddr.getElementType(); 2776 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2777 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2778 CGM.Int8PtrTy), 2779 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2780 getOrCreateThreadPrivateCache(VD)}; 2781 return Address(CGF.EmitRuntimeCall( 2782 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2783 VDAddr.getAlignment()); 2784 } 2785 2786 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2787 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2788 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2789 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2790 // library. 2791 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2792 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2793 OMPLoc); 2794 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2795 // to register constructor/destructor for variable. 2796 llvm::Value *Args[] = { 2797 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2798 Ctor, CopyCtor, Dtor}; 2799 CGF.EmitRuntimeCall( 2800 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2801 } 2802 2803 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2804 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2805 bool PerformInit, CodeGenFunction *CGF) { 2806 if (CGM.getLangOpts().OpenMPUseTLS && 2807 CGM.getContext().getTargetInfo().isTLSSupported()) 2808 return nullptr; 2809 2810 VD = VD->getDefinition(CGM.getContext()); 2811 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2812 QualType ASTTy = VD->getType(); 2813 2814 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2815 const Expr *Init = VD->getAnyInitializer(); 2816 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2817 // Generate function that re-emits the declaration's initializer into the 2818 // threadprivate copy of the variable VD 2819 CodeGenFunction CtorCGF(CGM); 2820 FunctionArgList Args; 2821 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2822 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2823 ImplicitParamDecl::Other); 2824 Args.push_back(&Dst); 2825 2826 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2827 CGM.getContext().VoidPtrTy, Args); 2828 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2829 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2830 llvm::Function *Fn = 2831 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2832 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2833 Args, Loc, Loc); 2834 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2835 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2836 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2837 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2838 Arg = CtorCGF.Builder.CreateElementBitCast( 2839 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2840 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2841 /*IsInitializer=*/true); 2842 ArgVal = CtorCGF.EmitLoadOfScalar( 2843 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2844 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2845 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2846 CtorCGF.FinishFunction(); 2847 Ctor = Fn; 2848 } 2849 if (VD->getType().isDestructedType() != QualType::DK_none) { 2850 // Generate function that emits destructor call for the threadprivate copy 2851 // of the variable VD 2852 CodeGenFunction DtorCGF(CGM); 2853 FunctionArgList Args; 2854 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2855 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2856 ImplicitParamDecl::Other); 2857 Args.push_back(&Dst); 2858 2859 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2860 CGM.getContext().VoidTy, Args); 2861 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2862 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2863 llvm::Function *Fn = 2864 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2865 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2866 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2867 Loc, Loc); 2868 // Create a scope with an artificial location for the body of this function. 2869 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2870 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2871 DtorCGF.GetAddrOfLocalVar(&Dst), 2872 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2873 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2874 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2875 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2876 DtorCGF.FinishFunction(); 2877 Dtor = Fn; 2878 } 2879 // Do not emit init function if it is not required. 2880 if (!Ctor && !Dtor) 2881 return nullptr; 2882 2883 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2884 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2885 /*isVarArg=*/false) 2886 ->getPointerTo(); 2887 // Copying constructor for the threadprivate variable. 2888 // Must be NULL - reserved by runtime, but currently it requires that this 2889 // parameter is always NULL. Otherwise it fires assertion. 2890 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2891 if (Ctor == nullptr) { 2892 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2893 /*isVarArg=*/false) 2894 ->getPointerTo(); 2895 Ctor = llvm::Constant::getNullValue(CtorTy); 2896 } 2897 if (Dtor == nullptr) { 2898 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2899 /*isVarArg=*/false) 2900 ->getPointerTo(); 2901 Dtor = llvm::Constant::getNullValue(DtorTy); 2902 } 2903 if (!CGF) { 2904 auto *InitFunctionTy = 2905 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2906 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2907 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2908 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2909 CodeGenFunction InitCGF(CGM); 2910 FunctionArgList ArgList; 2911 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2912 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2913 Loc, Loc); 2914 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2915 InitCGF.FinishFunction(); 2916 return InitFunction; 2917 } 2918 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2919 } 2920 return nullptr; 2921 } 2922 2923 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2924 llvm::GlobalVariable *Addr, 2925 bool PerformInit) { 2926 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2927 !CGM.getLangOpts().OpenMPIsDevice) 2928 return false; 2929 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2930 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2931 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2932 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2933 HasRequiresUnifiedSharedMemory)) 2934 return CGM.getLangOpts().OpenMPIsDevice; 2935 VD = VD->getDefinition(CGM.getContext()); 2936 assert(VD && "Unknown VarDecl"); 2937 2938 if (!DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2939 return CGM.getLangOpts().OpenMPIsDevice; 2940 2941 QualType ASTTy = VD->getType(); 2942 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2943 2944 // Produce the unique prefix to identify the new target regions. We use 2945 // the source location of the variable declaration which we know to not 2946 // conflict with any target region. 2947 unsigned DeviceID; 2948 unsigned FileID; 2949 unsigned Line; 2950 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2951 SmallString<128> Buffer, Out; 2952 { 2953 llvm::raw_svector_ostream OS(Buffer); 2954 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2955 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2956 } 2957 2958 const Expr *Init = VD->getAnyInitializer(); 2959 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2960 llvm::Constant *Ctor; 2961 llvm::Constant *ID; 2962 if (CGM.getLangOpts().OpenMPIsDevice) { 2963 // Generate function that re-emits the declaration's initializer into 2964 // the threadprivate copy of the variable VD 2965 CodeGenFunction CtorCGF(CGM); 2966 2967 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2968 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2969 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2970 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2971 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2972 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2973 FunctionArgList(), Loc, Loc); 2974 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2975 CtorCGF.EmitAnyExprToMem(Init, 2976 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2977 Init->getType().getQualifiers(), 2978 /*IsInitializer=*/true); 2979 CtorCGF.FinishFunction(); 2980 Ctor = Fn; 2981 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2982 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2983 } else { 2984 Ctor = new llvm::GlobalVariable( 2985 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2986 llvm::GlobalValue::PrivateLinkage, 2987 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2988 ID = Ctor; 2989 } 2990 2991 // Register the information for the entry associated with the constructor. 2992 Out.clear(); 2993 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2994 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2995 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2996 } 2997 if (VD->getType().isDestructedType() != QualType::DK_none) { 2998 llvm::Constant *Dtor; 2999 llvm::Constant *ID; 3000 if (CGM.getLangOpts().OpenMPIsDevice) { 3001 // Generate function that emits destructor call for the threadprivate 3002 // copy of the variable VD 3003 CodeGenFunction DtorCGF(CGM); 3004 3005 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 3006 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 3007 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 3008 FTy, Twine(Buffer, "_dtor"), FI, Loc); 3009 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 3010 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 3011 FunctionArgList(), Loc, Loc); 3012 // Create a scope with an artificial location for the body of this 3013 // function. 3014 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 3015 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 3016 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 3017 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 3018 DtorCGF.FinishFunction(); 3019 Dtor = Fn; 3020 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 3021 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 3022 } else { 3023 Dtor = new llvm::GlobalVariable( 3024 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 3025 llvm::GlobalValue::PrivateLinkage, 3026 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 3027 ID = Dtor; 3028 } 3029 // Register the information for the entry associated with the destructor. 3030 Out.clear(); 3031 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 3032 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 3033 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 3034 } 3035 return CGM.getLangOpts().OpenMPIsDevice; 3036 } 3037 3038 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 3039 QualType VarType, 3040 StringRef Name) { 3041 std::string Suffix = getName({"artificial", ""}); 3042 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 3043 llvm::Value *GAddr = 3044 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 3045 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 3046 CGM.getTarget().isTLSSupported()) { 3047 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 3048 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 3049 } 3050 std::string CacheSuffix = getName({"cache", ""}); 3051 llvm::Value *Args[] = { 3052 emitUpdateLocation(CGF, SourceLocation()), 3053 getThreadID(CGF, SourceLocation()), 3054 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 3055 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 3056 /*isSigned=*/false), 3057 getOrCreateInternalVariable( 3058 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 3059 return Address( 3060 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3061 CGF.EmitRuntimeCall( 3062 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3063 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3064 CGM.getContext().getTypeAlignInChars(VarType)); 3065 } 3066 3067 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 3068 const RegionCodeGenTy &ThenGen, 3069 const RegionCodeGenTy &ElseGen) { 3070 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3071 3072 // If the condition constant folds and can be elided, try to avoid emitting 3073 // the condition and the dead arm of the if/else. 3074 bool CondConstant; 3075 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3076 if (CondConstant) 3077 ThenGen(CGF); 3078 else 3079 ElseGen(CGF); 3080 return; 3081 } 3082 3083 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3084 // emit the conditional branch. 3085 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3086 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3087 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3088 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3089 3090 // Emit the 'then' code. 3091 CGF.EmitBlock(ThenBlock); 3092 ThenGen(CGF); 3093 CGF.EmitBranch(ContBlock); 3094 // Emit the 'else' code if present. 3095 // There is no need to emit line number for unconditional branch. 3096 (void)ApplyDebugLocation::CreateEmpty(CGF); 3097 CGF.EmitBlock(ElseBlock); 3098 ElseGen(CGF); 3099 // There is no need to emit line number for unconditional branch. 3100 (void)ApplyDebugLocation::CreateEmpty(CGF); 3101 CGF.EmitBranch(ContBlock); 3102 // Emit the continuation block for code after the if. 3103 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3104 } 3105 3106 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3107 llvm::Function *OutlinedFn, 3108 ArrayRef<llvm::Value *> CapturedVars, 3109 const Expr *IfCond) { 3110 if (!CGF.HaveInsertPoint()) 3111 return; 3112 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3113 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3114 PrePostActionTy &) { 3115 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3116 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3117 llvm::Value *Args[] = { 3118 RTLoc, 3119 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3120 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3121 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3122 RealArgs.append(std::begin(Args), std::end(Args)); 3123 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3124 3125 llvm::FunctionCallee RTLFn = 3126 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3127 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3128 }; 3129 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3130 PrePostActionTy &) { 3131 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3132 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3133 // Build calls: 3134 // __kmpc_serialized_parallel(&Loc, GTid); 3135 llvm::Value *Args[] = {RTLoc, ThreadID}; 3136 CGF.EmitRuntimeCall( 3137 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3138 3139 // OutlinedFn(>id, &zero_bound, CapturedStruct); 3140 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 3141 Address ZeroAddrBound = 3142 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3143 /*Name=*/".bound.zero.addr"); 3144 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 3145 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3146 // ThreadId for serialized parallels is 0. 3147 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 3148 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 3149 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3150 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3151 3152 // __kmpc_end_serialized_parallel(&Loc, GTid); 3153 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3154 CGF.EmitRuntimeCall( 3155 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3156 EndArgs); 3157 }; 3158 if (IfCond) { 3159 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 3160 } else { 3161 RegionCodeGenTy ThenRCG(ThenGen); 3162 ThenRCG(CGF); 3163 } 3164 } 3165 3166 // If we're inside an (outlined) parallel region, use the region info's 3167 // thread-ID variable (it is passed in a first argument of the outlined function 3168 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3169 // regular serial code region, get thread ID by calling kmp_int32 3170 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3171 // return the address of that temp. 3172 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3173 SourceLocation Loc) { 3174 if (auto *OMPRegionInfo = 3175 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3176 if (OMPRegionInfo->getThreadIDVariable()) 3177 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 3178 3179 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3180 QualType Int32Ty = 3181 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3182 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3183 CGF.EmitStoreOfScalar(ThreadID, 3184 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3185 3186 return ThreadIDTemp; 3187 } 3188 3189 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3190 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3191 SmallString<256> Buffer; 3192 llvm::raw_svector_ostream Out(Buffer); 3193 Out << Name; 3194 StringRef RuntimeName = Out.str(); 3195 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3196 if (Elem.second) { 3197 assert(Elem.second->getType()->getPointerElementType() == Ty && 3198 "OMP internal variable has different type than requested"); 3199 return &*Elem.second; 3200 } 3201 3202 return Elem.second = new llvm::GlobalVariable( 3203 CGM.getModule(), Ty, /*IsConstant*/ false, 3204 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3205 Elem.first(), /*InsertBefore=*/nullptr, 3206 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3207 } 3208 3209 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3210 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3211 std::string Name = getName({Prefix, "var"}); 3212 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3213 } 3214 3215 namespace { 3216 /// Common pre(post)-action for different OpenMP constructs. 3217 class CommonActionTy final : public PrePostActionTy { 3218 llvm::FunctionCallee EnterCallee; 3219 ArrayRef<llvm::Value *> EnterArgs; 3220 llvm::FunctionCallee ExitCallee; 3221 ArrayRef<llvm::Value *> ExitArgs; 3222 bool Conditional; 3223 llvm::BasicBlock *ContBlock = nullptr; 3224 3225 public: 3226 CommonActionTy(llvm::FunctionCallee EnterCallee, 3227 ArrayRef<llvm::Value *> EnterArgs, 3228 llvm::FunctionCallee ExitCallee, 3229 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3230 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3231 ExitArgs(ExitArgs), Conditional(Conditional) {} 3232 void Enter(CodeGenFunction &CGF) override { 3233 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3234 if (Conditional) { 3235 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3236 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3237 ContBlock = CGF.createBasicBlock("omp_if.end"); 3238 // Generate the branch (If-stmt) 3239 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3240 CGF.EmitBlock(ThenBlock); 3241 } 3242 } 3243 void Done(CodeGenFunction &CGF) { 3244 // Emit the rest of blocks/branches 3245 CGF.EmitBranch(ContBlock); 3246 CGF.EmitBlock(ContBlock, true); 3247 } 3248 void Exit(CodeGenFunction &CGF) override { 3249 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3250 } 3251 }; 3252 } // anonymous namespace 3253 3254 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3255 StringRef CriticalName, 3256 const RegionCodeGenTy &CriticalOpGen, 3257 SourceLocation Loc, const Expr *Hint) { 3258 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3259 // CriticalOpGen(); 3260 // __kmpc_end_critical(ident_t *, gtid, Lock); 3261 // Prepare arguments and build a call to __kmpc_critical 3262 if (!CGF.HaveInsertPoint()) 3263 return; 3264 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3265 getCriticalRegionLock(CriticalName)}; 3266 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3267 std::end(Args)); 3268 if (Hint) { 3269 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3270 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3271 } 3272 CommonActionTy Action( 3273 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3274 : OMPRTL__kmpc_critical), 3275 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3276 CriticalOpGen.setAction(Action); 3277 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3278 } 3279 3280 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3281 const RegionCodeGenTy &MasterOpGen, 3282 SourceLocation Loc) { 3283 if (!CGF.HaveInsertPoint()) 3284 return; 3285 // if(__kmpc_master(ident_t *, gtid)) { 3286 // MasterOpGen(); 3287 // __kmpc_end_master(ident_t *, gtid); 3288 // } 3289 // Prepare arguments and build a call to __kmpc_master 3290 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3291 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3292 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3293 /*Conditional=*/true); 3294 MasterOpGen.setAction(Action); 3295 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3296 Action.Done(CGF); 3297 } 3298 3299 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3300 SourceLocation Loc) { 3301 if (!CGF.HaveInsertPoint()) 3302 return; 3303 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3304 if (OMPBuilder) { 3305 OMPBuilder->CreateTaskyield(CGF.Builder); 3306 } else { 3307 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3308 llvm::Value *Args[] = { 3309 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3310 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3311 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), 3312 Args); 3313 } 3314 3315 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3316 Region->emitUntiedSwitch(CGF); 3317 } 3318 3319 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3320 const RegionCodeGenTy &TaskgroupOpGen, 3321 SourceLocation Loc) { 3322 if (!CGF.HaveInsertPoint()) 3323 return; 3324 // __kmpc_taskgroup(ident_t *, gtid); 3325 // TaskgroupOpGen(); 3326 // __kmpc_end_taskgroup(ident_t *, gtid); 3327 // Prepare arguments and build a call to __kmpc_taskgroup 3328 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3329 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3330 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3331 Args); 3332 TaskgroupOpGen.setAction(Action); 3333 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3334 } 3335 3336 /// Given an array of pointers to variables, project the address of a 3337 /// given variable. 3338 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3339 unsigned Index, const VarDecl *Var) { 3340 // Pull out the pointer to the variable. 3341 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3342 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3343 3344 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3345 Addr = CGF.Builder.CreateElementBitCast( 3346 Addr, CGF.ConvertTypeForMem(Var->getType())); 3347 return Addr; 3348 } 3349 3350 static llvm::Value *emitCopyprivateCopyFunction( 3351 CodeGenModule &CGM, llvm::Type *ArgsType, 3352 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3353 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3354 SourceLocation Loc) { 3355 ASTContext &C = CGM.getContext(); 3356 // void copy_func(void *LHSArg, void *RHSArg); 3357 FunctionArgList Args; 3358 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3359 ImplicitParamDecl::Other); 3360 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3361 ImplicitParamDecl::Other); 3362 Args.push_back(&LHSArg); 3363 Args.push_back(&RHSArg); 3364 const auto &CGFI = 3365 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3366 std::string Name = 3367 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3368 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3369 llvm::GlobalValue::InternalLinkage, Name, 3370 &CGM.getModule()); 3371 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3372 Fn->setDoesNotRecurse(); 3373 CodeGenFunction CGF(CGM); 3374 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3375 // Dest = (void*[n])(LHSArg); 3376 // Src = (void*[n])(RHSArg); 3377 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3378 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3379 ArgsType), CGF.getPointerAlign()); 3380 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3381 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3382 ArgsType), CGF.getPointerAlign()); 3383 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3384 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3385 // ... 3386 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3387 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3388 const auto *DestVar = 3389 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3390 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3391 3392 const auto *SrcVar = 3393 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3394 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3395 3396 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3397 QualType Type = VD->getType(); 3398 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3399 } 3400 CGF.FinishFunction(); 3401 return Fn; 3402 } 3403 3404 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3405 const RegionCodeGenTy &SingleOpGen, 3406 SourceLocation Loc, 3407 ArrayRef<const Expr *> CopyprivateVars, 3408 ArrayRef<const Expr *> SrcExprs, 3409 ArrayRef<const Expr *> DstExprs, 3410 ArrayRef<const Expr *> AssignmentOps) { 3411 if (!CGF.HaveInsertPoint()) 3412 return; 3413 assert(CopyprivateVars.size() == SrcExprs.size() && 3414 CopyprivateVars.size() == DstExprs.size() && 3415 CopyprivateVars.size() == AssignmentOps.size()); 3416 ASTContext &C = CGM.getContext(); 3417 // int32 did_it = 0; 3418 // if(__kmpc_single(ident_t *, gtid)) { 3419 // SingleOpGen(); 3420 // __kmpc_end_single(ident_t *, gtid); 3421 // did_it = 1; 3422 // } 3423 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3424 // <copy_func>, did_it); 3425 3426 Address DidIt = Address::invalid(); 3427 if (!CopyprivateVars.empty()) { 3428 // int32 did_it = 0; 3429 QualType KmpInt32Ty = 3430 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3431 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3432 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3433 } 3434 // Prepare arguments and build a call to __kmpc_single 3435 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3436 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3437 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3438 /*Conditional=*/true); 3439 SingleOpGen.setAction(Action); 3440 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3441 if (DidIt.isValid()) { 3442 // did_it = 1; 3443 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3444 } 3445 Action.Done(CGF); 3446 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3447 // <copy_func>, did_it); 3448 if (DidIt.isValid()) { 3449 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3450 QualType CopyprivateArrayTy = C.getConstantArrayType( 3451 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3452 /*IndexTypeQuals=*/0); 3453 // Create a list of all private variables for copyprivate. 3454 Address CopyprivateList = 3455 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3456 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3457 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3458 CGF.Builder.CreateStore( 3459 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3460 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 3461 CGF.VoidPtrTy), 3462 Elem); 3463 } 3464 // Build function that copies private values from single region to all other 3465 // threads in the corresponding parallel region. 3466 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3467 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3468 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3469 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3470 Address CL = 3471 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3472 CGF.VoidPtrTy); 3473 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3474 llvm::Value *Args[] = { 3475 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3476 getThreadID(CGF, Loc), // i32 <gtid> 3477 BufSize, // size_t <buf_size> 3478 CL.getPointer(), // void *<copyprivate list> 3479 CpyFn, // void (*) (void *, void *) <copy_func> 3480 DidItVal // i32 did_it 3481 }; 3482 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3483 } 3484 } 3485 3486 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3487 const RegionCodeGenTy &OrderedOpGen, 3488 SourceLocation Loc, bool IsThreads) { 3489 if (!CGF.HaveInsertPoint()) 3490 return; 3491 // __kmpc_ordered(ident_t *, gtid); 3492 // OrderedOpGen(); 3493 // __kmpc_end_ordered(ident_t *, gtid); 3494 // Prepare arguments and build a call to __kmpc_ordered 3495 if (IsThreads) { 3496 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3497 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3498 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3499 Args); 3500 OrderedOpGen.setAction(Action); 3501 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3502 return; 3503 } 3504 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3505 } 3506 3507 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3508 unsigned Flags; 3509 if (Kind == OMPD_for) 3510 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3511 else if (Kind == OMPD_sections) 3512 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3513 else if (Kind == OMPD_single) 3514 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3515 else if (Kind == OMPD_barrier) 3516 Flags = OMP_IDENT_BARRIER_EXPL; 3517 else 3518 Flags = OMP_IDENT_BARRIER_IMPL; 3519 return Flags; 3520 } 3521 3522 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3523 CodeGenFunction &CGF, const OMPLoopDirective &S, 3524 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3525 // Check if the loop directive is actually a doacross loop directive. In this 3526 // case choose static, 1 schedule. 3527 if (llvm::any_of( 3528 S.getClausesOfKind<OMPOrderedClause>(), 3529 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3530 ScheduleKind = OMPC_SCHEDULE_static; 3531 // Chunk size is 1 in this case. 3532 llvm::APInt ChunkSize(32, 1); 3533 ChunkExpr = IntegerLiteral::Create( 3534 CGF.getContext(), ChunkSize, 3535 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3536 SourceLocation()); 3537 } 3538 } 3539 3540 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3541 OpenMPDirectiveKind Kind, bool EmitChecks, 3542 bool ForceSimpleCall) { 3543 // Check if we should use the OMPBuilder 3544 auto *OMPRegionInfo = 3545 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 3546 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3547 if (OMPBuilder) { 3548 CGF.Builder.restoreIP(OMPBuilder->CreateBarrier( 3549 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 3550 return; 3551 } 3552 3553 if (!CGF.HaveInsertPoint()) 3554 return; 3555 // Build call __kmpc_cancel_barrier(loc, thread_id); 3556 // Build call __kmpc_barrier(loc, thread_id); 3557 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3558 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3559 // thread_id); 3560 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3561 getThreadID(CGF, Loc)}; 3562 if (OMPRegionInfo) { 3563 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3564 llvm::Value *Result = CGF.EmitRuntimeCall( 3565 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3566 if (EmitChecks) { 3567 // if (__kmpc_cancel_barrier()) { 3568 // exit from construct; 3569 // } 3570 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3571 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3572 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3573 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3574 CGF.EmitBlock(ExitBB); 3575 // exit from construct; 3576 CodeGenFunction::JumpDest CancelDestination = 3577 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3578 CGF.EmitBranchThroughCleanup(CancelDestination); 3579 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3580 } 3581 return; 3582 } 3583 } 3584 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3585 } 3586 3587 /// Map the OpenMP loop schedule to the runtime enumeration. 3588 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3589 bool Chunked, bool Ordered) { 3590 switch (ScheduleKind) { 3591 case OMPC_SCHEDULE_static: 3592 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3593 : (Ordered ? OMP_ord_static : OMP_sch_static); 3594 case OMPC_SCHEDULE_dynamic: 3595 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3596 case OMPC_SCHEDULE_guided: 3597 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3598 case OMPC_SCHEDULE_runtime: 3599 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3600 case OMPC_SCHEDULE_auto: 3601 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3602 case OMPC_SCHEDULE_unknown: 3603 assert(!Chunked && "chunk was specified but schedule kind not known"); 3604 return Ordered ? OMP_ord_static : OMP_sch_static; 3605 } 3606 llvm_unreachable("Unexpected runtime schedule"); 3607 } 3608 3609 /// Map the OpenMP distribute schedule to the runtime enumeration. 3610 static OpenMPSchedType 3611 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3612 // only static is allowed for dist_schedule 3613 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3614 } 3615 3616 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3617 bool Chunked) const { 3618 OpenMPSchedType Schedule = 3619 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3620 return Schedule == OMP_sch_static; 3621 } 3622 3623 bool CGOpenMPRuntime::isStaticNonchunked( 3624 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3625 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3626 return Schedule == OMP_dist_sch_static; 3627 } 3628 3629 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3630 bool Chunked) const { 3631 OpenMPSchedType Schedule = 3632 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3633 return Schedule == OMP_sch_static_chunked; 3634 } 3635 3636 bool CGOpenMPRuntime::isStaticChunked( 3637 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3638 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3639 return Schedule == OMP_dist_sch_static_chunked; 3640 } 3641 3642 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3643 OpenMPSchedType Schedule = 3644 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3645 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3646 return Schedule != OMP_sch_static; 3647 } 3648 3649 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3650 OpenMPScheduleClauseModifier M1, 3651 OpenMPScheduleClauseModifier M2) { 3652 int Modifier = 0; 3653 switch (M1) { 3654 case OMPC_SCHEDULE_MODIFIER_monotonic: 3655 Modifier = OMP_sch_modifier_monotonic; 3656 break; 3657 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3658 Modifier = OMP_sch_modifier_nonmonotonic; 3659 break; 3660 case OMPC_SCHEDULE_MODIFIER_simd: 3661 if (Schedule == OMP_sch_static_chunked) 3662 Schedule = OMP_sch_static_balanced_chunked; 3663 break; 3664 case OMPC_SCHEDULE_MODIFIER_last: 3665 case OMPC_SCHEDULE_MODIFIER_unknown: 3666 break; 3667 } 3668 switch (M2) { 3669 case OMPC_SCHEDULE_MODIFIER_monotonic: 3670 Modifier = OMP_sch_modifier_monotonic; 3671 break; 3672 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3673 Modifier = OMP_sch_modifier_nonmonotonic; 3674 break; 3675 case OMPC_SCHEDULE_MODIFIER_simd: 3676 if (Schedule == OMP_sch_static_chunked) 3677 Schedule = OMP_sch_static_balanced_chunked; 3678 break; 3679 case OMPC_SCHEDULE_MODIFIER_last: 3680 case OMPC_SCHEDULE_MODIFIER_unknown: 3681 break; 3682 } 3683 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3684 // If the static schedule kind is specified or if the ordered clause is 3685 // specified, and if the nonmonotonic modifier is not specified, the effect is 3686 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3687 // modifier is specified, the effect is as if the nonmonotonic modifier is 3688 // specified. 3689 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3690 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3691 Schedule == OMP_sch_static_balanced_chunked || 3692 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 3693 Schedule == OMP_dist_sch_static_chunked || 3694 Schedule == OMP_dist_sch_static)) 3695 Modifier = OMP_sch_modifier_nonmonotonic; 3696 } 3697 return Schedule | Modifier; 3698 } 3699 3700 void CGOpenMPRuntime::emitForDispatchInit( 3701 CodeGenFunction &CGF, SourceLocation Loc, 3702 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3703 bool Ordered, const DispatchRTInput &DispatchValues) { 3704 if (!CGF.HaveInsertPoint()) 3705 return; 3706 OpenMPSchedType Schedule = getRuntimeSchedule( 3707 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3708 assert(Ordered || 3709 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3710 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3711 Schedule != OMP_sch_static_balanced_chunked)); 3712 // Call __kmpc_dispatch_init( 3713 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3714 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3715 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3716 3717 // If the Chunk was not specified in the clause - use default value 1. 3718 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3719 : CGF.Builder.getIntN(IVSize, 1); 3720 llvm::Value *Args[] = { 3721 emitUpdateLocation(CGF, Loc), 3722 getThreadID(CGF, Loc), 3723 CGF.Builder.getInt32(addMonoNonMonoModifier( 3724 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3725 DispatchValues.LB, // Lower 3726 DispatchValues.UB, // Upper 3727 CGF.Builder.getIntN(IVSize, 1), // Stride 3728 Chunk // Chunk 3729 }; 3730 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3731 } 3732 3733 static void emitForStaticInitCall( 3734 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3735 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3736 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3737 const CGOpenMPRuntime::StaticRTInput &Values) { 3738 if (!CGF.HaveInsertPoint()) 3739 return; 3740 3741 assert(!Values.Ordered); 3742 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3743 Schedule == OMP_sch_static_balanced_chunked || 3744 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3745 Schedule == OMP_dist_sch_static || 3746 Schedule == OMP_dist_sch_static_chunked); 3747 3748 // Call __kmpc_for_static_init( 3749 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3750 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3751 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3752 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3753 llvm::Value *Chunk = Values.Chunk; 3754 if (Chunk == nullptr) { 3755 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3756 Schedule == OMP_dist_sch_static) && 3757 "expected static non-chunked schedule"); 3758 // If the Chunk was not specified in the clause - use default value 1. 3759 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3760 } else { 3761 assert((Schedule == OMP_sch_static_chunked || 3762 Schedule == OMP_sch_static_balanced_chunked || 3763 Schedule == OMP_ord_static_chunked || 3764 Schedule == OMP_dist_sch_static_chunked) && 3765 "expected static chunked schedule"); 3766 } 3767 llvm::Value *Args[] = { 3768 UpdateLocation, 3769 ThreadId, 3770 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3771 M2)), // Schedule type 3772 Values.IL.getPointer(), // &isLastIter 3773 Values.LB.getPointer(), // &LB 3774 Values.UB.getPointer(), // &UB 3775 Values.ST.getPointer(), // &Stride 3776 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3777 Chunk // Chunk 3778 }; 3779 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3780 } 3781 3782 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3783 SourceLocation Loc, 3784 OpenMPDirectiveKind DKind, 3785 const OpenMPScheduleTy &ScheduleKind, 3786 const StaticRTInput &Values) { 3787 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3788 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3789 assert(isOpenMPWorksharingDirective(DKind) && 3790 "Expected loop-based or sections-based directive."); 3791 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3792 isOpenMPLoopDirective(DKind) 3793 ? OMP_IDENT_WORK_LOOP 3794 : OMP_IDENT_WORK_SECTIONS); 3795 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3796 llvm::FunctionCallee StaticInitFunction = 3797 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3798 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3799 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3800 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3801 } 3802 3803 void CGOpenMPRuntime::emitDistributeStaticInit( 3804 CodeGenFunction &CGF, SourceLocation Loc, 3805 OpenMPDistScheduleClauseKind SchedKind, 3806 const CGOpenMPRuntime::StaticRTInput &Values) { 3807 OpenMPSchedType ScheduleNum = 3808 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3809 llvm::Value *UpdatedLocation = 3810 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3811 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3812 llvm::FunctionCallee StaticInitFunction = 3813 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3814 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3815 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3816 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3817 } 3818 3819 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3820 SourceLocation Loc, 3821 OpenMPDirectiveKind DKind) { 3822 if (!CGF.HaveInsertPoint()) 3823 return; 3824 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3825 llvm::Value *Args[] = { 3826 emitUpdateLocation(CGF, Loc, 3827 isOpenMPDistributeDirective(DKind) 3828 ? OMP_IDENT_WORK_DISTRIBUTE 3829 : isOpenMPLoopDirective(DKind) 3830 ? OMP_IDENT_WORK_LOOP 3831 : OMP_IDENT_WORK_SECTIONS), 3832 getThreadID(CGF, Loc)}; 3833 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3834 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3835 Args); 3836 } 3837 3838 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3839 SourceLocation Loc, 3840 unsigned IVSize, 3841 bool IVSigned) { 3842 if (!CGF.HaveInsertPoint()) 3843 return; 3844 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3845 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3846 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3847 } 3848 3849 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3850 SourceLocation Loc, unsigned IVSize, 3851 bool IVSigned, Address IL, 3852 Address LB, Address UB, 3853 Address ST) { 3854 // Call __kmpc_dispatch_next( 3855 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3856 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3857 // kmp_int[32|64] *p_stride); 3858 llvm::Value *Args[] = { 3859 emitUpdateLocation(CGF, Loc), 3860 getThreadID(CGF, Loc), 3861 IL.getPointer(), // &isLastIter 3862 LB.getPointer(), // &Lower 3863 UB.getPointer(), // &Upper 3864 ST.getPointer() // &Stride 3865 }; 3866 llvm::Value *Call = 3867 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3868 return CGF.EmitScalarConversion( 3869 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3870 CGF.getContext().BoolTy, Loc); 3871 } 3872 3873 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3874 llvm::Value *NumThreads, 3875 SourceLocation Loc) { 3876 if (!CGF.HaveInsertPoint()) 3877 return; 3878 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3879 llvm::Value *Args[] = { 3880 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3881 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3882 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3883 Args); 3884 } 3885 3886 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3887 ProcBindKind ProcBind, 3888 SourceLocation Loc) { 3889 if (!CGF.HaveInsertPoint()) 3890 return; 3891 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 3892 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3893 llvm::Value *Args[] = { 3894 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3895 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 3896 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3897 } 3898 3899 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3900 SourceLocation Loc, llvm::AtomicOrdering AO) { 3901 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3902 if (OMPBuilder) { 3903 OMPBuilder->CreateFlush(CGF.Builder); 3904 } else { 3905 if (!CGF.HaveInsertPoint()) 3906 return; 3907 // Build call void __kmpc_flush(ident_t *loc) 3908 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3909 emitUpdateLocation(CGF, Loc)); 3910 } 3911 } 3912 3913 namespace { 3914 /// Indexes of fields for type kmp_task_t. 3915 enum KmpTaskTFields { 3916 /// List of shared variables. 3917 KmpTaskTShareds, 3918 /// Task routine. 3919 KmpTaskTRoutine, 3920 /// Partition id for the untied tasks. 3921 KmpTaskTPartId, 3922 /// Function with call of destructors for private variables. 3923 Data1, 3924 /// Task priority. 3925 Data2, 3926 /// (Taskloops only) Lower bound. 3927 KmpTaskTLowerBound, 3928 /// (Taskloops only) Upper bound. 3929 KmpTaskTUpperBound, 3930 /// (Taskloops only) Stride. 3931 KmpTaskTStride, 3932 /// (Taskloops only) Is last iteration flag. 3933 KmpTaskTLastIter, 3934 /// (Taskloops only) Reduction data. 3935 KmpTaskTReductions, 3936 }; 3937 } // anonymous namespace 3938 3939 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3940 return OffloadEntriesTargetRegion.empty() && 3941 OffloadEntriesDeviceGlobalVar.empty(); 3942 } 3943 3944 /// Initialize target region entry. 3945 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3946 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3947 StringRef ParentName, unsigned LineNum, 3948 unsigned Order) { 3949 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3950 "only required for the device " 3951 "code generation."); 3952 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3953 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3954 OMPTargetRegionEntryTargetRegion); 3955 ++OffloadingEntriesNum; 3956 } 3957 3958 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3959 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3960 StringRef ParentName, unsigned LineNum, 3961 llvm::Constant *Addr, llvm::Constant *ID, 3962 OMPTargetRegionEntryKind Flags) { 3963 // If we are emitting code for a target, the entry is already initialized, 3964 // only has to be registered. 3965 if (CGM.getLangOpts().OpenMPIsDevice) { 3966 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3967 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3968 DiagnosticsEngine::Error, 3969 "Unable to find target region on line '%0' in the device code."); 3970 CGM.getDiags().Report(DiagID) << LineNum; 3971 return; 3972 } 3973 auto &Entry = 3974 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3975 assert(Entry.isValid() && "Entry not initialized!"); 3976 Entry.setAddress(Addr); 3977 Entry.setID(ID); 3978 Entry.setFlags(Flags); 3979 } else { 3980 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3981 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3982 ++OffloadingEntriesNum; 3983 } 3984 } 3985 3986 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3987 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3988 unsigned LineNum) const { 3989 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3990 if (PerDevice == OffloadEntriesTargetRegion.end()) 3991 return false; 3992 auto PerFile = PerDevice->second.find(FileID); 3993 if (PerFile == PerDevice->second.end()) 3994 return false; 3995 auto PerParentName = PerFile->second.find(ParentName); 3996 if (PerParentName == PerFile->second.end()) 3997 return false; 3998 auto PerLine = PerParentName->second.find(LineNum); 3999 if (PerLine == PerParentName->second.end()) 4000 return false; 4001 // Fail if this entry is already registered. 4002 if (PerLine->second.getAddress() || PerLine->second.getID()) 4003 return false; 4004 return true; 4005 } 4006 4007 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 4008 const OffloadTargetRegionEntryInfoActTy &Action) { 4009 // Scan all target region entries and perform the provided action. 4010 for (const auto &D : OffloadEntriesTargetRegion) 4011 for (const auto &F : D.second) 4012 for (const auto &P : F.second) 4013 for (const auto &L : P.second) 4014 Action(D.first, F.first, P.first(), L.first, L.second); 4015 } 4016 4017 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4018 initializeDeviceGlobalVarEntryInfo(StringRef Name, 4019 OMPTargetGlobalVarEntryKind Flags, 4020 unsigned Order) { 4021 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 4022 "only required for the device " 4023 "code generation."); 4024 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 4025 ++OffloadingEntriesNum; 4026 } 4027 4028 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4029 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 4030 CharUnits VarSize, 4031 OMPTargetGlobalVarEntryKind Flags, 4032 llvm::GlobalValue::LinkageTypes Linkage) { 4033 if (CGM.getLangOpts().OpenMPIsDevice) { 4034 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4035 assert(Entry.isValid() && Entry.getFlags() == Flags && 4036 "Entry not initialized!"); 4037 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4038 "Resetting with the new address."); 4039 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 4040 if (Entry.getVarSize().isZero()) { 4041 Entry.setVarSize(VarSize); 4042 Entry.setLinkage(Linkage); 4043 } 4044 return; 4045 } 4046 Entry.setVarSize(VarSize); 4047 Entry.setLinkage(Linkage); 4048 Entry.setAddress(Addr); 4049 } else { 4050 if (hasDeviceGlobalVarEntryInfo(VarName)) { 4051 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4052 assert(Entry.isValid() && Entry.getFlags() == Flags && 4053 "Entry not initialized!"); 4054 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4055 "Resetting with the new address."); 4056 if (Entry.getVarSize().isZero()) { 4057 Entry.setVarSize(VarSize); 4058 Entry.setLinkage(Linkage); 4059 } 4060 return; 4061 } 4062 OffloadEntriesDeviceGlobalVar.try_emplace( 4063 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 4064 ++OffloadingEntriesNum; 4065 } 4066 } 4067 4068 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4069 actOnDeviceGlobalVarEntriesInfo( 4070 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4071 // Scan all target region entries and perform the provided action. 4072 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4073 Action(E.getKey(), E.getValue()); 4074 } 4075 4076 void CGOpenMPRuntime::createOffloadEntry( 4077 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4078 llvm::GlobalValue::LinkageTypes Linkage) { 4079 StringRef Name = Addr->getName(); 4080 llvm::Module &M = CGM.getModule(); 4081 llvm::LLVMContext &C = M.getContext(); 4082 4083 // Create constant string with the name. 4084 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4085 4086 std::string StringName = getName({"omp_offloading", "entry_name"}); 4087 auto *Str = new llvm::GlobalVariable( 4088 M, StrPtrInit->getType(), /*isConstant=*/true, 4089 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4090 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4091 4092 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4093 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4094 llvm::ConstantInt::get(CGM.SizeTy, Size), 4095 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4096 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4097 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4098 llvm::GlobalVariable *Entry = createGlobalStruct( 4099 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4100 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4101 4102 // The entry has to be created in the section the linker expects it to be. 4103 Entry->setSection("omp_offloading_entries"); 4104 } 4105 4106 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4107 // Emit the offloading entries and metadata so that the device codegen side 4108 // can easily figure out what to emit. The produced metadata looks like 4109 // this: 4110 // 4111 // !omp_offload.info = !{!1, ...} 4112 // 4113 // Right now we only generate metadata for function that contain target 4114 // regions. 4115 4116 // If we are in simd mode or there are no entries, we don't need to do 4117 // anything. 4118 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4119 return; 4120 4121 llvm::Module &M = CGM.getModule(); 4122 llvm::LLVMContext &C = M.getContext(); 4123 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4124 SourceLocation, StringRef>, 4125 16> 4126 OrderedEntries(OffloadEntriesInfoManager.size()); 4127 llvm::SmallVector<StringRef, 16> ParentFunctions( 4128 OffloadEntriesInfoManager.size()); 4129 4130 // Auxiliary methods to create metadata values and strings. 4131 auto &&GetMDInt = [this](unsigned V) { 4132 return llvm::ConstantAsMetadata::get( 4133 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4134 }; 4135 4136 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4137 4138 // Create the offloading info metadata node. 4139 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4140 4141 // Create function that emits metadata for each target region entry; 4142 auto &&TargetRegionMetadataEmitter = 4143 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4144 &GetMDString]( 4145 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4146 unsigned Line, 4147 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4148 // Generate metadata for target regions. Each entry of this metadata 4149 // contains: 4150 // - Entry 0 -> Kind of this type of metadata (0). 4151 // - Entry 1 -> Device ID of the file where the entry was identified. 4152 // - Entry 2 -> File ID of the file where the entry was identified. 4153 // - Entry 3 -> Mangled name of the function where the entry was 4154 // identified. 4155 // - Entry 4 -> Line in the file where the entry was identified. 4156 // - Entry 5 -> Order the entry was created. 4157 // The first element of the metadata node is the kind. 4158 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4159 GetMDInt(FileID), GetMDString(ParentName), 4160 GetMDInt(Line), GetMDInt(E.getOrder())}; 4161 4162 SourceLocation Loc; 4163 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4164 E = CGM.getContext().getSourceManager().fileinfo_end(); 4165 I != E; ++I) { 4166 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4167 I->getFirst()->getUniqueID().getFile() == FileID) { 4168 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4169 I->getFirst(), Line, 1); 4170 break; 4171 } 4172 } 4173 // Save this entry in the right position of the ordered entries array. 4174 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4175 ParentFunctions[E.getOrder()] = ParentName; 4176 4177 // Add metadata to the named metadata node. 4178 MD->addOperand(llvm::MDNode::get(C, Ops)); 4179 }; 4180 4181 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4182 TargetRegionMetadataEmitter); 4183 4184 // Create function that emits metadata for each device global variable entry; 4185 auto &&DeviceGlobalVarMetadataEmitter = 4186 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4187 MD](StringRef MangledName, 4188 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4189 &E) { 4190 // Generate metadata for global variables. Each entry of this metadata 4191 // contains: 4192 // - Entry 0 -> Kind of this type of metadata (1). 4193 // - Entry 1 -> Mangled name of the variable. 4194 // - Entry 2 -> Declare target kind. 4195 // - Entry 3 -> Order the entry was created. 4196 // The first element of the metadata node is the kind. 4197 llvm::Metadata *Ops[] = { 4198 GetMDInt(E.getKind()), GetMDString(MangledName), 4199 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4200 4201 // Save this entry in the right position of the ordered entries array. 4202 OrderedEntries[E.getOrder()] = 4203 std::make_tuple(&E, SourceLocation(), MangledName); 4204 4205 // Add metadata to the named metadata node. 4206 MD->addOperand(llvm::MDNode::get(C, Ops)); 4207 }; 4208 4209 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4210 DeviceGlobalVarMetadataEmitter); 4211 4212 for (const auto &E : OrderedEntries) { 4213 assert(std::get<0>(E) && "All ordered entries must exist!"); 4214 if (const auto *CE = 4215 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4216 std::get<0>(E))) { 4217 if (!CE->getID() || !CE->getAddress()) { 4218 // Do not blame the entry if the parent funtion is not emitted. 4219 StringRef FnName = ParentFunctions[CE->getOrder()]; 4220 if (!CGM.GetGlobalValue(FnName)) 4221 continue; 4222 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4223 DiagnosticsEngine::Error, 4224 "Offloading entry for target region in %0 is incorrect: either the " 4225 "address or the ID is invalid."); 4226 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4227 continue; 4228 } 4229 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4230 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4231 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4232 OffloadEntryInfoDeviceGlobalVar>( 4233 std::get<0>(E))) { 4234 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4235 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4236 CE->getFlags()); 4237 switch (Flags) { 4238 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4239 if (CGM.getLangOpts().OpenMPIsDevice && 4240 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4241 continue; 4242 if (!CE->getAddress()) { 4243 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4244 DiagnosticsEngine::Error, "Offloading entry for declare target " 4245 "variable %0 is incorrect: the " 4246 "address is invalid."); 4247 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4248 continue; 4249 } 4250 // The vaiable has no definition - no need to add the entry. 4251 if (CE->getVarSize().isZero()) 4252 continue; 4253 break; 4254 } 4255 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4256 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4257 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4258 "Declaret target link address is set."); 4259 if (CGM.getLangOpts().OpenMPIsDevice) 4260 continue; 4261 if (!CE->getAddress()) { 4262 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4263 DiagnosticsEngine::Error, 4264 "Offloading entry for declare target variable is incorrect: the " 4265 "address is invalid."); 4266 CGM.getDiags().Report(DiagID); 4267 continue; 4268 } 4269 break; 4270 } 4271 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4272 CE->getVarSize().getQuantity(), Flags, 4273 CE->getLinkage()); 4274 } else { 4275 llvm_unreachable("Unsupported entry kind."); 4276 } 4277 } 4278 } 4279 4280 /// Loads all the offload entries information from the host IR 4281 /// metadata. 4282 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4283 // If we are in target mode, load the metadata from the host IR. This code has 4284 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4285 4286 if (!CGM.getLangOpts().OpenMPIsDevice) 4287 return; 4288 4289 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4290 return; 4291 4292 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4293 if (auto EC = Buf.getError()) { 4294 CGM.getDiags().Report(diag::err_cannot_open_file) 4295 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4296 return; 4297 } 4298 4299 llvm::LLVMContext C; 4300 auto ME = expectedToErrorOrAndEmitErrors( 4301 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4302 4303 if (auto EC = ME.getError()) { 4304 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4305 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4306 CGM.getDiags().Report(DiagID) 4307 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4308 return; 4309 } 4310 4311 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4312 if (!MD) 4313 return; 4314 4315 for (llvm::MDNode *MN : MD->operands()) { 4316 auto &&GetMDInt = [MN](unsigned Idx) { 4317 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4318 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4319 }; 4320 4321 auto &&GetMDString = [MN](unsigned Idx) { 4322 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4323 return V->getString(); 4324 }; 4325 4326 switch (GetMDInt(0)) { 4327 default: 4328 llvm_unreachable("Unexpected metadata!"); 4329 break; 4330 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4331 OffloadingEntryInfoTargetRegion: 4332 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4333 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4334 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4335 /*Order=*/GetMDInt(5)); 4336 break; 4337 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4338 OffloadingEntryInfoDeviceGlobalVar: 4339 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4340 /*MangledName=*/GetMDString(1), 4341 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4342 /*Flags=*/GetMDInt(2)), 4343 /*Order=*/GetMDInt(3)); 4344 break; 4345 } 4346 } 4347 } 4348 4349 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4350 if (!KmpRoutineEntryPtrTy) { 4351 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4352 ASTContext &C = CGM.getContext(); 4353 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4354 FunctionProtoType::ExtProtoInfo EPI; 4355 KmpRoutineEntryPtrQTy = C.getPointerType( 4356 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4357 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4358 } 4359 } 4360 4361 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4362 // Make sure the type of the entry is already created. This is the type we 4363 // have to create: 4364 // struct __tgt_offload_entry{ 4365 // void *addr; // Pointer to the offload entry info. 4366 // // (function or global) 4367 // char *name; // Name of the function or global. 4368 // size_t size; // Size of the entry info (0 if it a function). 4369 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4370 // int32_t reserved; // Reserved, to use by the runtime library. 4371 // }; 4372 if (TgtOffloadEntryQTy.isNull()) { 4373 ASTContext &C = CGM.getContext(); 4374 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4375 RD->startDefinition(); 4376 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4377 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4378 addFieldToRecordDecl(C, RD, C.getSizeType()); 4379 addFieldToRecordDecl( 4380 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4381 addFieldToRecordDecl( 4382 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4383 RD->completeDefinition(); 4384 RD->addAttr(PackedAttr::CreateImplicit(C)); 4385 TgtOffloadEntryQTy = C.getRecordType(RD); 4386 } 4387 return TgtOffloadEntryQTy; 4388 } 4389 4390 namespace { 4391 struct PrivateHelpersTy { 4392 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4393 const VarDecl *PrivateElemInit) 4394 : Original(Original), PrivateCopy(PrivateCopy), 4395 PrivateElemInit(PrivateElemInit) {} 4396 const VarDecl *Original; 4397 const VarDecl *PrivateCopy; 4398 const VarDecl *PrivateElemInit; 4399 }; 4400 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4401 } // anonymous namespace 4402 4403 static RecordDecl * 4404 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4405 if (!Privates.empty()) { 4406 ASTContext &C = CGM.getContext(); 4407 // Build struct .kmp_privates_t. { 4408 // /* private vars */ 4409 // }; 4410 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4411 RD->startDefinition(); 4412 for (const auto &Pair : Privates) { 4413 const VarDecl *VD = Pair.second.Original; 4414 QualType Type = VD->getType().getNonReferenceType(); 4415 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4416 if (VD->hasAttrs()) { 4417 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4418 E(VD->getAttrs().end()); 4419 I != E; ++I) 4420 FD->addAttr(*I); 4421 } 4422 } 4423 RD->completeDefinition(); 4424 return RD; 4425 } 4426 return nullptr; 4427 } 4428 4429 static RecordDecl * 4430 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4431 QualType KmpInt32Ty, 4432 QualType KmpRoutineEntryPointerQTy) { 4433 ASTContext &C = CGM.getContext(); 4434 // Build struct kmp_task_t { 4435 // void * shareds; 4436 // kmp_routine_entry_t routine; 4437 // kmp_int32 part_id; 4438 // kmp_cmplrdata_t data1; 4439 // kmp_cmplrdata_t data2; 4440 // For taskloops additional fields: 4441 // kmp_uint64 lb; 4442 // kmp_uint64 ub; 4443 // kmp_int64 st; 4444 // kmp_int32 liter; 4445 // void * reductions; 4446 // }; 4447 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4448 UD->startDefinition(); 4449 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4450 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4451 UD->completeDefinition(); 4452 QualType KmpCmplrdataTy = C.getRecordType(UD); 4453 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4454 RD->startDefinition(); 4455 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4456 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4457 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4458 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4459 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4460 if (isOpenMPTaskLoopDirective(Kind)) { 4461 QualType KmpUInt64Ty = 4462 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4463 QualType KmpInt64Ty = 4464 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4465 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4466 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4467 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4468 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4469 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4470 } 4471 RD->completeDefinition(); 4472 return RD; 4473 } 4474 4475 static RecordDecl * 4476 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4477 ArrayRef<PrivateDataTy> Privates) { 4478 ASTContext &C = CGM.getContext(); 4479 // Build struct kmp_task_t_with_privates { 4480 // kmp_task_t task_data; 4481 // .kmp_privates_t. privates; 4482 // }; 4483 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4484 RD->startDefinition(); 4485 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4486 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4487 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4488 RD->completeDefinition(); 4489 return RD; 4490 } 4491 4492 /// Emit a proxy function which accepts kmp_task_t as the second 4493 /// argument. 4494 /// \code 4495 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4496 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4497 /// For taskloops: 4498 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4499 /// tt->reductions, tt->shareds); 4500 /// return 0; 4501 /// } 4502 /// \endcode 4503 static llvm::Function * 4504 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4505 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4506 QualType KmpTaskTWithPrivatesPtrQTy, 4507 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4508 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4509 llvm::Value *TaskPrivatesMap) { 4510 ASTContext &C = CGM.getContext(); 4511 FunctionArgList Args; 4512 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4513 ImplicitParamDecl::Other); 4514 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4515 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4516 ImplicitParamDecl::Other); 4517 Args.push_back(&GtidArg); 4518 Args.push_back(&TaskTypeArg); 4519 const auto &TaskEntryFnInfo = 4520 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4521 llvm::FunctionType *TaskEntryTy = 4522 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4523 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4524 auto *TaskEntry = llvm::Function::Create( 4525 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4526 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4527 TaskEntry->setDoesNotRecurse(); 4528 CodeGenFunction CGF(CGM); 4529 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4530 Loc, Loc); 4531 4532 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4533 // tt, 4534 // For taskloops: 4535 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4536 // tt->task_data.shareds); 4537 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4538 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4539 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4540 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4541 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4542 const auto *KmpTaskTWithPrivatesQTyRD = 4543 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4544 LValue Base = 4545 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4546 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4547 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4548 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4549 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 4550 4551 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4552 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4553 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4554 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4555 CGF.ConvertTypeForMem(SharedsPtrTy)); 4556 4557 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4558 llvm::Value *PrivatesParam; 4559 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4560 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4561 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4562 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 4563 } else { 4564 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4565 } 4566 4567 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4568 TaskPrivatesMap, 4569 CGF.Builder 4570 .CreatePointerBitCastOrAddrSpaceCast( 4571 TDBase.getAddress(CGF), CGF.VoidPtrTy) 4572 .getPointer()}; 4573 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4574 std::end(CommonArgs)); 4575 if (isOpenMPTaskLoopDirective(Kind)) { 4576 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4577 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4578 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4579 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4580 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4581 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4582 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4583 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4584 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4585 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4586 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4587 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4588 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4589 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4590 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4591 CallArgs.push_back(LBParam); 4592 CallArgs.push_back(UBParam); 4593 CallArgs.push_back(StParam); 4594 CallArgs.push_back(LIParam); 4595 CallArgs.push_back(RParam); 4596 } 4597 CallArgs.push_back(SharedsParam); 4598 4599 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4600 CallArgs); 4601 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4602 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4603 CGF.FinishFunction(); 4604 return TaskEntry; 4605 } 4606 4607 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4608 SourceLocation Loc, 4609 QualType KmpInt32Ty, 4610 QualType KmpTaskTWithPrivatesPtrQTy, 4611 QualType KmpTaskTWithPrivatesQTy) { 4612 ASTContext &C = CGM.getContext(); 4613 FunctionArgList Args; 4614 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4615 ImplicitParamDecl::Other); 4616 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4617 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4618 ImplicitParamDecl::Other); 4619 Args.push_back(&GtidArg); 4620 Args.push_back(&TaskTypeArg); 4621 const auto &DestructorFnInfo = 4622 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4623 llvm::FunctionType *DestructorFnTy = 4624 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4625 std::string Name = 4626 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4627 auto *DestructorFn = 4628 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4629 Name, &CGM.getModule()); 4630 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4631 DestructorFnInfo); 4632 DestructorFn->setDoesNotRecurse(); 4633 CodeGenFunction CGF(CGM); 4634 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4635 Args, Loc, Loc); 4636 4637 LValue Base = CGF.EmitLoadOfPointerLValue( 4638 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4639 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4640 const auto *KmpTaskTWithPrivatesQTyRD = 4641 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4642 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4643 Base = CGF.EmitLValueForField(Base, *FI); 4644 for (const auto *Field : 4645 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4646 if (QualType::DestructionKind DtorKind = 4647 Field->getType().isDestructedType()) { 4648 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4649 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 4650 } 4651 } 4652 CGF.FinishFunction(); 4653 return DestructorFn; 4654 } 4655 4656 /// Emit a privates mapping function for correct handling of private and 4657 /// firstprivate variables. 4658 /// \code 4659 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4660 /// **noalias priv1,..., <tyn> **noalias privn) { 4661 /// *priv1 = &.privates.priv1; 4662 /// ...; 4663 /// *privn = &.privates.privn; 4664 /// } 4665 /// \endcode 4666 static llvm::Value * 4667 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4668 ArrayRef<const Expr *> PrivateVars, 4669 ArrayRef<const Expr *> FirstprivateVars, 4670 ArrayRef<const Expr *> LastprivateVars, 4671 QualType PrivatesQTy, 4672 ArrayRef<PrivateDataTy> Privates) { 4673 ASTContext &C = CGM.getContext(); 4674 FunctionArgList Args; 4675 ImplicitParamDecl TaskPrivatesArg( 4676 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4677 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4678 ImplicitParamDecl::Other); 4679 Args.push_back(&TaskPrivatesArg); 4680 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4681 unsigned Counter = 1; 4682 for (const Expr *E : PrivateVars) { 4683 Args.push_back(ImplicitParamDecl::Create( 4684 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4685 C.getPointerType(C.getPointerType(E->getType())) 4686 .withConst() 4687 .withRestrict(), 4688 ImplicitParamDecl::Other)); 4689 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4690 PrivateVarsPos[VD] = Counter; 4691 ++Counter; 4692 } 4693 for (const Expr *E : FirstprivateVars) { 4694 Args.push_back(ImplicitParamDecl::Create( 4695 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4696 C.getPointerType(C.getPointerType(E->getType())) 4697 .withConst() 4698 .withRestrict(), 4699 ImplicitParamDecl::Other)); 4700 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4701 PrivateVarsPos[VD] = Counter; 4702 ++Counter; 4703 } 4704 for (const Expr *E : LastprivateVars) { 4705 Args.push_back(ImplicitParamDecl::Create( 4706 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4707 C.getPointerType(C.getPointerType(E->getType())) 4708 .withConst() 4709 .withRestrict(), 4710 ImplicitParamDecl::Other)); 4711 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4712 PrivateVarsPos[VD] = Counter; 4713 ++Counter; 4714 } 4715 const auto &TaskPrivatesMapFnInfo = 4716 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4717 llvm::FunctionType *TaskPrivatesMapTy = 4718 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4719 std::string Name = 4720 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4721 auto *TaskPrivatesMap = llvm::Function::Create( 4722 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4723 &CGM.getModule()); 4724 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4725 TaskPrivatesMapFnInfo); 4726 if (CGM.getLangOpts().Optimize) { 4727 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4728 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4729 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4730 } 4731 CodeGenFunction CGF(CGM); 4732 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4733 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4734 4735 // *privi = &.privates.privi; 4736 LValue Base = CGF.EmitLoadOfPointerLValue( 4737 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4738 TaskPrivatesArg.getType()->castAs<PointerType>()); 4739 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4740 Counter = 0; 4741 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4742 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4743 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4744 LValue RefLVal = 4745 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4746 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4747 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 4748 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 4749 ++Counter; 4750 } 4751 CGF.FinishFunction(); 4752 return TaskPrivatesMap; 4753 } 4754 4755 /// Emit initialization for private variables in task-based directives. 4756 static void emitPrivatesInit(CodeGenFunction &CGF, 4757 const OMPExecutableDirective &D, 4758 Address KmpTaskSharedsPtr, LValue TDBase, 4759 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4760 QualType SharedsTy, QualType SharedsPtrTy, 4761 const OMPTaskDataTy &Data, 4762 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4763 ASTContext &C = CGF.getContext(); 4764 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4765 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4766 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4767 ? OMPD_taskloop 4768 : OMPD_task; 4769 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4770 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4771 LValue SrcBase; 4772 bool IsTargetTask = 4773 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4774 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4775 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4776 // PointersArray and SizesArray. The original variables for these arrays are 4777 // not captured and we get their addresses explicitly. 4778 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4779 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4780 SrcBase = CGF.MakeAddrLValue( 4781 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4782 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4783 SharedsTy); 4784 } 4785 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4786 for (const PrivateDataTy &Pair : Privates) { 4787 const VarDecl *VD = Pair.second.PrivateCopy; 4788 const Expr *Init = VD->getAnyInitializer(); 4789 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4790 !CGF.isTrivialInitializer(Init)))) { 4791 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4792 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4793 const VarDecl *OriginalVD = Pair.second.Original; 4794 // Check if the variable is the target-based BasePointersArray, 4795 // PointersArray or SizesArray. 4796 LValue SharedRefLValue; 4797 QualType Type = PrivateLValue.getType(); 4798 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4799 if (IsTargetTask && !SharedField) { 4800 assert(isa<ImplicitParamDecl>(OriginalVD) && 4801 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4802 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4803 ->getNumParams() == 0 && 4804 isa<TranslationUnitDecl>( 4805 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4806 ->getDeclContext()) && 4807 "Expected artificial target data variable."); 4808 SharedRefLValue = 4809 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4810 } else { 4811 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4812 SharedRefLValue = CGF.MakeAddrLValue( 4813 Address(SharedRefLValue.getPointer(CGF), 4814 C.getDeclAlign(OriginalVD)), 4815 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4816 SharedRefLValue.getTBAAInfo()); 4817 } 4818 if (Type->isArrayType()) { 4819 // Initialize firstprivate array. 4820 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4821 // Perform simple memcpy. 4822 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4823 } else { 4824 // Initialize firstprivate array using element-by-element 4825 // initialization. 4826 CGF.EmitOMPAggregateAssign( 4827 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 4828 Type, 4829 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4830 Address SrcElement) { 4831 // Clean up any temporaries needed by the initialization. 4832 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4833 InitScope.addPrivate( 4834 Elem, [SrcElement]() -> Address { return SrcElement; }); 4835 (void)InitScope.Privatize(); 4836 // Emit initialization for single element. 4837 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4838 CGF, &CapturesInfo); 4839 CGF.EmitAnyExprToMem(Init, DestElement, 4840 Init->getType().getQualifiers(), 4841 /*IsInitializer=*/false); 4842 }); 4843 } 4844 } else { 4845 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4846 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 4847 return SharedRefLValue.getAddress(CGF); 4848 }); 4849 (void)InitScope.Privatize(); 4850 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4851 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4852 /*capturedByInit=*/false); 4853 } 4854 } else { 4855 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4856 } 4857 } 4858 ++FI; 4859 } 4860 } 4861 4862 /// Check if duplication function is required for taskloops. 4863 static bool checkInitIsRequired(CodeGenFunction &CGF, 4864 ArrayRef<PrivateDataTy> Privates) { 4865 bool InitRequired = false; 4866 for (const PrivateDataTy &Pair : Privates) { 4867 const VarDecl *VD = Pair.second.PrivateCopy; 4868 const Expr *Init = VD->getAnyInitializer(); 4869 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4870 !CGF.isTrivialInitializer(Init)); 4871 if (InitRequired) 4872 break; 4873 } 4874 return InitRequired; 4875 } 4876 4877 4878 /// Emit task_dup function (for initialization of 4879 /// private/firstprivate/lastprivate vars and last_iter flag) 4880 /// \code 4881 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4882 /// lastpriv) { 4883 /// // setup lastprivate flag 4884 /// task_dst->last = lastpriv; 4885 /// // could be constructor calls here... 4886 /// } 4887 /// \endcode 4888 static llvm::Value * 4889 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4890 const OMPExecutableDirective &D, 4891 QualType KmpTaskTWithPrivatesPtrQTy, 4892 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4893 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4894 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4895 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4896 ASTContext &C = CGM.getContext(); 4897 FunctionArgList Args; 4898 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4899 KmpTaskTWithPrivatesPtrQTy, 4900 ImplicitParamDecl::Other); 4901 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4902 KmpTaskTWithPrivatesPtrQTy, 4903 ImplicitParamDecl::Other); 4904 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4905 ImplicitParamDecl::Other); 4906 Args.push_back(&DstArg); 4907 Args.push_back(&SrcArg); 4908 Args.push_back(&LastprivArg); 4909 const auto &TaskDupFnInfo = 4910 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4911 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4912 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4913 auto *TaskDup = llvm::Function::Create( 4914 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4915 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4916 TaskDup->setDoesNotRecurse(); 4917 CodeGenFunction CGF(CGM); 4918 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4919 Loc); 4920 4921 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4922 CGF.GetAddrOfLocalVar(&DstArg), 4923 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4924 // task_dst->liter = lastpriv; 4925 if (WithLastIter) { 4926 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4927 LValue Base = CGF.EmitLValueForField( 4928 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4929 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4930 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4931 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4932 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4933 } 4934 4935 // Emit initial values for private copies (if any). 4936 assert(!Privates.empty()); 4937 Address KmpTaskSharedsPtr = Address::invalid(); 4938 if (!Data.FirstprivateVars.empty()) { 4939 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4940 CGF.GetAddrOfLocalVar(&SrcArg), 4941 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4942 LValue Base = CGF.EmitLValueForField( 4943 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4944 KmpTaskSharedsPtr = Address( 4945 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4946 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4947 KmpTaskTShareds)), 4948 Loc), 4949 CGF.getNaturalTypeAlignment(SharedsTy)); 4950 } 4951 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4952 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4953 CGF.FinishFunction(); 4954 return TaskDup; 4955 } 4956 4957 /// Checks if destructor function is required to be generated. 4958 /// \return true if cleanups are required, false otherwise. 4959 static bool 4960 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4961 bool NeedsCleanup = false; 4962 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4963 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4964 for (const FieldDecl *FD : PrivateRD->fields()) { 4965 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4966 if (NeedsCleanup) 4967 break; 4968 } 4969 return NeedsCleanup; 4970 } 4971 4972 CGOpenMPRuntime::TaskResultTy 4973 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4974 const OMPExecutableDirective &D, 4975 llvm::Function *TaskFunction, QualType SharedsTy, 4976 Address Shareds, const OMPTaskDataTy &Data) { 4977 ASTContext &C = CGM.getContext(); 4978 llvm::SmallVector<PrivateDataTy, 4> Privates; 4979 // Aggregate privates and sort them by the alignment. 4980 auto I = Data.PrivateCopies.begin(); 4981 for (const Expr *E : Data.PrivateVars) { 4982 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4983 Privates.emplace_back( 4984 C.getDeclAlign(VD), 4985 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4986 /*PrivateElemInit=*/nullptr)); 4987 ++I; 4988 } 4989 I = Data.FirstprivateCopies.begin(); 4990 auto IElemInitRef = Data.FirstprivateInits.begin(); 4991 for (const Expr *E : Data.FirstprivateVars) { 4992 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4993 Privates.emplace_back( 4994 C.getDeclAlign(VD), 4995 PrivateHelpersTy( 4996 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4997 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4998 ++I; 4999 ++IElemInitRef; 5000 } 5001 I = Data.LastprivateCopies.begin(); 5002 for (const Expr *E : Data.LastprivateVars) { 5003 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5004 Privates.emplace_back( 5005 C.getDeclAlign(VD), 5006 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5007 /*PrivateElemInit=*/nullptr)); 5008 ++I; 5009 } 5010 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 5011 return L.first > R.first; 5012 }); 5013 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 5014 // Build type kmp_routine_entry_t (if not built yet). 5015 emitKmpRoutineEntryT(KmpInt32Ty); 5016 // Build type kmp_task_t (if not built yet). 5017 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5018 if (SavedKmpTaskloopTQTy.isNull()) { 5019 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5020 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5021 } 5022 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5023 } else { 5024 assert((D.getDirectiveKind() == OMPD_task || 5025 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5026 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5027 "Expected taskloop, task or target directive"); 5028 if (SavedKmpTaskTQTy.isNull()) { 5029 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5030 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5031 } 5032 KmpTaskTQTy = SavedKmpTaskTQTy; 5033 } 5034 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5035 // Build particular struct kmp_task_t for the given task. 5036 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5037 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5038 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5039 QualType KmpTaskTWithPrivatesPtrQTy = 5040 C.getPointerType(KmpTaskTWithPrivatesQTy); 5041 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5042 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5043 KmpTaskTWithPrivatesTy->getPointerTo(); 5044 llvm::Value *KmpTaskTWithPrivatesTySize = 5045 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5046 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5047 5048 // Emit initial values for private copies (if any). 5049 llvm::Value *TaskPrivatesMap = nullptr; 5050 llvm::Type *TaskPrivatesMapTy = 5051 std::next(TaskFunction->arg_begin(), 3)->getType(); 5052 if (!Privates.empty()) { 5053 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5054 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5055 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5056 FI->getType(), Privates); 5057 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5058 TaskPrivatesMap, TaskPrivatesMapTy); 5059 } else { 5060 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5061 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5062 } 5063 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5064 // kmp_task_t *tt); 5065 llvm::Function *TaskEntry = emitProxyTaskFunction( 5066 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5067 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5068 TaskPrivatesMap); 5069 5070 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5071 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5072 // kmp_routine_entry_t *task_entry); 5073 // Task flags. Format is taken from 5074 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5075 // description of kmp_tasking_flags struct. 5076 enum { 5077 TiedFlag = 0x1, 5078 FinalFlag = 0x2, 5079 DestructorsFlag = 0x8, 5080 PriorityFlag = 0x20 5081 }; 5082 unsigned Flags = Data.Tied ? TiedFlag : 0; 5083 bool NeedsCleanup = false; 5084 if (!Privates.empty()) { 5085 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5086 if (NeedsCleanup) 5087 Flags = Flags | DestructorsFlag; 5088 } 5089 if (Data.Priority.getInt()) 5090 Flags = Flags | PriorityFlag; 5091 llvm::Value *TaskFlags = 5092 Data.Final.getPointer() 5093 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5094 CGF.Builder.getInt32(FinalFlag), 5095 CGF.Builder.getInt32(/*C=*/0)) 5096 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5097 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5098 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5099 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5100 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5101 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5102 TaskEntry, KmpRoutineEntryPtrTy)}; 5103 llvm::Value *NewTask; 5104 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5105 // Check if we have any device clause associated with the directive. 5106 const Expr *Device = nullptr; 5107 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5108 Device = C->getDevice(); 5109 // Emit device ID if any otherwise use default value. 5110 llvm::Value *DeviceID; 5111 if (Device) 5112 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5113 CGF.Int64Ty, /*isSigned=*/true); 5114 else 5115 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5116 AllocArgs.push_back(DeviceID); 5117 NewTask = CGF.EmitRuntimeCall( 5118 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5119 } else { 5120 NewTask = CGF.EmitRuntimeCall( 5121 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5122 } 5123 llvm::Value *NewTaskNewTaskTTy = 5124 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5125 NewTask, KmpTaskTWithPrivatesPtrTy); 5126 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5127 KmpTaskTWithPrivatesQTy); 5128 LValue TDBase = 5129 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5130 // Fill the data in the resulting kmp_task_t record. 5131 // Copy shareds if there are any. 5132 Address KmpTaskSharedsPtr = Address::invalid(); 5133 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5134 KmpTaskSharedsPtr = 5135 Address(CGF.EmitLoadOfScalar( 5136 CGF.EmitLValueForField( 5137 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5138 KmpTaskTShareds)), 5139 Loc), 5140 CGF.getNaturalTypeAlignment(SharedsTy)); 5141 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5142 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5143 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5144 } 5145 // Emit initial values for private copies (if any). 5146 TaskResultTy Result; 5147 if (!Privates.empty()) { 5148 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5149 SharedsTy, SharedsPtrTy, Data, Privates, 5150 /*ForDup=*/false); 5151 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5152 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5153 Result.TaskDupFn = emitTaskDupFunction( 5154 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5155 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5156 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5157 } 5158 } 5159 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5160 enum { Priority = 0, Destructors = 1 }; 5161 // Provide pointer to function with destructors for privates. 5162 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5163 const RecordDecl *KmpCmplrdataUD = 5164 (*FI)->getType()->getAsUnionType()->getDecl(); 5165 if (NeedsCleanup) { 5166 llvm::Value *DestructorFn = emitDestructorsFunction( 5167 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5168 KmpTaskTWithPrivatesQTy); 5169 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5170 LValue DestructorsLV = CGF.EmitLValueForField( 5171 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5172 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5173 DestructorFn, KmpRoutineEntryPtrTy), 5174 DestructorsLV); 5175 } 5176 // Set priority. 5177 if (Data.Priority.getInt()) { 5178 LValue Data2LV = CGF.EmitLValueForField( 5179 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5180 LValue PriorityLV = CGF.EmitLValueForField( 5181 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5182 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5183 } 5184 Result.NewTask = NewTask; 5185 Result.TaskEntry = TaskEntry; 5186 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5187 Result.TDBase = TDBase; 5188 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5189 return Result; 5190 } 5191 5192 namespace { 5193 /// Dependence kind for RTL. 5194 enum RTLDependenceKindTy { 5195 DepIn = 0x01, 5196 DepInOut = 0x3, 5197 DepMutexInOutSet = 0x4 5198 }; 5199 /// Fields ids in kmp_depend_info record. 5200 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5201 } // namespace 5202 5203 /// Translates internal dependency kind into the runtime kind. 5204 static RTLDependenceKindTy translateDependencyKind(OpenMPDependClauseKind K) { 5205 RTLDependenceKindTy DepKind; 5206 switch (K) { 5207 case OMPC_DEPEND_in: 5208 DepKind = DepIn; 5209 break; 5210 // Out and InOut dependencies must use the same code. 5211 case OMPC_DEPEND_out: 5212 case OMPC_DEPEND_inout: 5213 DepKind = DepInOut; 5214 break; 5215 case OMPC_DEPEND_mutexinoutset: 5216 DepKind = DepMutexInOutSet; 5217 break; 5218 case OMPC_DEPEND_source: 5219 case OMPC_DEPEND_sink: 5220 case OMPC_DEPEND_depobj: 5221 case OMPC_DEPEND_unknown: 5222 llvm_unreachable("Unknown task dependence type"); 5223 } 5224 return DepKind; 5225 } 5226 5227 /// Builds kmp_depend_info, if it is not built yet, and builds flags type. 5228 static void getDependTypes(ASTContext &C, QualType &KmpDependInfoTy, 5229 QualType &FlagsTy) { 5230 FlagsTy = C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5231 if (KmpDependInfoTy.isNull()) { 5232 RecordDecl *KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5233 KmpDependInfoRD->startDefinition(); 5234 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5235 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5236 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5237 KmpDependInfoRD->completeDefinition(); 5238 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5239 } 5240 } 5241 5242 std::pair<llvm::Value *, LValue> 5243 CGOpenMPRuntime::getDepobjElements(CodeGenFunction &CGF, LValue DepobjLVal, 5244 SourceLocation Loc) { 5245 ASTContext &C = CGM.getContext(); 5246 QualType FlagsTy; 5247 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5248 RecordDecl *KmpDependInfoRD = 5249 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5250 LValue Base = CGF.EmitLoadOfPointerLValue( 5251 DepobjLVal.getAddress(CGF), 5252 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5253 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5254 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5255 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 5256 Base = CGF.MakeAddrLValue(Addr, KmpDependInfoTy, Base.getBaseInfo(), 5257 Base.getTBAAInfo()); 5258 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5259 Addr.getPointer(), 5260 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5261 LValue NumDepsBase = CGF.MakeAddrLValue( 5262 Address(DepObjAddr, Addr.getAlignment()), KmpDependInfoTy, 5263 Base.getBaseInfo(), Base.getTBAAInfo()); 5264 // NumDeps = deps[i].base_addr; 5265 LValue BaseAddrLVal = CGF.EmitLValueForField( 5266 NumDepsBase, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5267 llvm::Value *NumDeps = CGF.EmitLoadOfScalar(BaseAddrLVal, Loc); 5268 return std::make_pair(NumDeps, Base); 5269 } 5270 5271 std::pair<llvm::Value *, Address> CGOpenMPRuntime::emitDependClause( 5272 CodeGenFunction &CGF, 5273 ArrayRef<std::pair<OpenMPDependClauseKind, const Expr *>> Dependencies, 5274 bool ForDepobj, SourceLocation Loc) { 5275 // Process list of dependencies. 5276 ASTContext &C = CGM.getContext(); 5277 Address DependenciesArray = Address::invalid(); 5278 unsigned NumDependencies = Dependencies.size(); 5279 llvm::Value *NumOfElements = nullptr; 5280 if (NumDependencies) { 5281 QualType FlagsTy; 5282 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5283 RecordDecl *KmpDependInfoRD = 5284 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5285 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5286 unsigned NumDepobjDependecies = 0; 5287 SmallVector<std::pair<llvm::Value *, LValue>, 4> Depobjs; 5288 llvm::Value *NumOfDepobjElements = llvm::ConstantInt::get(CGF.IntPtrTy, 0); 5289 // Calculate number of depobj dependecies. 5290 for (const std::pair<OpenMPDependClauseKind, const Expr *> &Pair : 5291 Dependencies) { 5292 if (Pair.first != OMPC_DEPEND_depobj) 5293 continue; 5294 LValue DepobjLVal = CGF.EmitLValue(Pair.second); 5295 llvm::Value *NumDeps; 5296 LValue Base; 5297 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 5298 NumOfDepobjElements = 5299 CGF.Builder.CreateNUWAdd(NumOfDepobjElements, NumDeps); 5300 Depobjs.emplace_back(NumDeps, Base); 5301 ++NumDepobjDependecies; 5302 } 5303 5304 QualType KmpDependInfoArrayTy; 5305 // Define type kmp_depend_info[<Dependencies.size()>]; 5306 // For depobj reserve one extra element to store the number of elements. 5307 // It is required to handle depobj(x) update(in) construct. 5308 // kmp_depend_info[<Dependencies.size()>] deps; 5309 if (ForDepobj) { 5310 assert(NumDepobjDependecies == 0 && 5311 "depobj dependency kind is not expected in depobj directive."); 5312 KmpDependInfoArrayTy = C.getConstantArrayType( 5313 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies + 1), 5314 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5315 // Need to allocate on the dynamic memory. 5316 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5317 // Use default allocator. 5318 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5319 CharUnits Align = C.getTypeAlignInChars(KmpDependInfoArrayTy); 5320 CharUnits Sz = C.getTypeSizeInChars(KmpDependInfoArrayTy); 5321 llvm::Value *Size = CGF.CGM.getSize(Sz.alignTo(Align)); 5322 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 5323 5324 llvm::Value *Addr = CGF.EmitRuntimeCall( 5325 createRuntimeFunction(OMPRTL__kmpc_alloc), Args, ".dep.arr.addr"); 5326 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5327 Addr, CGF.ConvertTypeForMem(KmpDependInfoArrayTy)->getPointerTo()); 5328 DependenciesArray = Address(Addr, Align); 5329 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 5330 /*isSigned=*/false); 5331 } else if (NumDepobjDependecies > 0) { 5332 NumOfElements = CGF.Builder.CreateNUWAdd( 5333 NumOfDepobjElements, 5334 llvm::ConstantInt::get(CGM.IntPtrTy, 5335 NumDependencies - NumDepobjDependecies, 5336 /*isSigned=*/false)); 5337 NumOfElements = CGF.Builder.CreateIntCast(NumOfElements, CGF.Int32Ty, 5338 /*isSigned=*/false); 5339 OpaqueValueExpr OVE( 5340 Loc, C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0), 5341 VK_RValue); 5342 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, 5343 RValue::get(NumOfElements)); 5344 KmpDependInfoArrayTy = 5345 C.getVariableArrayType(KmpDependInfoTy, &OVE, ArrayType::Normal, 5346 /*IndexTypeQuals=*/0, SourceRange(Loc, Loc)); 5347 // CGF.EmitVariablyModifiedType(KmpDependInfoArrayTy); 5348 // Properly emit variable-sized array. 5349 auto *PD = ImplicitParamDecl::Create(C, KmpDependInfoArrayTy, 5350 ImplicitParamDecl::Other); 5351 CGF.EmitVarDecl(*PD); 5352 DependenciesArray = CGF.GetAddrOfLocalVar(PD); 5353 } else { 5354 KmpDependInfoArrayTy = C.getConstantArrayType( 5355 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5356 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5357 DependenciesArray = 5358 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5359 NumOfElements = llvm::ConstantInt::get(CGM.Int32Ty, NumDependencies, 5360 /*isSigned=*/false); 5361 } 5362 if (ForDepobj) { 5363 // Write number of elements in the first element of array for depobj. 5364 llvm::Value *NumVal = 5365 llvm::ConstantInt::get(CGF.IntPtrTy, NumDependencies); 5366 LValue Base = CGF.MakeAddrLValue( 5367 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), 5368 KmpDependInfoTy); 5369 // deps[i].base_addr = NumDependencies; 5370 LValue BaseAddrLVal = CGF.EmitLValueForField( 5371 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5372 CGF.EmitStoreOfScalar(NumVal, BaseAddrLVal); 5373 } 5374 unsigned Pos = ForDepobj ? 1 : 0; 5375 for (unsigned I = 0; I < NumDependencies; ++I) { 5376 if (Dependencies[I].first == OMPC_DEPEND_depobj) 5377 continue; 5378 const Expr *E = Dependencies[I].second; 5379 LValue Addr = CGF.EmitLValue(E); 5380 llvm::Value *Size; 5381 QualType Ty = E->getType(); 5382 if (const auto *ASE = 5383 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5384 LValue UpAddrLVal = 5385 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5386 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 5387 UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 5388 llvm::Value *LowIntPtr = 5389 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy); 5390 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5391 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5392 } else { 5393 Size = CGF.getTypeSize(Ty); 5394 } 5395 LValue Base; 5396 if (NumDepobjDependecies > 0) { 5397 Base = CGF.MakeAddrLValue( 5398 CGF.Builder.CreateConstGEP(DependenciesArray, Pos), 5399 KmpDependInfoTy); 5400 } else { 5401 Base = CGF.MakeAddrLValue( 5402 CGF.Builder.CreateConstArrayGEP(DependenciesArray, Pos), 5403 KmpDependInfoTy); 5404 } 5405 // deps[i].base_addr = &<Dependencies[i].second>; 5406 LValue BaseAddrLVal = CGF.EmitLValueForField( 5407 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5408 CGF.EmitStoreOfScalar( 5409 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy), 5410 BaseAddrLVal); 5411 // deps[i].len = sizeof(<Dependencies[i].second>); 5412 LValue LenLVal = CGF.EmitLValueForField( 5413 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5414 CGF.EmitStoreOfScalar(Size, LenLVal); 5415 // deps[i].flags = <Dependencies[i].first>; 5416 RTLDependenceKindTy DepKind = 5417 translateDependencyKind(Dependencies[I].first); 5418 LValue FlagsLVal = CGF.EmitLValueForField( 5419 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5420 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5421 FlagsLVal); 5422 ++Pos; 5423 } 5424 // Copy final depobj arrays. 5425 if (NumDepobjDependecies > 0) { 5426 llvm::Value *ElSize = CGF.getTypeSize(KmpDependInfoTy); 5427 Address Addr = CGF.Builder.CreateConstGEP(DependenciesArray, Pos); 5428 for (const std::pair<llvm::Value *, LValue> &Pair : Depobjs) { 5429 llvm::Value *Size = CGF.Builder.CreateNUWMul(ElSize, Pair.first); 5430 CGF.Builder.CreateMemCpy(Addr, Pair.second.getAddress(CGF), Size); 5431 Addr = 5432 Address(CGF.Builder.CreateGEP( 5433 Addr.getElementType(), Addr.getPointer(), Pair.first), 5434 DependenciesArray.getAlignment().alignmentOfArrayElement( 5435 C.getTypeSizeInChars(KmpDependInfoTy))); 5436 } 5437 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5438 DependenciesArray, CGF.VoidPtrTy); 5439 } else { 5440 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5441 CGF.Builder.CreateConstArrayGEP(DependenciesArray, ForDepobj ? 1 : 0), 5442 CGF.VoidPtrTy); 5443 } 5444 } 5445 return std::make_pair(NumOfElements, DependenciesArray); 5446 } 5447 5448 void CGOpenMPRuntime::emitDestroyClause(CodeGenFunction &CGF, LValue DepobjLVal, 5449 SourceLocation Loc) { 5450 ASTContext &C = CGM.getContext(); 5451 QualType FlagsTy; 5452 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5453 LValue Base = CGF.EmitLoadOfPointerLValue( 5454 DepobjLVal.getAddress(CGF), 5455 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 5456 QualType KmpDependInfoPtrTy = C.getPointerType(KmpDependInfoTy); 5457 Address Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5458 Base.getAddress(CGF), CGF.ConvertTypeForMem(KmpDependInfoPtrTy)); 5459 llvm::Value *DepObjAddr = CGF.Builder.CreateGEP( 5460 Addr.getPointer(), 5461 llvm::ConstantInt::get(CGF.IntPtrTy, -1, /*isSigned=*/true)); 5462 DepObjAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(DepObjAddr, 5463 CGF.VoidPtrTy); 5464 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5465 // Use default allocator. 5466 llvm::Value *Allocator = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5467 llvm::Value *Args[] = {ThreadID, DepObjAddr, Allocator}; 5468 5469 // _kmpc_free(gtid, addr, nullptr); 5470 (void)CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_free), Args); 5471 } 5472 5473 void CGOpenMPRuntime::emitUpdateClause(CodeGenFunction &CGF, LValue DepobjLVal, 5474 OpenMPDependClauseKind NewDepKind, 5475 SourceLocation Loc) { 5476 ASTContext &C = CGM.getContext(); 5477 QualType FlagsTy; 5478 getDependTypes(C, KmpDependInfoTy, FlagsTy); 5479 RecordDecl *KmpDependInfoRD = 5480 cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5481 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5482 llvm::Value *NumDeps; 5483 LValue Base; 5484 std::tie(NumDeps, Base) = getDepobjElements(CGF, DepobjLVal, Loc); 5485 5486 Address Begin = Base.getAddress(CGF); 5487 // Cast from pointer to array type to pointer to single element. 5488 llvm::Value *End = CGF.Builder.CreateGEP(Begin.getPointer(), NumDeps); 5489 // The basic structure here is a while-do loop. 5490 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.body"); 5491 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.done"); 5492 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5493 CGF.EmitBlock(BodyBB); 5494 llvm::PHINode *ElementPHI = 5495 CGF.Builder.CreatePHI(Begin.getType(), 2, "omp.elementPast"); 5496 ElementPHI->addIncoming(Begin.getPointer(), EntryBB); 5497 Begin = Address(ElementPHI, Begin.getAlignment()); 5498 Base = CGF.MakeAddrLValue(Begin, KmpDependInfoTy, Base.getBaseInfo(), 5499 Base.getTBAAInfo()); 5500 // deps[i].flags = NewDepKind; 5501 RTLDependenceKindTy DepKind = translateDependencyKind(NewDepKind); 5502 LValue FlagsLVal = CGF.EmitLValueForField( 5503 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5504 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5505 FlagsLVal); 5506 5507 // Shift the address forward by one element. 5508 Address ElementNext = 5509 CGF.Builder.CreateConstGEP(Begin, /*Index=*/1, "omp.elementNext"); 5510 ElementPHI->addIncoming(ElementNext.getPointer(), 5511 CGF.Builder.GetInsertBlock()); 5512 llvm::Value *IsEmpty = 5513 CGF.Builder.CreateICmpEQ(ElementNext.getPointer(), End, "omp.isempty"); 5514 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5515 // Done. 5516 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5517 } 5518 5519 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5520 const OMPExecutableDirective &D, 5521 llvm::Function *TaskFunction, 5522 QualType SharedsTy, Address Shareds, 5523 const Expr *IfCond, 5524 const OMPTaskDataTy &Data) { 5525 if (!CGF.HaveInsertPoint()) 5526 return; 5527 5528 TaskResultTy Result = 5529 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5530 llvm::Value *NewTask = Result.NewTask; 5531 llvm::Function *TaskEntry = Result.TaskEntry; 5532 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5533 LValue TDBase = Result.TDBase; 5534 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5535 // Process list of dependences. 5536 Address DependenciesArray = Address::invalid(); 5537 llvm::Value *NumOfElements; 5538 std::tie(NumOfElements, DependenciesArray) = 5539 emitDependClause(CGF, Data.Dependences, /*ForDepobj=*/false, Loc); 5540 5541 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5542 // libcall. 5543 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5544 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5545 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5546 // list is not empty 5547 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5548 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5549 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5550 llvm::Value *DepTaskArgs[7]; 5551 if (!Data.Dependences.empty()) { 5552 DepTaskArgs[0] = UpLoc; 5553 DepTaskArgs[1] = ThreadID; 5554 DepTaskArgs[2] = NewTask; 5555 DepTaskArgs[3] = NumOfElements; 5556 DepTaskArgs[4] = DependenciesArray.getPointer(); 5557 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5558 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5559 } 5560 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, &TaskArgs, 5561 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5562 if (!Data.Tied) { 5563 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5564 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5565 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5566 } 5567 if (!Data.Dependences.empty()) { 5568 CGF.EmitRuntimeCall( 5569 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5570 } else { 5571 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5572 TaskArgs); 5573 } 5574 // Check if parent region is untied and build return for untied task; 5575 if (auto *Region = 5576 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5577 Region->emitUntiedSwitch(CGF); 5578 }; 5579 5580 llvm::Value *DepWaitTaskArgs[6]; 5581 if (!Data.Dependences.empty()) { 5582 DepWaitTaskArgs[0] = UpLoc; 5583 DepWaitTaskArgs[1] = ThreadID; 5584 DepWaitTaskArgs[2] = NumOfElements; 5585 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5586 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5587 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5588 } 5589 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5590 &Data, &DepWaitTaskArgs, 5591 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5592 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5593 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5594 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5595 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5596 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5597 // is specified. 5598 if (!Data.Dependences.empty()) 5599 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5600 DepWaitTaskArgs); 5601 // Call proxy_task_entry(gtid, new_task); 5602 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5603 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5604 Action.Enter(CGF); 5605 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5606 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5607 OutlinedFnArgs); 5608 }; 5609 5610 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5611 // kmp_task_t *new_task); 5612 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5613 // kmp_task_t *new_task); 5614 RegionCodeGenTy RCG(CodeGen); 5615 CommonActionTy Action( 5616 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5617 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5618 RCG.setAction(Action); 5619 RCG(CGF); 5620 }; 5621 5622 if (IfCond) { 5623 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5624 } else { 5625 RegionCodeGenTy ThenRCG(ThenCodeGen); 5626 ThenRCG(CGF); 5627 } 5628 } 5629 5630 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5631 const OMPLoopDirective &D, 5632 llvm::Function *TaskFunction, 5633 QualType SharedsTy, Address Shareds, 5634 const Expr *IfCond, 5635 const OMPTaskDataTy &Data) { 5636 if (!CGF.HaveInsertPoint()) 5637 return; 5638 TaskResultTy Result = 5639 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5640 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5641 // libcall. 5642 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5643 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5644 // sched, kmp_uint64 grainsize, void *task_dup); 5645 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5646 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5647 llvm::Value *IfVal; 5648 if (IfCond) { 5649 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5650 /*isSigned=*/true); 5651 } else { 5652 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5653 } 5654 5655 LValue LBLVal = CGF.EmitLValueForField( 5656 Result.TDBase, 5657 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5658 const auto *LBVar = 5659 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5660 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5661 LBLVal.getQuals(), 5662 /*IsInitializer=*/true); 5663 LValue UBLVal = CGF.EmitLValueForField( 5664 Result.TDBase, 5665 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5666 const auto *UBVar = 5667 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5668 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5669 UBLVal.getQuals(), 5670 /*IsInitializer=*/true); 5671 LValue StLVal = CGF.EmitLValueForField( 5672 Result.TDBase, 5673 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5674 const auto *StVar = 5675 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5676 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5677 StLVal.getQuals(), 5678 /*IsInitializer=*/true); 5679 // Store reductions address. 5680 LValue RedLVal = CGF.EmitLValueForField( 5681 Result.TDBase, 5682 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5683 if (Data.Reductions) { 5684 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5685 } else { 5686 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5687 CGF.getContext().VoidPtrTy); 5688 } 5689 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5690 llvm::Value *TaskArgs[] = { 5691 UpLoc, 5692 ThreadID, 5693 Result.NewTask, 5694 IfVal, 5695 LBLVal.getPointer(CGF), 5696 UBLVal.getPointer(CGF), 5697 CGF.EmitLoadOfScalar(StLVal, Loc), 5698 llvm::ConstantInt::getSigned( 5699 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5700 llvm::ConstantInt::getSigned( 5701 CGF.IntTy, Data.Schedule.getPointer() 5702 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5703 : NoSchedule), 5704 Data.Schedule.getPointer() 5705 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5706 /*isSigned=*/false) 5707 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5708 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5709 Result.TaskDupFn, CGF.VoidPtrTy) 5710 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5711 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5712 } 5713 5714 /// Emit reduction operation for each element of array (required for 5715 /// array sections) LHS op = RHS. 5716 /// \param Type Type of array. 5717 /// \param LHSVar Variable on the left side of the reduction operation 5718 /// (references element of array in original variable). 5719 /// \param RHSVar Variable on the right side of the reduction operation 5720 /// (references element of array in original variable). 5721 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5722 /// RHSVar. 5723 static void EmitOMPAggregateReduction( 5724 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5725 const VarDecl *RHSVar, 5726 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5727 const Expr *, const Expr *)> &RedOpGen, 5728 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5729 const Expr *UpExpr = nullptr) { 5730 // Perform element-by-element initialization. 5731 QualType ElementTy; 5732 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5733 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5734 5735 // Drill down to the base element type on both arrays. 5736 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5737 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5738 5739 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5740 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5741 // Cast from pointer to array type to pointer to single element. 5742 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5743 // The basic structure here is a while-do loop. 5744 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5745 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5746 llvm::Value *IsEmpty = 5747 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5748 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5749 5750 // Enter the loop body, making that address the current address. 5751 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5752 CGF.EmitBlock(BodyBB); 5753 5754 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5755 5756 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5757 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5758 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5759 Address RHSElementCurrent = 5760 Address(RHSElementPHI, 5761 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5762 5763 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5764 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5765 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5766 Address LHSElementCurrent = 5767 Address(LHSElementPHI, 5768 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5769 5770 // Emit copy. 5771 CodeGenFunction::OMPPrivateScope Scope(CGF); 5772 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5773 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5774 Scope.Privatize(); 5775 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5776 Scope.ForceCleanup(); 5777 5778 // Shift the address forward by one element. 5779 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5780 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5781 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5782 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5783 // Check whether we've reached the end. 5784 llvm::Value *Done = 5785 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5786 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5787 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5788 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5789 5790 // Done. 5791 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5792 } 5793 5794 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5795 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5796 /// UDR combiner function. 5797 static void emitReductionCombiner(CodeGenFunction &CGF, 5798 const Expr *ReductionOp) { 5799 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5800 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5801 if (const auto *DRE = 5802 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5803 if (const auto *DRD = 5804 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5805 std::pair<llvm::Function *, llvm::Function *> Reduction = 5806 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5807 RValue Func = RValue::get(Reduction.first); 5808 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5809 CGF.EmitIgnoredExpr(ReductionOp); 5810 return; 5811 } 5812 CGF.EmitIgnoredExpr(ReductionOp); 5813 } 5814 5815 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5816 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5817 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5818 ArrayRef<const Expr *> ReductionOps) { 5819 ASTContext &C = CGM.getContext(); 5820 5821 // void reduction_func(void *LHSArg, void *RHSArg); 5822 FunctionArgList Args; 5823 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5824 ImplicitParamDecl::Other); 5825 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5826 ImplicitParamDecl::Other); 5827 Args.push_back(&LHSArg); 5828 Args.push_back(&RHSArg); 5829 const auto &CGFI = 5830 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5831 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5832 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5833 llvm::GlobalValue::InternalLinkage, Name, 5834 &CGM.getModule()); 5835 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5836 Fn->setDoesNotRecurse(); 5837 CodeGenFunction CGF(CGM); 5838 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5839 5840 // Dst = (void*[n])(LHSArg); 5841 // Src = (void*[n])(RHSArg); 5842 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5843 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5844 ArgsType), CGF.getPointerAlign()); 5845 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5846 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5847 ArgsType), CGF.getPointerAlign()); 5848 5849 // ... 5850 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5851 // ... 5852 CodeGenFunction::OMPPrivateScope Scope(CGF); 5853 auto IPriv = Privates.begin(); 5854 unsigned Idx = 0; 5855 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5856 const auto *RHSVar = 5857 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5858 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5859 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5860 }); 5861 const auto *LHSVar = 5862 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5863 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5864 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5865 }); 5866 QualType PrivTy = (*IPriv)->getType(); 5867 if (PrivTy->isVariablyModifiedType()) { 5868 // Get array size and emit VLA type. 5869 ++Idx; 5870 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5871 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5872 const VariableArrayType *VLA = 5873 CGF.getContext().getAsVariableArrayType(PrivTy); 5874 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5875 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5876 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5877 CGF.EmitVariablyModifiedType(PrivTy); 5878 } 5879 } 5880 Scope.Privatize(); 5881 IPriv = Privates.begin(); 5882 auto ILHS = LHSExprs.begin(); 5883 auto IRHS = RHSExprs.begin(); 5884 for (const Expr *E : ReductionOps) { 5885 if ((*IPriv)->getType()->isArrayType()) { 5886 // Emit reduction for array section. 5887 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5888 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5889 EmitOMPAggregateReduction( 5890 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5891 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5892 emitReductionCombiner(CGF, E); 5893 }); 5894 } else { 5895 // Emit reduction for array subscript or single variable. 5896 emitReductionCombiner(CGF, E); 5897 } 5898 ++IPriv; 5899 ++ILHS; 5900 ++IRHS; 5901 } 5902 Scope.ForceCleanup(); 5903 CGF.FinishFunction(); 5904 return Fn; 5905 } 5906 5907 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5908 const Expr *ReductionOp, 5909 const Expr *PrivateRef, 5910 const DeclRefExpr *LHS, 5911 const DeclRefExpr *RHS) { 5912 if (PrivateRef->getType()->isArrayType()) { 5913 // Emit reduction for array section. 5914 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5915 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5916 EmitOMPAggregateReduction( 5917 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5918 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5919 emitReductionCombiner(CGF, ReductionOp); 5920 }); 5921 } else { 5922 // Emit reduction for array subscript or single variable. 5923 emitReductionCombiner(CGF, ReductionOp); 5924 } 5925 } 5926 5927 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5928 ArrayRef<const Expr *> Privates, 5929 ArrayRef<const Expr *> LHSExprs, 5930 ArrayRef<const Expr *> RHSExprs, 5931 ArrayRef<const Expr *> ReductionOps, 5932 ReductionOptionsTy Options) { 5933 if (!CGF.HaveInsertPoint()) 5934 return; 5935 5936 bool WithNowait = Options.WithNowait; 5937 bool SimpleReduction = Options.SimpleReduction; 5938 5939 // Next code should be emitted for reduction: 5940 // 5941 // static kmp_critical_name lock = { 0 }; 5942 // 5943 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5944 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5945 // ... 5946 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5947 // *(Type<n>-1*)rhs[<n>-1]); 5948 // } 5949 // 5950 // ... 5951 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5952 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5953 // RedList, reduce_func, &<lock>)) { 5954 // case 1: 5955 // ... 5956 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5957 // ... 5958 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5959 // break; 5960 // case 2: 5961 // ... 5962 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5963 // ... 5964 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5965 // break; 5966 // default:; 5967 // } 5968 // 5969 // if SimpleReduction is true, only the next code is generated: 5970 // ... 5971 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5972 // ... 5973 5974 ASTContext &C = CGM.getContext(); 5975 5976 if (SimpleReduction) { 5977 CodeGenFunction::RunCleanupsScope Scope(CGF); 5978 auto IPriv = Privates.begin(); 5979 auto ILHS = LHSExprs.begin(); 5980 auto IRHS = RHSExprs.begin(); 5981 for (const Expr *E : ReductionOps) { 5982 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5983 cast<DeclRefExpr>(*IRHS)); 5984 ++IPriv; 5985 ++ILHS; 5986 ++IRHS; 5987 } 5988 return; 5989 } 5990 5991 // 1. Build a list of reduction variables. 5992 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5993 auto Size = RHSExprs.size(); 5994 for (const Expr *E : Privates) { 5995 if (E->getType()->isVariablyModifiedType()) 5996 // Reserve place for array size. 5997 ++Size; 5998 } 5999 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 6000 QualType ReductionArrayTy = 6001 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 6002 /*IndexTypeQuals=*/0); 6003 Address ReductionList = 6004 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 6005 auto IPriv = Privates.begin(); 6006 unsigned Idx = 0; 6007 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 6008 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 6009 CGF.Builder.CreateStore( 6010 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6011 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 6012 Elem); 6013 if ((*IPriv)->getType()->isVariablyModifiedType()) { 6014 // Store array size. 6015 ++Idx; 6016 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 6017 llvm::Value *Size = CGF.Builder.CreateIntCast( 6018 CGF.getVLASize( 6019 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 6020 .NumElts, 6021 CGF.SizeTy, /*isSigned=*/false); 6022 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 6023 Elem); 6024 } 6025 } 6026 6027 // 2. Emit reduce_func(). 6028 llvm::Function *ReductionFn = emitReductionFunction( 6029 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 6030 LHSExprs, RHSExprs, ReductionOps); 6031 6032 // 3. Create static kmp_critical_name lock = { 0 }; 6033 std::string Name = getName({"reduction"}); 6034 llvm::Value *Lock = getCriticalRegionLock(Name); 6035 6036 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 6037 // RedList, reduce_func, &<lock>); 6038 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 6039 llvm::Value *ThreadId = getThreadID(CGF, Loc); 6040 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 6041 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6042 ReductionList.getPointer(), CGF.VoidPtrTy); 6043 llvm::Value *Args[] = { 6044 IdentTLoc, // ident_t *<loc> 6045 ThreadId, // i32 <gtid> 6046 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 6047 ReductionArrayTySize, // size_type sizeof(RedList) 6048 RL, // void *RedList 6049 ReductionFn, // void (*) (void *, void *) <reduce_func> 6050 Lock // kmp_critical_name *&<lock> 6051 }; 6052 llvm::Value *Res = CGF.EmitRuntimeCall( 6053 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 6054 : OMPRTL__kmpc_reduce), 6055 Args); 6056 6057 // 5. Build switch(res) 6058 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 6059 llvm::SwitchInst *SwInst = 6060 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 6061 6062 // 6. Build case 1: 6063 // ... 6064 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 6065 // ... 6066 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 6067 // break; 6068 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 6069 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 6070 CGF.EmitBlock(Case1BB); 6071 6072 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 6073 llvm::Value *EndArgs[] = { 6074 IdentTLoc, // ident_t *<loc> 6075 ThreadId, // i32 <gtid> 6076 Lock // kmp_critical_name *&<lock> 6077 }; 6078 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 6079 CodeGenFunction &CGF, PrePostActionTy &Action) { 6080 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6081 auto IPriv = Privates.begin(); 6082 auto ILHS = LHSExprs.begin(); 6083 auto IRHS = RHSExprs.begin(); 6084 for (const Expr *E : ReductionOps) { 6085 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 6086 cast<DeclRefExpr>(*IRHS)); 6087 ++IPriv; 6088 ++ILHS; 6089 ++IRHS; 6090 } 6091 }; 6092 RegionCodeGenTy RCG(CodeGen); 6093 CommonActionTy Action( 6094 nullptr, llvm::None, 6095 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 6096 : OMPRTL__kmpc_end_reduce), 6097 EndArgs); 6098 RCG.setAction(Action); 6099 RCG(CGF); 6100 6101 CGF.EmitBranch(DefaultBB); 6102 6103 // 7. Build case 2: 6104 // ... 6105 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 6106 // ... 6107 // break; 6108 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 6109 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 6110 CGF.EmitBlock(Case2BB); 6111 6112 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 6113 CodeGenFunction &CGF, PrePostActionTy &Action) { 6114 auto ILHS = LHSExprs.begin(); 6115 auto IRHS = RHSExprs.begin(); 6116 auto IPriv = Privates.begin(); 6117 for (const Expr *E : ReductionOps) { 6118 const Expr *XExpr = nullptr; 6119 const Expr *EExpr = nullptr; 6120 const Expr *UpExpr = nullptr; 6121 BinaryOperatorKind BO = BO_Comma; 6122 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 6123 if (BO->getOpcode() == BO_Assign) { 6124 XExpr = BO->getLHS(); 6125 UpExpr = BO->getRHS(); 6126 } 6127 } 6128 // Try to emit update expression as a simple atomic. 6129 const Expr *RHSExpr = UpExpr; 6130 if (RHSExpr) { 6131 // Analyze RHS part of the whole expression. 6132 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 6133 RHSExpr->IgnoreParenImpCasts())) { 6134 // If this is a conditional operator, analyze its condition for 6135 // min/max reduction operator. 6136 RHSExpr = ACO->getCond(); 6137 } 6138 if (const auto *BORHS = 6139 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 6140 EExpr = BORHS->getRHS(); 6141 BO = BORHS->getOpcode(); 6142 } 6143 } 6144 if (XExpr) { 6145 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 6146 auto &&AtomicRedGen = [BO, VD, 6147 Loc](CodeGenFunction &CGF, const Expr *XExpr, 6148 const Expr *EExpr, const Expr *UpExpr) { 6149 LValue X = CGF.EmitLValue(XExpr); 6150 RValue E; 6151 if (EExpr) 6152 E = CGF.EmitAnyExpr(EExpr); 6153 CGF.EmitOMPAtomicSimpleUpdateExpr( 6154 X, E, BO, /*IsXLHSInRHSPart=*/true, 6155 llvm::AtomicOrdering::Monotonic, Loc, 6156 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 6157 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6158 PrivateScope.addPrivate( 6159 VD, [&CGF, VD, XRValue, Loc]() { 6160 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 6161 CGF.emitOMPSimpleStore( 6162 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 6163 VD->getType().getNonReferenceType(), Loc); 6164 return LHSTemp; 6165 }); 6166 (void)PrivateScope.Privatize(); 6167 return CGF.EmitAnyExpr(UpExpr); 6168 }); 6169 }; 6170 if ((*IPriv)->getType()->isArrayType()) { 6171 // Emit atomic reduction for array section. 6172 const auto *RHSVar = 6173 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 6174 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 6175 AtomicRedGen, XExpr, EExpr, UpExpr); 6176 } else { 6177 // Emit atomic reduction for array subscript or single variable. 6178 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 6179 } 6180 } else { 6181 // Emit as a critical region. 6182 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 6183 const Expr *, const Expr *) { 6184 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6185 std::string Name = RT.getName({"atomic_reduction"}); 6186 RT.emitCriticalRegion( 6187 CGF, Name, 6188 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 6189 Action.Enter(CGF); 6190 emitReductionCombiner(CGF, E); 6191 }, 6192 Loc); 6193 }; 6194 if ((*IPriv)->getType()->isArrayType()) { 6195 const auto *LHSVar = 6196 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 6197 const auto *RHSVar = 6198 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 6199 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 6200 CritRedGen); 6201 } else { 6202 CritRedGen(CGF, nullptr, nullptr, nullptr); 6203 } 6204 } 6205 ++ILHS; 6206 ++IRHS; 6207 ++IPriv; 6208 } 6209 }; 6210 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 6211 if (!WithNowait) { 6212 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 6213 llvm::Value *EndArgs[] = { 6214 IdentTLoc, // ident_t *<loc> 6215 ThreadId, // i32 <gtid> 6216 Lock // kmp_critical_name *&<lock> 6217 }; 6218 CommonActionTy Action(nullptr, llvm::None, 6219 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 6220 EndArgs); 6221 AtomicRCG.setAction(Action); 6222 AtomicRCG(CGF); 6223 } else { 6224 AtomicRCG(CGF); 6225 } 6226 6227 CGF.EmitBranch(DefaultBB); 6228 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 6229 } 6230 6231 /// Generates unique name for artificial threadprivate variables. 6232 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 6233 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 6234 const Expr *Ref) { 6235 SmallString<256> Buffer; 6236 llvm::raw_svector_ostream Out(Buffer); 6237 const clang::DeclRefExpr *DE; 6238 const VarDecl *D = ::getBaseDecl(Ref, DE); 6239 if (!D) 6240 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 6241 D = D->getCanonicalDecl(); 6242 std::string Name = CGM.getOpenMPRuntime().getName( 6243 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 6244 Out << Prefix << Name << "_" 6245 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 6246 return std::string(Out.str()); 6247 } 6248 6249 /// Emits reduction initializer function: 6250 /// \code 6251 /// void @.red_init(void* %arg) { 6252 /// %0 = bitcast void* %arg to <type>* 6253 /// store <type> <init>, <type>* %0 6254 /// ret void 6255 /// } 6256 /// \endcode 6257 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6258 SourceLocation Loc, 6259 ReductionCodeGen &RCG, unsigned N) { 6260 ASTContext &C = CGM.getContext(); 6261 FunctionArgList Args; 6262 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6263 ImplicitParamDecl::Other); 6264 Args.emplace_back(&Param); 6265 const auto &FnInfo = 6266 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6267 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6268 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6269 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6270 Name, &CGM.getModule()); 6271 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6272 Fn->setDoesNotRecurse(); 6273 CodeGenFunction CGF(CGM); 6274 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6275 Address PrivateAddr = CGF.EmitLoadOfPointer( 6276 CGF.GetAddrOfLocalVar(&Param), 6277 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6278 llvm::Value *Size = nullptr; 6279 // If the size of the reduction item is non-constant, load it from global 6280 // threadprivate variable. 6281 if (RCG.getSizes(N).second) { 6282 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6283 CGF, CGM.getContext().getSizeType(), 6284 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6285 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6286 CGM.getContext().getSizeType(), Loc); 6287 } 6288 RCG.emitAggregateType(CGF, N, Size); 6289 LValue SharedLVal; 6290 // If initializer uses initializer from declare reduction construct, emit a 6291 // pointer to the address of the original reduction item (reuired by reduction 6292 // initializer) 6293 if (RCG.usesReductionInitializer(N)) { 6294 Address SharedAddr = 6295 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6296 CGF, CGM.getContext().VoidPtrTy, 6297 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6298 SharedAddr = CGF.EmitLoadOfPointer( 6299 SharedAddr, 6300 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6301 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6302 } else { 6303 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6304 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6305 CGM.getContext().VoidPtrTy); 6306 } 6307 // Emit the initializer: 6308 // %0 = bitcast void* %arg to <type>* 6309 // store <type> <init>, <type>* %0 6310 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6311 [](CodeGenFunction &) { return false; }); 6312 CGF.FinishFunction(); 6313 return Fn; 6314 } 6315 6316 /// Emits reduction combiner function: 6317 /// \code 6318 /// void @.red_comb(void* %arg0, void* %arg1) { 6319 /// %lhs = bitcast void* %arg0 to <type>* 6320 /// %rhs = bitcast void* %arg1 to <type>* 6321 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6322 /// store <type> %2, <type>* %lhs 6323 /// ret void 6324 /// } 6325 /// \endcode 6326 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6327 SourceLocation Loc, 6328 ReductionCodeGen &RCG, unsigned N, 6329 const Expr *ReductionOp, 6330 const Expr *LHS, const Expr *RHS, 6331 const Expr *PrivateRef) { 6332 ASTContext &C = CGM.getContext(); 6333 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6334 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6335 FunctionArgList Args; 6336 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6337 C.VoidPtrTy, ImplicitParamDecl::Other); 6338 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6339 ImplicitParamDecl::Other); 6340 Args.emplace_back(&ParamInOut); 6341 Args.emplace_back(&ParamIn); 6342 const auto &FnInfo = 6343 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6344 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6345 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6346 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6347 Name, &CGM.getModule()); 6348 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6349 Fn->setDoesNotRecurse(); 6350 CodeGenFunction CGF(CGM); 6351 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6352 llvm::Value *Size = nullptr; 6353 // If the size of the reduction item is non-constant, load it from global 6354 // threadprivate variable. 6355 if (RCG.getSizes(N).second) { 6356 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6357 CGF, CGM.getContext().getSizeType(), 6358 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6359 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6360 CGM.getContext().getSizeType(), Loc); 6361 } 6362 RCG.emitAggregateType(CGF, N, Size); 6363 // Remap lhs and rhs variables to the addresses of the function arguments. 6364 // %lhs = bitcast void* %arg0 to <type>* 6365 // %rhs = bitcast void* %arg1 to <type>* 6366 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6367 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6368 // Pull out the pointer to the variable. 6369 Address PtrAddr = CGF.EmitLoadOfPointer( 6370 CGF.GetAddrOfLocalVar(&ParamInOut), 6371 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6372 return CGF.Builder.CreateElementBitCast( 6373 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6374 }); 6375 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6376 // Pull out the pointer to the variable. 6377 Address PtrAddr = CGF.EmitLoadOfPointer( 6378 CGF.GetAddrOfLocalVar(&ParamIn), 6379 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6380 return CGF.Builder.CreateElementBitCast( 6381 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6382 }); 6383 PrivateScope.Privatize(); 6384 // Emit the combiner body: 6385 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6386 // store <type> %2, <type>* %lhs 6387 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6388 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6389 cast<DeclRefExpr>(RHS)); 6390 CGF.FinishFunction(); 6391 return Fn; 6392 } 6393 6394 /// Emits reduction finalizer function: 6395 /// \code 6396 /// void @.red_fini(void* %arg) { 6397 /// %0 = bitcast void* %arg to <type>* 6398 /// <destroy>(<type>* %0) 6399 /// ret void 6400 /// } 6401 /// \endcode 6402 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6403 SourceLocation Loc, 6404 ReductionCodeGen &RCG, unsigned N) { 6405 if (!RCG.needCleanups(N)) 6406 return nullptr; 6407 ASTContext &C = CGM.getContext(); 6408 FunctionArgList Args; 6409 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6410 ImplicitParamDecl::Other); 6411 Args.emplace_back(&Param); 6412 const auto &FnInfo = 6413 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6414 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6415 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6416 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6417 Name, &CGM.getModule()); 6418 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6419 Fn->setDoesNotRecurse(); 6420 CodeGenFunction CGF(CGM); 6421 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6422 Address PrivateAddr = CGF.EmitLoadOfPointer( 6423 CGF.GetAddrOfLocalVar(&Param), 6424 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6425 llvm::Value *Size = nullptr; 6426 // If the size of the reduction item is non-constant, load it from global 6427 // threadprivate variable. 6428 if (RCG.getSizes(N).second) { 6429 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6430 CGF, CGM.getContext().getSizeType(), 6431 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6432 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6433 CGM.getContext().getSizeType(), Loc); 6434 } 6435 RCG.emitAggregateType(CGF, N, Size); 6436 // Emit the finalizer body: 6437 // <destroy>(<type>* %0) 6438 RCG.emitCleanups(CGF, N, PrivateAddr); 6439 CGF.FinishFunction(Loc); 6440 return Fn; 6441 } 6442 6443 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6444 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6445 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6446 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6447 return nullptr; 6448 6449 // Build typedef struct: 6450 // kmp_task_red_input { 6451 // void *reduce_shar; // shared reduction item 6452 // size_t reduce_size; // size of data item 6453 // void *reduce_init; // data initialization routine 6454 // void *reduce_fini; // data finalization routine 6455 // void *reduce_comb; // data combiner routine 6456 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6457 // } kmp_task_red_input_t; 6458 ASTContext &C = CGM.getContext(); 6459 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6460 RD->startDefinition(); 6461 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6462 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6463 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6464 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6465 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6466 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6467 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6468 RD->completeDefinition(); 6469 QualType RDType = C.getRecordType(RD); 6470 unsigned Size = Data.ReductionVars.size(); 6471 llvm::APInt ArraySize(/*numBits=*/64, Size); 6472 QualType ArrayRDType = C.getConstantArrayType( 6473 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6474 // kmp_task_red_input_t .rd_input.[Size]; 6475 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6476 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6477 Data.ReductionOps); 6478 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6479 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6480 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6481 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6482 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6483 TaskRedInput.getPointer(), Idxs, 6484 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6485 ".rd_input.gep."); 6486 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6487 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6488 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6489 RCG.emitSharedLValue(CGF, Cnt); 6490 llvm::Value *CastedShared = 6491 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6492 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6493 RCG.emitAggregateType(CGF, Cnt); 6494 llvm::Value *SizeValInChars; 6495 llvm::Value *SizeVal; 6496 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6497 // We use delayed creation/initialization for VLAs, array sections and 6498 // custom reduction initializations. It is required because runtime does not 6499 // provide the way to pass the sizes of VLAs/array sections to 6500 // initializer/combiner/finalizer functions and does not pass the pointer to 6501 // original reduction item to the initializer. Instead threadprivate global 6502 // variables are used to store these values and use them in the functions. 6503 bool DelayedCreation = !!SizeVal; 6504 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6505 /*isSigned=*/false); 6506 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6507 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6508 // ElemLVal.reduce_init = init; 6509 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6510 llvm::Value *InitAddr = 6511 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6512 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6513 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6514 // ElemLVal.reduce_fini = fini; 6515 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6516 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6517 llvm::Value *FiniAddr = Fini 6518 ? CGF.EmitCastToVoidPtr(Fini) 6519 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6520 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6521 // ElemLVal.reduce_comb = comb; 6522 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6523 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6524 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6525 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6526 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6527 // ElemLVal.flags = 0; 6528 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6529 if (DelayedCreation) { 6530 CGF.EmitStoreOfScalar( 6531 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6532 FlagsLVal); 6533 } else 6534 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6535 FlagsLVal.getType()); 6536 } 6537 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6538 // *data); 6539 llvm::Value *Args[] = { 6540 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6541 /*isSigned=*/true), 6542 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6543 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6544 CGM.VoidPtrTy)}; 6545 return CGF.EmitRuntimeCall( 6546 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6547 } 6548 6549 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6550 SourceLocation Loc, 6551 ReductionCodeGen &RCG, 6552 unsigned N) { 6553 auto Sizes = RCG.getSizes(N); 6554 // Emit threadprivate global variable if the type is non-constant 6555 // (Sizes.second = nullptr). 6556 if (Sizes.second) { 6557 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6558 /*isSigned=*/false); 6559 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6560 CGF, CGM.getContext().getSizeType(), 6561 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6562 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6563 } 6564 // Store address of the original reduction item if custom initializer is used. 6565 if (RCG.usesReductionInitializer(N)) { 6566 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6567 CGF, CGM.getContext().VoidPtrTy, 6568 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6569 CGF.Builder.CreateStore( 6570 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6571 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy), 6572 SharedAddr, /*IsVolatile=*/false); 6573 } 6574 } 6575 6576 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6577 SourceLocation Loc, 6578 llvm::Value *ReductionsPtr, 6579 LValue SharedLVal) { 6580 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6581 // *d); 6582 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6583 CGM.IntTy, 6584 /*isSigned=*/true), 6585 ReductionsPtr, 6586 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6587 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6588 return Address( 6589 CGF.EmitRuntimeCall( 6590 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6591 SharedLVal.getAlignment()); 6592 } 6593 6594 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6595 SourceLocation Loc) { 6596 if (!CGF.HaveInsertPoint()) 6597 return; 6598 6599 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 6600 if (OMPBuilder) { 6601 OMPBuilder->CreateTaskwait(CGF.Builder); 6602 } else { 6603 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6604 // global_tid); 6605 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6606 // Ignore return result until untied tasks are supported. 6607 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6608 } 6609 6610 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6611 Region->emitUntiedSwitch(CGF); 6612 } 6613 6614 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6615 OpenMPDirectiveKind InnerKind, 6616 const RegionCodeGenTy &CodeGen, 6617 bool HasCancel) { 6618 if (!CGF.HaveInsertPoint()) 6619 return; 6620 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6621 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6622 } 6623 6624 namespace { 6625 enum RTCancelKind { 6626 CancelNoreq = 0, 6627 CancelParallel = 1, 6628 CancelLoop = 2, 6629 CancelSections = 3, 6630 CancelTaskgroup = 4 6631 }; 6632 } // anonymous namespace 6633 6634 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6635 RTCancelKind CancelKind = CancelNoreq; 6636 if (CancelRegion == OMPD_parallel) 6637 CancelKind = CancelParallel; 6638 else if (CancelRegion == OMPD_for) 6639 CancelKind = CancelLoop; 6640 else if (CancelRegion == OMPD_sections) 6641 CancelKind = CancelSections; 6642 else { 6643 assert(CancelRegion == OMPD_taskgroup); 6644 CancelKind = CancelTaskgroup; 6645 } 6646 return CancelKind; 6647 } 6648 6649 void CGOpenMPRuntime::emitCancellationPointCall( 6650 CodeGenFunction &CGF, SourceLocation Loc, 6651 OpenMPDirectiveKind CancelRegion) { 6652 if (!CGF.HaveInsertPoint()) 6653 return; 6654 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6655 // global_tid, kmp_int32 cncl_kind); 6656 if (auto *OMPRegionInfo = 6657 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6658 // For 'cancellation point taskgroup', the task region info may not have a 6659 // cancel. This may instead happen in another adjacent task. 6660 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6661 llvm::Value *Args[] = { 6662 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6663 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6664 // Ignore return result until untied tasks are supported. 6665 llvm::Value *Result = CGF.EmitRuntimeCall( 6666 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6667 // if (__kmpc_cancellationpoint()) { 6668 // exit from construct; 6669 // } 6670 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6671 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6672 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6673 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6674 CGF.EmitBlock(ExitBB); 6675 // exit from construct; 6676 CodeGenFunction::JumpDest CancelDest = 6677 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6678 CGF.EmitBranchThroughCleanup(CancelDest); 6679 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6680 } 6681 } 6682 } 6683 6684 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6685 const Expr *IfCond, 6686 OpenMPDirectiveKind CancelRegion) { 6687 if (!CGF.HaveInsertPoint()) 6688 return; 6689 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6690 // kmp_int32 cncl_kind); 6691 if (auto *OMPRegionInfo = 6692 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6693 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6694 PrePostActionTy &) { 6695 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6696 llvm::Value *Args[] = { 6697 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6698 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6699 // Ignore return result until untied tasks are supported. 6700 llvm::Value *Result = CGF.EmitRuntimeCall( 6701 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6702 // if (__kmpc_cancel()) { 6703 // exit from construct; 6704 // } 6705 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6706 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6707 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6708 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6709 CGF.EmitBlock(ExitBB); 6710 // exit from construct; 6711 CodeGenFunction::JumpDest CancelDest = 6712 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6713 CGF.EmitBranchThroughCleanup(CancelDest); 6714 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6715 }; 6716 if (IfCond) { 6717 emitIfClause(CGF, IfCond, ThenGen, 6718 [](CodeGenFunction &, PrePostActionTy &) {}); 6719 } else { 6720 RegionCodeGenTy ThenRCG(ThenGen); 6721 ThenRCG(CGF); 6722 } 6723 } 6724 } 6725 6726 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6727 const OMPExecutableDirective &D, StringRef ParentName, 6728 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6729 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6730 assert(!ParentName.empty() && "Invalid target region parent name!"); 6731 HasEmittedTargetRegion = true; 6732 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6733 IsOffloadEntry, CodeGen); 6734 } 6735 6736 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6737 const OMPExecutableDirective &D, StringRef ParentName, 6738 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6739 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6740 // Create a unique name for the entry function using the source location 6741 // information of the current target region. The name will be something like: 6742 // 6743 // __omp_offloading_DD_FFFF_PP_lBB 6744 // 6745 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6746 // mangled name of the function that encloses the target region and BB is the 6747 // line number of the target region. 6748 6749 unsigned DeviceID; 6750 unsigned FileID; 6751 unsigned Line; 6752 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6753 Line); 6754 SmallString<64> EntryFnName; 6755 { 6756 llvm::raw_svector_ostream OS(EntryFnName); 6757 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6758 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6759 } 6760 6761 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6762 6763 CodeGenFunction CGF(CGM, true); 6764 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6765 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6766 6767 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6768 6769 // If this target outline function is not an offload entry, we don't need to 6770 // register it. 6771 if (!IsOffloadEntry) 6772 return; 6773 6774 // The target region ID is used by the runtime library to identify the current 6775 // target region, so it only has to be unique and not necessarily point to 6776 // anything. It could be the pointer to the outlined function that implements 6777 // the target region, but we aren't using that so that the compiler doesn't 6778 // need to keep that, and could therefore inline the host function if proven 6779 // worthwhile during optimization. In the other hand, if emitting code for the 6780 // device, the ID has to be the function address so that it can retrieved from 6781 // the offloading entry and launched by the runtime library. We also mark the 6782 // outlined function to have external linkage in case we are emitting code for 6783 // the device, because these functions will be entry points to the device. 6784 6785 if (CGM.getLangOpts().OpenMPIsDevice) { 6786 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6787 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6788 OutlinedFn->setDSOLocal(false); 6789 } else { 6790 std::string Name = getName({EntryFnName, "region_id"}); 6791 OutlinedFnID = new llvm::GlobalVariable( 6792 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6793 llvm::GlobalValue::WeakAnyLinkage, 6794 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6795 } 6796 6797 // Register the information for the entry associated with this target region. 6798 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6799 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6800 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6801 } 6802 6803 /// Checks if the expression is constant or does not have non-trivial function 6804 /// calls. 6805 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6806 // We can skip constant expressions. 6807 // We can skip expressions with trivial calls or simple expressions. 6808 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6809 !E->hasNonTrivialCall(Ctx)) && 6810 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6811 } 6812 6813 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6814 const Stmt *Body) { 6815 const Stmt *Child = Body->IgnoreContainers(); 6816 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6817 Child = nullptr; 6818 for (const Stmt *S : C->body()) { 6819 if (const auto *E = dyn_cast<Expr>(S)) { 6820 if (isTrivial(Ctx, E)) 6821 continue; 6822 } 6823 // Some of the statements can be ignored. 6824 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6825 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6826 continue; 6827 // Analyze declarations. 6828 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6829 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6830 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6831 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6832 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6833 isa<UsingDirectiveDecl>(D) || 6834 isa<OMPDeclareReductionDecl>(D) || 6835 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6836 return true; 6837 const auto *VD = dyn_cast<VarDecl>(D); 6838 if (!VD) 6839 return false; 6840 return VD->isConstexpr() || 6841 ((VD->getType().isTrivialType(Ctx) || 6842 VD->getType()->isReferenceType()) && 6843 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6844 })) 6845 continue; 6846 } 6847 // Found multiple children - cannot get the one child only. 6848 if (Child) 6849 return nullptr; 6850 Child = S; 6851 } 6852 if (Child) 6853 Child = Child->IgnoreContainers(); 6854 } 6855 return Child; 6856 } 6857 6858 /// Emit the number of teams for a target directive. Inspect the num_teams 6859 /// clause associated with a teams construct combined or closely nested 6860 /// with the target directive. 6861 /// 6862 /// Emit a team of size one for directives such as 'target parallel' that 6863 /// have no associated teams construct. 6864 /// 6865 /// Otherwise, return nullptr. 6866 static llvm::Value * 6867 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6868 const OMPExecutableDirective &D) { 6869 assert(!CGF.getLangOpts().OpenMPIsDevice && 6870 "Clauses associated with the teams directive expected to be emitted " 6871 "only for the host!"); 6872 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6873 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6874 "Expected target-based executable directive."); 6875 CGBuilderTy &Bld = CGF.Builder; 6876 switch (DirectiveKind) { 6877 case OMPD_target: { 6878 const auto *CS = D.getInnermostCapturedStmt(); 6879 const auto *Body = 6880 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6881 const Stmt *ChildStmt = 6882 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6883 if (const auto *NestedDir = 6884 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6885 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6886 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6887 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6888 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6889 const Expr *NumTeams = 6890 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6891 llvm::Value *NumTeamsVal = 6892 CGF.EmitScalarExpr(NumTeams, 6893 /*IgnoreResultAssign*/ true); 6894 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6895 /*isSigned=*/true); 6896 } 6897 return Bld.getInt32(0); 6898 } 6899 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6900 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6901 return Bld.getInt32(1); 6902 return Bld.getInt32(0); 6903 } 6904 return nullptr; 6905 } 6906 case OMPD_target_teams: 6907 case OMPD_target_teams_distribute: 6908 case OMPD_target_teams_distribute_simd: 6909 case OMPD_target_teams_distribute_parallel_for: 6910 case OMPD_target_teams_distribute_parallel_for_simd: { 6911 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6912 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6913 const Expr *NumTeams = 6914 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6915 llvm::Value *NumTeamsVal = 6916 CGF.EmitScalarExpr(NumTeams, 6917 /*IgnoreResultAssign*/ true); 6918 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6919 /*isSigned=*/true); 6920 } 6921 return Bld.getInt32(0); 6922 } 6923 case OMPD_target_parallel: 6924 case OMPD_target_parallel_for: 6925 case OMPD_target_parallel_for_simd: 6926 case OMPD_target_simd: 6927 return Bld.getInt32(1); 6928 case OMPD_parallel: 6929 case OMPD_for: 6930 case OMPD_parallel_for: 6931 case OMPD_parallel_master: 6932 case OMPD_parallel_sections: 6933 case OMPD_for_simd: 6934 case OMPD_parallel_for_simd: 6935 case OMPD_cancel: 6936 case OMPD_cancellation_point: 6937 case OMPD_ordered: 6938 case OMPD_threadprivate: 6939 case OMPD_allocate: 6940 case OMPD_task: 6941 case OMPD_simd: 6942 case OMPD_sections: 6943 case OMPD_section: 6944 case OMPD_single: 6945 case OMPD_master: 6946 case OMPD_critical: 6947 case OMPD_taskyield: 6948 case OMPD_barrier: 6949 case OMPD_taskwait: 6950 case OMPD_taskgroup: 6951 case OMPD_atomic: 6952 case OMPD_flush: 6953 case OMPD_depobj: 6954 case OMPD_teams: 6955 case OMPD_target_data: 6956 case OMPD_target_exit_data: 6957 case OMPD_target_enter_data: 6958 case OMPD_distribute: 6959 case OMPD_distribute_simd: 6960 case OMPD_distribute_parallel_for: 6961 case OMPD_distribute_parallel_for_simd: 6962 case OMPD_teams_distribute: 6963 case OMPD_teams_distribute_simd: 6964 case OMPD_teams_distribute_parallel_for: 6965 case OMPD_teams_distribute_parallel_for_simd: 6966 case OMPD_target_update: 6967 case OMPD_declare_simd: 6968 case OMPD_declare_variant: 6969 case OMPD_declare_target: 6970 case OMPD_end_declare_target: 6971 case OMPD_declare_reduction: 6972 case OMPD_declare_mapper: 6973 case OMPD_taskloop: 6974 case OMPD_taskloop_simd: 6975 case OMPD_master_taskloop: 6976 case OMPD_master_taskloop_simd: 6977 case OMPD_parallel_master_taskloop: 6978 case OMPD_parallel_master_taskloop_simd: 6979 case OMPD_requires: 6980 case OMPD_unknown: 6981 break; 6982 } 6983 llvm_unreachable("Unexpected directive kind."); 6984 } 6985 6986 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6987 llvm::Value *DefaultThreadLimitVal) { 6988 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6989 CGF.getContext(), CS->getCapturedStmt()); 6990 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6991 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6992 llvm::Value *NumThreads = nullptr; 6993 llvm::Value *CondVal = nullptr; 6994 // Handle if clause. If if clause present, the number of threads is 6995 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6996 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6997 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6998 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6999 const OMPIfClause *IfClause = nullptr; 7000 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 7001 if (C->getNameModifier() == OMPD_unknown || 7002 C->getNameModifier() == OMPD_parallel) { 7003 IfClause = C; 7004 break; 7005 } 7006 } 7007 if (IfClause) { 7008 const Expr *Cond = IfClause->getCondition(); 7009 bool Result; 7010 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7011 if (!Result) 7012 return CGF.Builder.getInt32(1); 7013 } else { 7014 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 7015 if (const auto *PreInit = 7016 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 7017 for (const auto *I : PreInit->decls()) { 7018 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7019 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7020 } else { 7021 CodeGenFunction::AutoVarEmission Emission = 7022 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7023 CGF.EmitAutoVarCleanups(Emission); 7024 } 7025 } 7026 } 7027 CondVal = CGF.EvaluateExprAsBool(Cond); 7028 } 7029 } 7030 } 7031 // Check the value of num_threads clause iff if clause was not specified 7032 // or is not evaluated to false. 7033 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 7034 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7035 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7036 const auto *NumThreadsClause = 7037 Dir->getSingleClause<OMPNumThreadsClause>(); 7038 CodeGenFunction::LexicalScope Scope( 7039 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 7040 if (const auto *PreInit = 7041 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 7042 for (const auto *I : PreInit->decls()) { 7043 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7044 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7045 } else { 7046 CodeGenFunction::AutoVarEmission Emission = 7047 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7048 CGF.EmitAutoVarCleanups(Emission); 7049 } 7050 } 7051 } 7052 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 7053 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 7054 /*isSigned=*/false); 7055 if (DefaultThreadLimitVal) 7056 NumThreads = CGF.Builder.CreateSelect( 7057 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 7058 DefaultThreadLimitVal, NumThreads); 7059 } else { 7060 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 7061 : CGF.Builder.getInt32(0); 7062 } 7063 // Process condition of the if clause. 7064 if (CondVal) { 7065 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 7066 CGF.Builder.getInt32(1)); 7067 } 7068 return NumThreads; 7069 } 7070 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 7071 return CGF.Builder.getInt32(1); 7072 return DefaultThreadLimitVal; 7073 } 7074 return DefaultThreadLimitVal ? DefaultThreadLimitVal 7075 : CGF.Builder.getInt32(0); 7076 } 7077 7078 /// Emit the number of threads for a target directive. Inspect the 7079 /// thread_limit clause associated with a teams construct combined or closely 7080 /// nested with the target directive. 7081 /// 7082 /// Emit the num_threads clause for directives such as 'target parallel' that 7083 /// have no associated teams construct. 7084 /// 7085 /// Otherwise, return nullptr. 7086 static llvm::Value * 7087 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 7088 const OMPExecutableDirective &D) { 7089 assert(!CGF.getLangOpts().OpenMPIsDevice && 7090 "Clauses associated with the teams directive expected to be emitted " 7091 "only for the host!"); 7092 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 7093 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 7094 "Expected target-based executable directive."); 7095 CGBuilderTy &Bld = CGF.Builder; 7096 llvm::Value *ThreadLimitVal = nullptr; 7097 llvm::Value *NumThreadsVal = nullptr; 7098 switch (DirectiveKind) { 7099 case OMPD_target: { 7100 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7101 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7102 return NumThreads; 7103 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7104 CGF.getContext(), CS->getCapturedStmt()); 7105 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7106 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 7107 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 7108 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 7109 const auto *ThreadLimitClause = 7110 Dir->getSingleClause<OMPThreadLimitClause>(); 7111 CodeGenFunction::LexicalScope Scope( 7112 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 7113 if (const auto *PreInit = 7114 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 7115 for (const auto *I : PreInit->decls()) { 7116 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 7117 CGF.EmitVarDecl(cast<VarDecl>(*I)); 7118 } else { 7119 CodeGenFunction::AutoVarEmission Emission = 7120 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 7121 CGF.EmitAutoVarCleanups(Emission); 7122 } 7123 } 7124 } 7125 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7126 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7127 ThreadLimitVal = 7128 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7129 } 7130 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 7131 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 7132 CS = Dir->getInnermostCapturedStmt(); 7133 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7134 CGF.getContext(), CS->getCapturedStmt()); 7135 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 7136 } 7137 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 7138 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 7139 CS = Dir->getInnermostCapturedStmt(); 7140 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7141 return NumThreads; 7142 } 7143 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 7144 return Bld.getInt32(1); 7145 } 7146 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7147 } 7148 case OMPD_target_teams: { 7149 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7150 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7151 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7152 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7153 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7154 ThreadLimitVal = 7155 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7156 } 7157 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 7158 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7159 return NumThreads; 7160 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 7161 CGF.getContext(), CS->getCapturedStmt()); 7162 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 7163 if (Dir->getDirectiveKind() == OMPD_distribute) { 7164 CS = Dir->getInnermostCapturedStmt(); 7165 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 7166 return NumThreads; 7167 } 7168 } 7169 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 7170 } 7171 case OMPD_target_teams_distribute: 7172 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7173 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7174 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7175 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7176 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7177 ThreadLimitVal = 7178 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7179 } 7180 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 7181 case OMPD_target_parallel: 7182 case OMPD_target_parallel_for: 7183 case OMPD_target_parallel_for_simd: 7184 case OMPD_target_teams_distribute_parallel_for: 7185 case OMPD_target_teams_distribute_parallel_for_simd: { 7186 llvm::Value *CondVal = nullptr; 7187 // Handle if clause. If if clause present, the number of threads is 7188 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 7189 if (D.hasClausesOfKind<OMPIfClause>()) { 7190 const OMPIfClause *IfClause = nullptr; 7191 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 7192 if (C->getNameModifier() == OMPD_unknown || 7193 C->getNameModifier() == OMPD_parallel) { 7194 IfClause = C; 7195 break; 7196 } 7197 } 7198 if (IfClause) { 7199 const Expr *Cond = IfClause->getCondition(); 7200 bool Result; 7201 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7202 if (!Result) 7203 return Bld.getInt32(1); 7204 } else { 7205 CodeGenFunction::RunCleanupsScope Scope(CGF); 7206 CondVal = CGF.EvaluateExprAsBool(Cond); 7207 } 7208 } 7209 } 7210 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7211 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7212 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7213 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7214 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7215 ThreadLimitVal = 7216 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7217 } 7218 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 7219 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 7220 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 7221 llvm::Value *NumThreads = CGF.EmitScalarExpr( 7222 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 7223 NumThreadsVal = 7224 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 7225 ThreadLimitVal = ThreadLimitVal 7226 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 7227 ThreadLimitVal), 7228 NumThreadsVal, ThreadLimitVal) 7229 : NumThreadsVal; 7230 } 7231 if (!ThreadLimitVal) 7232 ThreadLimitVal = Bld.getInt32(0); 7233 if (CondVal) 7234 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 7235 return ThreadLimitVal; 7236 } 7237 case OMPD_target_teams_distribute_simd: 7238 case OMPD_target_simd: 7239 return Bld.getInt32(1); 7240 case OMPD_parallel: 7241 case OMPD_for: 7242 case OMPD_parallel_for: 7243 case OMPD_parallel_master: 7244 case OMPD_parallel_sections: 7245 case OMPD_for_simd: 7246 case OMPD_parallel_for_simd: 7247 case OMPD_cancel: 7248 case OMPD_cancellation_point: 7249 case OMPD_ordered: 7250 case OMPD_threadprivate: 7251 case OMPD_allocate: 7252 case OMPD_task: 7253 case OMPD_simd: 7254 case OMPD_sections: 7255 case OMPD_section: 7256 case OMPD_single: 7257 case OMPD_master: 7258 case OMPD_critical: 7259 case OMPD_taskyield: 7260 case OMPD_barrier: 7261 case OMPD_taskwait: 7262 case OMPD_taskgroup: 7263 case OMPD_atomic: 7264 case OMPD_flush: 7265 case OMPD_depobj: 7266 case OMPD_teams: 7267 case OMPD_target_data: 7268 case OMPD_target_exit_data: 7269 case OMPD_target_enter_data: 7270 case OMPD_distribute: 7271 case OMPD_distribute_simd: 7272 case OMPD_distribute_parallel_for: 7273 case OMPD_distribute_parallel_for_simd: 7274 case OMPD_teams_distribute: 7275 case OMPD_teams_distribute_simd: 7276 case OMPD_teams_distribute_parallel_for: 7277 case OMPD_teams_distribute_parallel_for_simd: 7278 case OMPD_target_update: 7279 case OMPD_declare_simd: 7280 case OMPD_declare_variant: 7281 case OMPD_declare_target: 7282 case OMPD_end_declare_target: 7283 case OMPD_declare_reduction: 7284 case OMPD_declare_mapper: 7285 case OMPD_taskloop: 7286 case OMPD_taskloop_simd: 7287 case OMPD_master_taskloop: 7288 case OMPD_master_taskloop_simd: 7289 case OMPD_parallel_master_taskloop: 7290 case OMPD_parallel_master_taskloop_simd: 7291 case OMPD_requires: 7292 case OMPD_unknown: 7293 break; 7294 } 7295 llvm_unreachable("Unsupported directive kind."); 7296 } 7297 7298 namespace { 7299 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7300 7301 // Utility to handle information from clauses associated with a given 7302 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7303 // It provides a convenient interface to obtain the information and generate 7304 // code for that information. 7305 class MappableExprsHandler { 7306 public: 7307 /// Values for bit flags used to specify the mapping type for 7308 /// offloading. 7309 enum OpenMPOffloadMappingFlags : uint64_t { 7310 /// No flags 7311 OMP_MAP_NONE = 0x0, 7312 /// Allocate memory on the device and move data from host to device. 7313 OMP_MAP_TO = 0x01, 7314 /// Allocate memory on the device and move data from device to host. 7315 OMP_MAP_FROM = 0x02, 7316 /// Always perform the requested mapping action on the element, even 7317 /// if it was already mapped before. 7318 OMP_MAP_ALWAYS = 0x04, 7319 /// Delete the element from the device environment, ignoring the 7320 /// current reference count associated with the element. 7321 OMP_MAP_DELETE = 0x08, 7322 /// The element being mapped is a pointer-pointee pair; both the 7323 /// pointer and the pointee should be mapped. 7324 OMP_MAP_PTR_AND_OBJ = 0x10, 7325 /// This flags signals that the base address of an entry should be 7326 /// passed to the target kernel as an argument. 7327 OMP_MAP_TARGET_PARAM = 0x20, 7328 /// Signal that the runtime library has to return the device pointer 7329 /// in the current position for the data being mapped. Used when we have the 7330 /// use_device_ptr clause. 7331 OMP_MAP_RETURN_PARAM = 0x40, 7332 /// This flag signals that the reference being passed is a pointer to 7333 /// private data. 7334 OMP_MAP_PRIVATE = 0x80, 7335 /// Pass the element to the device by value. 7336 OMP_MAP_LITERAL = 0x100, 7337 /// Implicit map 7338 OMP_MAP_IMPLICIT = 0x200, 7339 /// Close is a hint to the runtime to allocate memory close to 7340 /// the target device. 7341 OMP_MAP_CLOSE = 0x400, 7342 /// The 16 MSBs of the flags indicate whether the entry is member of some 7343 /// struct/class. 7344 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7345 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7346 }; 7347 7348 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7349 static unsigned getFlagMemberOffset() { 7350 unsigned Offset = 0; 7351 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7352 Remain = Remain >> 1) 7353 Offset++; 7354 return Offset; 7355 } 7356 7357 /// Class that associates information with a base pointer to be passed to the 7358 /// runtime library. 7359 class BasePointerInfo { 7360 /// The base pointer. 7361 llvm::Value *Ptr = nullptr; 7362 /// The base declaration that refers to this device pointer, or null if 7363 /// there is none. 7364 const ValueDecl *DevPtrDecl = nullptr; 7365 7366 public: 7367 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7368 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7369 llvm::Value *operator*() const { return Ptr; } 7370 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7371 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7372 }; 7373 7374 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7375 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7376 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7377 7378 /// Map between a struct and the its lowest & highest elements which have been 7379 /// mapped. 7380 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7381 /// HE(FieldIndex, Pointer)} 7382 struct StructRangeInfoTy { 7383 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7384 0, Address::invalid()}; 7385 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7386 0, Address::invalid()}; 7387 Address Base = Address::invalid(); 7388 }; 7389 7390 private: 7391 /// Kind that defines how a device pointer has to be returned. 7392 struct MapInfo { 7393 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7394 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7395 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7396 bool ReturnDevicePointer = false; 7397 bool IsImplicit = false; 7398 7399 MapInfo() = default; 7400 MapInfo( 7401 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7402 OpenMPMapClauseKind MapType, 7403 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7404 bool ReturnDevicePointer, bool IsImplicit) 7405 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7406 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7407 }; 7408 7409 /// If use_device_ptr is used on a pointer which is a struct member and there 7410 /// is no map information about it, then emission of that entry is deferred 7411 /// until the whole struct has been processed. 7412 struct DeferredDevicePtrEntryTy { 7413 const Expr *IE = nullptr; 7414 const ValueDecl *VD = nullptr; 7415 7416 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7417 : IE(IE), VD(VD) {} 7418 }; 7419 7420 /// The target directive from where the mappable clauses were extracted. It 7421 /// is either a executable directive or a user-defined mapper directive. 7422 llvm::PointerUnion<const OMPExecutableDirective *, 7423 const OMPDeclareMapperDecl *> 7424 CurDir; 7425 7426 /// Function the directive is being generated for. 7427 CodeGenFunction &CGF; 7428 7429 /// Set of all first private variables in the current directive. 7430 /// bool data is set to true if the variable is implicitly marked as 7431 /// firstprivate, false otherwise. 7432 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7433 7434 /// Map between device pointer declarations and their expression components. 7435 /// The key value for declarations in 'this' is null. 7436 llvm::DenseMap< 7437 const ValueDecl *, 7438 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7439 DevPointersMap; 7440 7441 llvm::Value *getExprTypeSize(const Expr *E) const { 7442 QualType ExprTy = E->getType().getCanonicalType(); 7443 7444 // Reference types are ignored for mapping purposes. 7445 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7446 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7447 7448 // Given that an array section is considered a built-in type, we need to 7449 // do the calculation based on the length of the section instead of relying 7450 // on CGF.getTypeSize(E->getType()). 7451 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7452 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7453 OAE->getBase()->IgnoreParenImpCasts()) 7454 .getCanonicalType(); 7455 7456 // If there is no length associated with the expression and lower bound is 7457 // not specified too, that means we are using the whole length of the 7458 // base. 7459 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7460 !OAE->getLowerBound()) 7461 return CGF.getTypeSize(BaseTy); 7462 7463 llvm::Value *ElemSize; 7464 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7465 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7466 } else { 7467 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7468 assert(ATy && "Expecting array type if not a pointer type."); 7469 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7470 } 7471 7472 // If we don't have a length at this point, that is because we have an 7473 // array section with a single element. 7474 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7475 return ElemSize; 7476 7477 if (const Expr *LenExpr = OAE->getLength()) { 7478 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7479 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7480 CGF.getContext().getSizeType(), 7481 LenExpr->getExprLoc()); 7482 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7483 } 7484 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7485 OAE->getLowerBound() && "expected array_section[lb:]."); 7486 // Size = sizetype - lb * elemtype; 7487 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7488 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7489 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7490 CGF.getContext().getSizeType(), 7491 OAE->getLowerBound()->getExprLoc()); 7492 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7493 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7494 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7495 LengthVal = CGF.Builder.CreateSelect( 7496 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7497 return LengthVal; 7498 } 7499 return CGF.getTypeSize(ExprTy); 7500 } 7501 7502 /// Return the corresponding bits for a given map clause modifier. Add 7503 /// a flag marking the map as a pointer if requested. Add a flag marking the 7504 /// map as the first one of a series of maps that relate to the same map 7505 /// expression. 7506 OpenMPOffloadMappingFlags getMapTypeBits( 7507 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7508 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7509 OpenMPOffloadMappingFlags Bits = 7510 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7511 switch (MapType) { 7512 case OMPC_MAP_alloc: 7513 case OMPC_MAP_release: 7514 // alloc and release is the default behavior in the runtime library, i.e. 7515 // if we don't pass any bits alloc/release that is what the runtime is 7516 // going to do. Therefore, we don't need to signal anything for these two 7517 // type modifiers. 7518 break; 7519 case OMPC_MAP_to: 7520 Bits |= OMP_MAP_TO; 7521 break; 7522 case OMPC_MAP_from: 7523 Bits |= OMP_MAP_FROM; 7524 break; 7525 case OMPC_MAP_tofrom: 7526 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7527 break; 7528 case OMPC_MAP_delete: 7529 Bits |= OMP_MAP_DELETE; 7530 break; 7531 case OMPC_MAP_unknown: 7532 llvm_unreachable("Unexpected map type!"); 7533 } 7534 if (AddPtrFlag) 7535 Bits |= OMP_MAP_PTR_AND_OBJ; 7536 if (AddIsTargetParamFlag) 7537 Bits |= OMP_MAP_TARGET_PARAM; 7538 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7539 != MapModifiers.end()) 7540 Bits |= OMP_MAP_ALWAYS; 7541 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7542 != MapModifiers.end()) 7543 Bits |= OMP_MAP_CLOSE; 7544 return Bits; 7545 } 7546 7547 /// Return true if the provided expression is a final array section. A 7548 /// final array section, is one whose length can't be proved to be one. 7549 bool isFinalArraySectionExpression(const Expr *E) const { 7550 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7551 7552 // It is not an array section and therefore not a unity-size one. 7553 if (!OASE) 7554 return false; 7555 7556 // An array section with no colon always refer to a single element. 7557 if (OASE->getColonLoc().isInvalid()) 7558 return false; 7559 7560 const Expr *Length = OASE->getLength(); 7561 7562 // If we don't have a length we have to check if the array has size 1 7563 // for this dimension. Also, we should always expect a length if the 7564 // base type is pointer. 7565 if (!Length) { 7566 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7567 OASE->getBase()->IgnoreParenImpCasts()) 7568 .getCanonicalType(); 7569 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7570 return ATy->getSize().getSExtValue() != 1; 7571 // If we don't have a constant dimension length, we have to consider 7572 // the current section as having any size, so it is not necessarily 7573 // unitary. If it happen to be unity size, that's user fault. 7574 return true; 7575 } 7576 7577 // Check if the length evaluates to 1. 7578 Expr::EvalResult Result; 7579 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7580 return true; // Can have more that size 1. 7581 7582 llvm::APSInt ConstLength = Result.Val.getInt(); 7583 return ConstLength.getSExtValue() != 1; 7584 } 7585 7586 /// Generate the base pointers, section pointers, sizes and map type 7587 /// bits for the provided map type, map modifier, and expression components. 7588 /// \a IsFirstComponent should be set to true if the provided set of 7589 /// components is the first associated with a capture. 7590 void generateInfoForComponentList( 7591 OpenMPMapClauseKind MapType, 7592 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7593 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7594 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7595 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7596 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7597 bool IsImplicit, 7598 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7599 OverlappedElements = llvm::None) const { 7600 // The following summarizes what has to be generated for each map and the 7601 // types below. The generated information is expressed in this order: 7602 // base pointer, section pointer, size, flags 7603 // (to add to the ones that come from the map type and modifier). 7604 // 7605 // double d; 7606 // int i[100]; 7607 // float *p; 7608 // 7609 // struct S1 { 7610 // int i; 7611 // float f[50]; 7612 // } 7613 // struct S2 { 7614 // int i; 7615 // float f[50]; 7616 // S1 s; 7617 // double *p; 7618 // struct S2 *ps; 7619 // } 7620 // S2 s; 7621 // S2 *ps; 7622 // 7623 // map(d) 7624 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7625 // 7626 // map(i) 7627 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7628 // 7629 // map(i[1:23]) 7630 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7631 // 7632 // map(p) 7633 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7634 // 7635 // map(p[1:24]) 7636 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7637 // 7638 // map(s) 7639 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7640 // 7641 // map(s.i) 7642 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7643 // 7644 // map(s.s.f) 7645 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7646 // 7647 // map(s.p) 7648 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7649 // 7650 // map(to: s.p[:22]) 7651 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7652 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7653 // &(s.p), &(s.p[0]), 22*sizeof(double), 7654 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7655 // (*) alloc space for struct members, only this is a target parameter 7656 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7657 // optimizes this entry out, same in the examples below) 7658 // (***) map the pointee (map: to) 7659 // 7660 // map(s.ps) 7661 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7662 // 7663 // map(from: s.ps->s.i) 7664 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7665 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7666 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7667 // 7668 // map(to: s.ps->ps) 7669 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7670 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7671 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7672 // 7673 // map(s.ps->ps->ps) 7674 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7675 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7676 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7677 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7678 // 7679 // map(to: s.ps->ps->s.f[:22]) 7680 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7681 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7682 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7683 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7684 // 7685 // map(ps) 7686 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7687 // 7688 // map(ps->i) 7689 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7690 // 7691 // map(ps->s.f) 7692 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7693 // 7694 // map(from: ps->p) 7695 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7696 // 7697 // map(to: ps->p[:22]) 7698 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7699 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7700 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7701 // 7702 // map(ps->ps) 7703 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7704 // 7705 // map(from: ps->ps->s.i) 7706 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7707 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7708 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7709 // 7710 // map(from: ps->ps->ps) 7711 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7712 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7713 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7714 // 7715 // map(ps->ps->ps->ps) 7716 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7717 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7718 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7719 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7720 // 7721 // map(to: ps->ps->ps->s.f[:22]) 7722 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7723 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7724 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7725 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7726 // 7727 // map(to: s.f[:22]) map(from: s.p[:33]) 7728 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7729 // sizeof(double*) (**), TARGET_PARAM 7730 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7731 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7732 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7733 // (*) allocate contiguous space needed to fit all mapped members even if 7734 // we allocate space for members not mapped (in this example, 7735 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7736 // them as well because they fall between &s.f[0] and &s.p) 7737 // 7738 // map(from: s.f[:22]) map(to: ps->p[:33]) 7739 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7740 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7741 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7742 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7743 // (*) the struct this entry pertains to is the 2nd element in the list of 7744 // arguments, hence MEMBER_OF(2) 7745 // 7746 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7747 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7748 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7749 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7750 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7751 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7752 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7753 // (*) the struct this entry pertains to is the 4th element in the list 7754 // of arguments, hence MEMBER_OF(4) 7755 7756 // Track if the map information being generated is the first for a capture. 7757 bool IsCaptureFirstInfo = IsFirstComponentList; 7758 // When the variable is on a declare target link or in a to clause with 7759 // unified memory, a reference is needed to hold the host/device address 7760 // of the variable. 7761 bool RequiresReference = false; 7762 7763 // Scan the components from the base to the complete expression. 7764 auto CI = Components.rbegin(); 7765 auto CE = Components.rend(); 7766 auto I = CI; 7767 7768 // Track if the map information being generated is the first for a list of 7769 // components. 7770 bool IsExpressionFirstInfo = true; 7771 Address BP = Address::invalid(); 7772 const Expr *AssocExpr = I->getAssociatedExpression(); 7773 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7774 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7775 7776 if (isa<MemberExpr>(AssocExpr)) { 7777 // The base is the 'this' pointer. The content of the pointer is going 7778 // to be the base of the field being mapped. 7779 BP = CGF.LoadCXXThisAddress(); 7780 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7781 (OASE && 7782 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7783 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7784 } else { 7785 // The base is the reference to the variable. 7786 // BP = &Var. 7787 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7788 if (const auto *VD = 7789 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7790 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7791 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7792 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7793 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7794 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7795 RequiresReference = true; 7796 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7797 } 7798 } 7799 } 7800 7801 // If the variable is a pointer and is being dereferenced (i.e. is not 7802 // the last component), the base has to be the pointer itself, not its 7803 // reference. References are ignored for mapping purposes. 7804 QualType Ty = 7805 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7806 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7807 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7808 7809 // We do not need to generate individual map information for the 7810 // pointer, it can be associated with the combined storage. 7811 ++I; 7812 } 7813 } 7814 7815 // Track whether a component of the list should be marked as MEMBER_OF some 7816 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7817 // in a component list should be marked as MEMBER_OF, all subsequent entries 7818 // do not belong to the base struct. E.g. 7819 // struct S2 s; 7820 // s.ps->ps->ps->f[:] 7821 // (1) (2) (3) (4) 7822 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7823 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7824 // is the pointee of ps(2) which is not member of struct s, so it should not 7825 // be marked as such (it is still PTR_AND_OBJ). 7826 // The variable is initialized to false so that PTR_AND_OBJ entries which 7827 // are not struct members are not considered (e.g. array of pointers to 7828 // data). 7829 bool ShouldBeMemberOf = false; 7830 7831 // Variable keeping track of whether or not we have encountered a component 7832 // in the component list which is a member expression. Useful when we have a 7833 // pointer or a final array section, in which case it is the previous 7834 // component in the list which tells us whether we have a member expression. 7835 // E.g. X.f[:] 7836 // While processing the final array section "[:]" it is "f" which tells us 7837 // whether we are dealing with a member of a declared struct. 7838 const MemberExpr *EncounteredME = nullptr; 7839 7840 for (; I != CE; ++I) { 7841 // If the current component is member of a struct (parent struct) mark it. 7842 if (!EncounteredME) { 7843 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7844 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7845 // as MEMBER_OF the parent struct. 7846 if (EncounteredME) 7847 ShouldBeMemberOf = true; 7848 } 7849 7850 auto Next = std::next(I); 7851 7852 // We need to generate the addresses and sizes if this is the last 7853 // component, if the component is a pointer or if it is an array section 7854 // whose length can't be proved to be one. If this is a pointer, it 7855 // becomes the base address for the following components. 7856 7857 // A final array section, is one whose length can't be proved to be one. 7858 bool IsFinalArraySection = 7859 isFinalArraySectionExpression(I->getAssociatedExpression()); 7860 7861 // Get information on whether the element is a pointer. Have to do a 7862 // special treatment for array sections given that they are built-in 7863 // types. 7864 const auto *OASE = 7865 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7866 const auto *UO = dyn_cast<UnaryOperator>(I->getAssociatedExpression()); 7867 const auto *BO = dyn_cast<BinaryOperator>(I->getAssociatedExpression()); 7868 bool IsPointer = 7869 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7870 .getCanonicalType() 7871 ->isAnyPointerType()) || 7872 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7873 bool IsNonDerefPointer = IsPointer && !UO && !BO; 7874 7875 if (Next == CE || IsNonDerefPointer || IsFinalArraySection) { 7876 // If this is not the last component, we expect the pointer to be 7877 // associated with an array expression or member expression. 7878 assert((Next == CE || 7879 isa<MemberExpr>(Next->getAssociatedExpression()) || 7880 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7881 isa<OMPArraySectionExpr>(Next->getAssociatedExpression()) || 7882 isa<UnaryOperator>(Next->getAssociatedExpression()) || 7883 isa<BinaryOperator>(Next->getAssociatedExpression())) && 7884 "Unexpected expression"); 7885 7886 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7887 .getAddress(CGF); 7888 7889 // If this component is a pointer inside the base struct then we don't 7890 // need to create any entry for it - it will be combined with the object 7891 // it is pointing to into a single PTR_AND_OBJ entry. 7892 bool IsMemberPointer = 7893 IsPointer && EncounteredME && 7894 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7895 EncounteredME); 7896 if (!OverlappedElements.empty()) { 7897 // Handle base element with the info for overlapped elements. 7898 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7899 assert(Next == CE && 7900 "Expected last element for the overlapped elements."); 7901 assert(!IsPointer && 7902 "Unexpected base element with the pointer type."); 7903 // Mark the whole struct as the struct that requires allocation on the 7904 // device. 7905 PartialStruct.LowestElem = {0, LB}; 7906 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7907 I->getAssociatedExpression()->getType()); 7908 Address HB = CGF.Builder.CreateConstGEP( 7909 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7910 CGF.VoidPtrTy), 7911 TypeSize.getQuantity() - 1); 7912 PartialStruct.HighestElem = { 7913 std::numeric_limits<decltype( 7914 PartialStruct.HighestElem.first)>::max(), 7915 HB}; 7916 PartialStruct.Base = BP; 7917 // Emit data for non-overlapped data. 7918 OpenMPOffloadMappingFlags Flags = 7919 OMP_MAP_MEMBER_OF | 7920 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7921 /*AddPtrFlag=*/false, 7922 /*AddIsTargetParamFlag=*/false); 7923 LB = BP; 7924 llvm::Value *Size = nullptr; 7925 // Do bitcopy of all non-overlapped structure elements. 7926 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7927 Component : OverlappedElements) { 7928 Address ComponentLB = Address::invalid(); 7929 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7930 Component) { 7931 if (MC.getAssociatedDeclaration()) { 7932 ComponentLB = 7933 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7934 .getAddress(CGF); 7935 Size = CGF.Builder.CreatePtrDiff( 7936 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7937 CGF.EmitCastToVoidPtr(LB.getPointer())); 7938 break; 7939 } 7940 } 7941 BasePointers.push_back(BP.getPointer()); 7942 Pointers.push_back(LB.getPointer()); 7943 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7944 /*isSigned=*/true)); 7945 Types.push_back(Flags); 7946 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7947 } 7948 BasePointers.push_back(BP.getPointer()); 7949 Pointers.push_back(LB.getPointer()); 7950 Size = CGF.Builder.CreatePtrDiff( 7951 CGF.EmitCastToVoidPtr( 7952 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7953 CGF.EmitCastToVoidPtr(LB.getPointer())); 7954 Sizes.push_back( 7955 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7956 Types.push_back(Flags); 7957 break; 7958 } 7959 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7960 if (!IsMemberPointer) { 7961 BasePointers.push_back(BP.getPointer()); 7962 Pointers.push_back(LB.getPointer()); 7963 Sizes.push_back( 7964 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7965 7966 // We need to add a pointer flag for each map that comes from the 7967 // same expression except for the first one. We also need to signal 7968 // this map is the first one that relates with the current capture 7969 // (there is a set of entries for each capture). 7970 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7971 MapType, MapModifiers, IsImplicit, 7972 !IsExpressionFirstInfo || RequiresReference, 7973 IsCaptureFirstInfo && !RequiresReference); 7974 7975 if (!IsExpressionFirstInfo) { 7976 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7977 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7978 if (IsPointer) 7979 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7980 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7981 7982 if (ShouldBeMemberOf) { 7983 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7984 // should be later updated with the correct value of MEMBER_OF. 7985 Flags |= OMP_MAP_MEMBER_OF; 7986 // From now on, all subsequent PTR_AND_OBJ entries should not be 7987 // marked as MEMBER_OF. 7988 ShouldBeMemberOf = false; 7989 } 7990 } 7991 7992 Types.push_back(Flags); 7993 } 7994 7995 // If we have encountered a member expression so far, keep track of the 7996 // mapped member. If the parent is "*this", then the value declaration 7997 // is nullptr. 7998 if (EncounteredME) { 7999 const auto *FD = cast<FieldDecl>(EncounteredME->getMemberDecl()); 8000 unsigned FieldIndex = FD->getFieldIndex(); 8001 8002 // Update info about the lowest and highest elements for this struct 8003 if (!PartialStruct.Base.isValid()) { 8004 PartialStruct.LowestElem = {FieldIndex, LB}; 8005 PartialStruct.HighestElem = {FieldIndex, LB}; 8006 PartialStruct.Base = BP; 8007 } else if (FieldIndex < PartialStruct.LowestElem.first) { 8008 PartialStruct.LowestElem = {FieldIndex, LB}; 8009 } else if (FieldIndex > PartialStruct.HighestElem.first) { 8010 PartialStruct.HighestElem = {FieldIndex, LB}; 8011 } 8012 } 8013 8014 // If we have a final array section, we are done with this expression. 8015 if (IsFinalArraySection) 8016 break; 8017 8018 // The pointer becomes the base for the next element. 8019 if (Next != CE) 8020 BP = LB; 8021 8022 IsExpressionFirstInfo = false; 8023 IsCaptureFirstInfo = false; 8024 } 8025 } 8026 } 8027 8028 /// Return the adjusted map modifiers if the declaration a capture refers to 8029 /// appears in a first-private clause. This is expected to be used only with 8030 /// directives that start with 'target'. 8031 MappableExprsHandler::OpenMPOffloadMappingFlags 8032 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 8033 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 8034 8035 // A first private variable captured by reference will use only the 8036 // 'private ptr' and 'map to' flag. Return the right flags if the captured 8037 // declaration is known as first-private in this handler. 8038 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 8039 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 8040 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 8041 return MappableExprsHandler::OMP_MAP_ALWAYS | 8042 MappableExprsHandler::OMP_MAP_TO; 8043 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 8044 return MappableExprsHandler::OMP_MAP_TO | 8045 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 8046 return MappableExprsHandler::OMP_MAP_PRIVATE | 8047 MappableExprsHandler::OMP_MAP_TO; 8048 } 8049 return MappableExprsHandler::OMP_MAP_TO | 8050 MappableExprsHandler::OMP_MAP_FROM; 8051 } 8052 8053 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 8054 // Rotate by getFlagMemberOffset() bits. 8055 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 8056 << getFlagMemberOffset()); 8057 } 8058 8059 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 8060 OpenMPOffloadMappingFlags MemberOfFlag) { 8061 // If the entry is PTR_AND_OBJ but has not been marked with the special 8062 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 8063 // marked as MEMBER_OF. 8064 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 8065 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 8066 return; 8067 8068 // Reset the placeholder value to prepare the flag for the assignment of the 8069 // proper MEMBER_OF value. 8070 Flags &= ~OMP_MAP_MEMBER_OF; 8071 Flags |= MemberOfFlag; 8072 } 8073 8074 void getPlainLayout(const CXXRecordDecl *RD, 8075 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 8076 bool AsBase) const { 8077 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 8078 8079 llvm::StructType *St = 8080 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 8081 8082 unsigned NumElements = St->getNumElements(); 8083 llvm::SmallVector< 8084 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 8085 RecordLayout(NumElements); 8086 8087 // Fill bases. 8088 for (const auto &I : RD->bases()) { 8089 if (I.isVirtual()) 8090 continue; 8091 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8092 // Ignore empty bases. 8093 if (Base->isEmpty() || CGF.getContext() 8094 .getASTRecordLayout(Base) 8095 .getNonVirtualSize() 8096 .isZero()) 8097 continue; 8098 8099 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 8100 RecordLayout[FieldIndex] = Base; 8101 } 8102 // Fill in virtual bases. 8103 for (const auto &I : RD->vbases()) { 8104 const auto *Base = I.getType()->getAsCXXRecordDecl(); 8105 // Ignore empty bases. 8106 if (Base->isEmpty()) 8107 continue; 8108 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 8109 if (RecordLayout[FieldIndex]) 8110 continue; 8111 RecordLayout[FieldIndex] = Base; 8112 } 8113 // Fill in all the fields. 8114 assert(!RD->isUnion() && "Unexpected union."); 8115 for (const auto *Field : RD->fields()) { 8116 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 8117 // will fill in later.) 8118 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 8119 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 8120 RecordLayout[FieldIndex] = Field; 8121 } 8122 } 8123 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 8124 &Data : RecordLayout) { 8125 if (Data.isNull()) 8126 continue; 8127 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 8128 getPlainLayout(Base, Layout, /*AsBase=*/true); 8129 else 8130 Layout.push_back(Data.get<const FieldDecl *>()); 8131 } 8132 } 8133 8134 public: 8135 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 8136 : CurDir(&Dir), CGF(CGF) { 8137 // Extract firstprivate clause information. 8138 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 8139 for (const auto *D : C->varlists()) 8140 FirstPrivateDecls.try_emplace( 8141 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 8142 // Extract device pointer clause information. 8143 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 8144 for (auto L : C->component_lists()) 8145 DevPointersMap[L.first].push_back(L.second); 8146 } 8147 8148 /// Constructor for the declare mapper directive. 8149 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 8150 : CurDir(&Dir), CGF(CGF) {} 8151 8152 /// Generate code for the combined entry if we have a partially mapped struct 8153 /// and take care of the mapping flags of the arguments corresponding to 8154 /// individual struct members. 8155 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 8156 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8157 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 8158 const StructRangeInfoTy &PartialStruct) const { 8159 // Base is the base of the struct 8160 BasePointers.push_back(PartialStruct.Base.getPointer()); 8161 // Pointer is the address of the lowest element 8162 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 8163 Pointers.push_back(LB); 8164 // Size is (addr of {highest+1} element) - (addr of lowest element) 8165 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 8166 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 8167 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 8168 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 8169 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 8170 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 8171 /*isSigned=*/false); 8172 Sizes.push_back(Size); 8173 // Map type is always TARGET_PARAM 8174 Types.push_back(OMP_MAP_TARGET_PARAM); 8175 // Remove TARGET_PARAM flag from the first element 8176 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 8177 8178 // All other current entries will be MEMBER_OF the combined entry 8179 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8180 // 0xFFFF in the MEMBER_OF field). 8181 OpenMPOffloadMappingFlags MemberOfFlag = 8182 getMemberOfFlag(BasePointers.size() - 1); 8183 for (auto &M : CurTypes) 8184 setCorrectMemberOfFlag(M, MemberOfFlag); 8185 } 8186 8187 /// Generate all the base pointers, section pointers, sizes and map 8188 /// types for the extracted mappable expressions. Also, for each item that 8189 /// relates with a device pointer, a pair of the relevant declaration and 8190 /// index where it occurs is appended to the device pointers info array. 8191 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 8192 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8193 MapFlagsArrayTy &Types) const { 8194 // We have to process the component lists that relate with the same 8195 // declaration in a single chunk so that we can generate the map flags 8196 // correctly. Therefore, we organize all lists in a map. 8197 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8198 8199 // Helper function to fill the information map for the different supported 8200 // clauses. 8201 auto &&InfoGen = [&Info]( 8202 const ValueDecl *D, 8203 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8204 OpenMPMapClauseKind MapType, 8205 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8206 bool ReturnDevicePointer, bool IsImplicit) { 8207 const ValueDecl *VD = 8208 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8209 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8210 IsImplicit); 8211 }; 8212 8213 assert(CurDir.is<const OMPExecutableDirective *>() && 8214 "Expect a executable directive"); 8215 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8216 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 8217 for (const auto L : C->component_lists()) { 8218 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 8219 /*ReturnDevicePointer=*/false, C->isImplicit()); 8220 } 8221 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 8222 for (const auto L : C->component_lists()) { 8223 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 8224 /*ReturnDevicePointer=*/false, C->isImplicit()); 8225 } 8226 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 8227 for (const auto L : C->component_lists()) { 8228 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 8229 /*ReturnDevicePointer=*/false, C->isImplicit()); 8230 } 8231 8232 // Look at the use_device_ptr clause information and mark the existing map 8233 // entries as such. If there is no map information for an entry in the 8234 // use_device_ptr list, we create one with map type 'alloc' and zero size 8235 // section. It is the user fault if that was not mapped before. If there is 8236 // no map information and the pointer is a struct member, then we defer the 8237 // emission of that entry until the whole struct has been processed. 8238 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 8239 DeferredInfo; 8240 8241 for (const auto *C : 8242 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 8243 for (const auto L : C->component_lists()) { 8244 assert(!L.second.empty() && "Not expecting empty list of components!"); 8245 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 8246 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8247 const Expr *IE = L.second.back().getAssociatedExpression(); 8248 // If the first component is a member expression, we have to look into 8249 // 'this', which maps to null in the map of map information. Otherwise 8250 // look directly for the information. 8251 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8252 8253 // We potentially have map information for this declaration already. 8254 // Look for the first set of components that refer to it. 8255 if (It != Info.end()) { 8256 auto CI = std::find_if( 8257 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 8258 return MI.Components.back().getAssociatedDeclaration() == VD; 8259 }); 8260 // If we found a map entry, signal that the pointer has to be returned 8261 // and move on to the next declaration. 8262 if (CI != It->second.end()) { 8263 CI->ReturnDevicePointer = true; 8264 continue; 8265 } 8266 } 8267 8268 // We didn't find any match in our map information - generate a zero 8269 // size array section - if the pointer is a struct member we defer this 8270 // action until the whole struct has been processed. 8271 if (isa<MemberExpr>(IE)) { 8272 // Insert the pointer into Info to be processed by 8273 // generateInfoForComponentList. Because it is a member pointer 8274 // without a pointee, no entry will be generated for it, therefore 8275 // we need to generate one after the whole struct has been processed. 8276 // Nonetheless, generateInfoForComponentList must be called to take 8277 // the pointer into account for the calculation of the range of the 8278 // partial struct. 8279 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 8280 /*ReturnDevicePointer=*/false, C->isImplicit()); 8281 DeferredInfo[nullptr].emplace_back(IE, VD); 8282 } else { 8283 llvm::Value *Ptr = 8284 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8285 BasePointers.emplace_back(Ptr, VD); 8286 Pointers.push_back(Ptr); 8287 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8288 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8289 } 8290 } 8291 } 8292 8293 for (const auto &M : Info) { 8294 // We need to know when we generate information for the first component 8295 // associated with a capture, because the mapping flags depend on it. 8296 bool IsFirstComponentList = true; 8297 8298 // Temporary versions of arrays 8299 MapBaseValuesArrayTy CurBasePointers; 8300 MapValuesArrayTy CurPointers; 8301 MapValuesArrayTy CurSizes; 8302 MapFlagsArrayTy CurTypes; 8303 StructRangeInfoTy PartialStruct; 8304 8305 for (const MapInfo &L : M.second) { 8306 assert(!L.Components.empty() && 8307 "Not expecting declaration with no component lists."); 8308 8309 // Remember the current base pointer index. 8310 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8311 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8312 CurBasePointers, CurPointers, CurSizes, 8313 CurTypes, PartialStruct, 8314 IsFirstComponentList, L.IsImplicit); 8315 8316 // If this entry relates with a device pointer, set the relevant 8317 // declaration and add the 'return pointer' flag. 8318 if (L.ReturnDevicePointer) { 8319 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8320 "Unexpected number of mapped base pointers."); 8321 8322 const ValueDecl *RelevantVD = 8323 L.Components.back().getAssociatedDeclaration(); 8324 assert(RelevantVD && 8325 "No relevant declaration related with device pointer??"); 8326 8327 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8328 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8329 } 8330 IsFirstComponentList = false; 8331 } 8332 8333 // Append any pending zero-length pointers which are struct members and 8334 // used with use_device_ptr. 8335 auto CI = DeferredInfo.find(M.first); 8336 if (CI != DeferredInfo.end()) { 8337 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8338 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8339 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8340 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8341 CurBasePointers.emplace_back(BasePtr, L.VD); 8342 CurPointers.push_back(Ptr); 8343 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8344 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8345 // value MEMBER_OF=FFFF so that the entry is later updated with the 8346 // correct value of MEMBER_OF. 8347 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8348 OMP_MAP_MEMBER_OF); 8349 } 8350 } 8351 8352 // If there is an entry in PartialStruct it means we have a struct with 8353 // individual members mapped. Emit an extra combined entry. 8354 if (PartialStruct.Base.isValid()) 8355 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8356 PartialStruct); 8357 8358 // We need to append the results of this capture to what we already have. 8359 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8360 Pointers.append(CurPointers.begin(), CurPointers.end()); 8361 Sizes.append(CurSizes.begin(), CurSizes.end()); 8362 Types.append(CurTypes.begin(), CurTypes.end()); 8363 } 8364 } 8365 8366 /// Generate all the base pointers, section pointers, sizes and map types for 8367 /// the extracted map clauses of user-defined mapper. 8368 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8369 MapValuesArrayTy &Pointers, 8370 MapValuesArrayTy &Sizes, 8371 MapFlagsArrayTy &Types) const { 8372 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8373 "Expect a declare mapper directive"); 8374 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8375 // We have to process the component lists that relate with the same 8376 // declaration in a single chunk so that we can generate the map flags 8377 // correctly. Therefore, we organize all lists in a map. 8378 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8379 8380 // Helper function to fill the information map for the different supported 8381 // clauses. 8382 auto &&InfoGen = [&Info]( 8383 const ValueDecl *D, 8384 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8385 OpenMPMapClauseKind MapType, 8386 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8387 bool ReturnDevicePointer, bool IsImplicit) { 8388 const ValueDecl *VD = 8389 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8390 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8391 IsImplicit); 8392 }; 8393 8394 for (const auto *C : CurMapperDir->clauselists()) { 8395 const auto *MC = cast<OMPMapClause>(C); 8396 for (const auto L : MC->component_lists()) { 8397 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8398 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8399 } 8400 } 8401 8402 for (const auto &M : Info) { 8403 // We need to know when we generate information for the first component 8404 // associated with a capture, because the mapping flags depend on it. 8405 bool IsFirstComponentList = true; 8406 8407 // Temporary versions of arrays 8408 MapBaseValuesArrayTy CurBasePointers; 8409 MapValuesArrayTy CurPointers; 8410 MapValuesArrayTy CurSizes; 8411 MapFlagsArrayTy CurTypes; 8412 StructRangeInfoTy PartialStruct; 8413 8414 for (const MapInfo &L : M.second) { 8415 assert(!L.Components.empty() && 8416 "Not expecting declaration with no component lists."); 8417 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8418 CurBasePointers, CurPointers, CurSizes, 8419 CurTypes, PartialStruct, 8420 IsFirstComponentList, L.IsImplicit); 8421 IsFirstComponentList = false; 8422 } 8423 8424 // If there is an entry in PartialStruct it means we have a struct with 8425 // individual members mapped. Emit an extra combined entry. 8426 if (PartialStruct.Base.isValid()) 8427 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8428 PartialStruct); 8429 8430 // We need to append the results of this capture to what we already have. 8431 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8432 Pointers.append(CurPointers.begin(), CurPointers.end()); 8433 Sizes.append(CurSizes.begin(), CurSizes.end()); 8434 Types.append(CurTypes.begin(), CurTypes.end()); 8435 } 8436 } 8437 8438 /// Emit capture info for lambdas for variables captured by reference. 8439 void generateInfoForLambdaCaptures( 8440 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8441 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8442 MapFlagsArrayTy &Types, 8443 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8444 const auto *RD = VD->getType() 8445 .getCanonicalType() 8446 .getNonReferenceType() 8447 ->getAsCXXRecordDecl(); 8448 if (!RD || !RD->isLambda()) 8449 return; 8450 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8451 LValue VDLVal = CGF.MakeAddrLValue( 8452 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8453 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8454 FieldDecl *ThisCapture = nullptr; 8455 RD->getCaptureFields(Captures, ThisCapture); 8456 if (ThisCapture) { 8457 LValue ThisLVal = 8458 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8459 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8460 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8461 VDLVal.getPointer(CGF)); 8462 BasePointers.push_back(ThisLVal.getPointer(CGF)); 8463 Pointers.push_back(ThisLValVal.getPointer(CGF)); 8464 Sizes.push_back( 8465 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8466 CGF.Int64Ty, /*isSigned=*/true)); 8467 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8468 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8469 } 8470 for (const LambdaCapture &LC : RD->captures()) { 8471 if (!LC.capturesVariable()) 8472 continue; 8473 const VarDecl *VD = LC.getCapturedVar(); 8474 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8475 continue; 8476 auto It = Captures.find(VD); 8477 assert(It != Captures.end() && "Found lambda capture without field."); 8478 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8479 if (LC.getCaptureKind() == LCK_ByRef) { 8480 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8481 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8482 VDLVal.getPointer(CGF)); 8483 BasePointers.push_back(VarLVal.getPointer(CGF)); 8484 Pointers.push_back(VarLValVal.getPointer(CGF)); 8485 Sizes.push_back(CGF.Builder.CreateIntCast( 8486 CGF.getTypeSize( 8487 VD->getType().getCanonicalType().getNonReferenceType()), 8488 CGF.Int64Ty, /*isSigned=*/true)); 8489 } else { 8490 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8491 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8492 VDLVal.getPointer(CGF)); 8493 BasePointers.push_back(VarLVal.getPointer(CGF)); 8494 Pointers.push_back(VarRVal.getScalarVal()); 8495 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8496 } 8497 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8498 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8499 } 8500 } 8501 8502 /// Set correct indices for lambdas captures. 8503 void adjustMemberOfForLambdaCaptures( 8504 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8505 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8506 MapFlagsArrayTy &Types) const { 8507 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8508 // Set correct member_of idx for all implicit lambda captures. 8509 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8510 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8511 continue; 8512 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8513 assert(BasePtr && "Unable to find base lambda address."); 8514 int TgtIdx = -1; 8515 for (unsigned J = I; J > 0; --J) { 8516 unsigned Idx = J - 1; 8517 if (Pointers[Idx] != BasePtr) 8518 continue; 8519 TgtIdx = Idx; 8520 break; 8521 } 8522 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8523 // All other current entries will be MEMBER_OF the combined entry 8524 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8525 // 0xFFFF in the MEMBER_OF field). 8526 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8527 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8528 } 8529 } 8530 8531 /// Generate the base pointers, section pointers, sizes and map types 8532 /// associated to a given capture. 8533 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8534 llvm::Value *Arg, 8535 MapBaseValuesArrayTy &BasePointers, 8536 MapValuesArrayTy &Pointers, 8537 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8538 StructRangeInfoTy &PartialStruct) const { 8539 assert(!Cap->capturesVariableArrayType() && 8540 "Not expecting to generate map info for a variable array type!"); 8541 8542 // We need to know when we generating information for the first component 8543 const ValueDecl *VD = Cap->capturesThis() 8544 ? nullptr 8545 : Cap->getCapturedVar()->getCanonicalDecl(); 8546 8547 // If this declaration appears in a is_device_ptr clause we just have to 8548 // pass the pointer by value. If it is a reference to a declaration, we just 8549 // pass its value. 8550 if (DevPointersMap.count(VD)) { 8551 BasePointers.emplace_back(Arg, VD); 8552 Pointers.push_back(Arg); 8553 Sizes.push_back( 8554 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8555 CGF.Int64Ty, /*isSigned=*/true)); 8556 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8557 return; 8558 } 8559 8560 using MapData = 8561 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8562 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8563 SmallVector<MapData, 4> DeclComponentLists; 8564 assert(CurDir.is<const OMPExecutableDirective *>() && 8565 "Expect a executable directive"); 8566 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8567 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8568 for (const auto L : C->decl_component_lists(VD)) { 8569 assert(L.first == VD && 8570 "We got information for the wrong declaration??"); 8571 assert(!L.second.empty() && 8572 "Not expecting declaration with no component lists."); 8573 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8574 C->getMapTypeModifiers(), 8575 C->isImplicit()); 8576 } 8577 } 8578 8579 // Find overlapping elements (including the offset from the base element). 8580 llvm::SmallDenseMap< 8581 const MapData *, 8582 llvm::SmallVector< 8583 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8584 4> 8585 OverlappedData; 8586 size_t Count = 0; 8587 for (const MapData &L : DeclComponentLists) { 8588 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8589 OpenMPMapClauseKind MapType; 8590 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8591 bool IsImplicit; 8592 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8593 ++Count; 8594 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8595 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8596 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8597 auto CI = Components.rbegin(); 8598 auto CE = Components.rend(); 8599 auto SI = Components1.rbegin(); 8600 auto SE = Components1.rend(); 8601 for (; CI != CE && SI != SE; ++CI, ++SI) { 8602 if (CI->getAssociatedExpression()->getStmtClass() != 8603 SI->getAssociatedExpression()->getStmtClass()) 8604 break; 8605 // Are we dealing with different variables/fields? 8606 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8607 break; 8608 } 8609 // Found overlapping if, at least for one component, reached the head of 8610 // the components list. 8611 if (CI == CE || SI == SE) { 8612 assert((CI != CE || SI != SE) && 8613 "Unexpected full match of the mapping components."); 8614 const MapData &BaseData = CI == CE ? L : L1; 8615 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8616 SI == SE ? Components : Components1; 8617 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8618 OverlappedElements.getSecond().push_back(SubData); 8619 } 8620 } 8621 } 8622 // Sort the overlapped elements for each item. 8623 llvm::SmallVector<const FieldDecl *, 4> Layout; 8624 if (!OverlappedData.empty()) { 8625 if (const auto *CRD = 8626 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8627 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8628 else { 8629 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8630 Layout.append(RD->field_begin(), RD->field_end()); 8631 } 8632 } 8633 for (auto &Pair : OverlappedData) { 8634 llvm::sort( 8635 Pair.getSecond(), 8636 [&Layout]( 8637 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8638 OMPClauseMappableExprCommon::MappableExprComponentListRef 8639 Second) { 8640 auto CI = First.rbegin(); 8641 auto CE = First.rend(); 8642 auto SI = Second.rbegin(); 8643 auto SE = Second.rend(); 8644 for (; CI != CE && SI != SE; ++CI, ++SI) { 8645 if (CI->getAssociatedExpression()->getStmtClass() != 8646 SI->getAssociatedExpression()->getStmtClass()) 8647 break; 8648 // Are we dealing with different variables/fields? 8649 if (CI->getAssociatedDeclaration() != 8650 SI->getAssociatedDeclaration()) 8651 break; 8652 } 8653 8654 // Lists contain the same elements. 8655 if (CI == CE && SI == SE) 8656 return false; 8657 8658 // List with less elements is less than list with more elements. 8659 if (CI == CE || SI == SE) 8660 return CI == CE; 8661 8662 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8663 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8664 if (FD1->getParent() == FD2->getParent()) 8665 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8666 const auto It = 8667 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8668 return FD == FD1 || FD == FD2; 8669 }); 8670 return *It == FD1; 8671 }); 8672 } 8673 8674 // Associated with a capture, because the mapping flags depend on it. 8675 // Go through all of the elements with the overlapped elements. 8676 for (const auto &Pair : OverlappedData) { 8677 const MapData &L = *Pair.getFirst(); 8678 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8679 OpenMPMapClauseKind MapType; 8680 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8681 bool IsImplicit; 8682 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8683 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8684 OverlappedComponents = Pair.getSecond(); 8685 bool IsFirstComponentList = true; 8686 generateInfoForComponentList(MapType, MapModifiers, Components, 8687 BasePointers, Pointers, Sizes, Types, 8688 PartialStruct, IsFirstComponentList, 8689 IsImplicit, OverlappedComponents); 8690 } 8691 // Go through other elements without overlapped elements. 8692 bool IsFirstComponentList = OverlappedData.empty(); 8693 for (const MapData &L : DeclComponentLists) { 8694 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8695 OpenMPMapClauseKind MapType; 8696 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8697 bool IsImplicit; 8698 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8699 auto It = OverlappedData.find(&L); 8700 if (It == OverlappedData.end()) 8701 generateInfoForComponentList(MapType, MapModifiers, Components, 8702 BasePointers, Pointers, Sizes, Types, 8703 PartialStruct, IsFirstComponentList, 8704 IsImplicit); 8705 IsFirstComponentList = false; 8706 } 8707 } 8708 8709 /// Generate the base pointers, section pointers, sizes and map types 8710 /// associated with the declare target link variables. 8711 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8712 MapValuesArrayTy &Pointers, 8713 MapValuesArrayTy &Sizes, 8714 MapFlagsArrayTy &Types) const { 8715 assert(CurDir.is<const OMPExecutableDirective *>() && 8716 "Expect a executable directive"); 8717 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8718 // Map other list items in the map clause which are not captured variables 8719 // but "declare target link" global variables. 8720 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8721 for (const auto L : C->component_lists()) { 8722 if (!L.first) 8723 continue; 8724 const auto *VD = dyn_cast<VarDecl>(L.first); 8725 if (!VD) 8726 continue; 8727 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8728 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8729 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8730 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8731 continue; 8732 StructRangeInfoTy PartialStruct; 8733 generateInfoForComponentList( 8734 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8735 Pointers, Sizes, Types, PartialStruct, 8736 /*IsFirstComponentList=*/true, C->isImplicit()); 8737 assert(!PartialStruct.Base.isValid() && 8738 "No partial structs for declare target link expected."); 8739 } 8740 } 8741 } 8742 8743 /// Generate the default map information for a given capture \a CI, 8744 /// record field declaration \a RI and captured value \a CV. 8745 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8746 const FieldDecl &RI, llvm::Value *CV, 8747 MapBaseValuesArrayTy &CurBasePointers, 8748 MapValuesArrayTy &CurPointers, 8749 MapValuesArrayTy &CurSizes, 8750 MapFlagsArrayTy &CurMapTypes) const { 8751 bool IsImplicit = true; 8752 // Do the default mapping. 8753 if (CI.capturesThis()) { 8754 CurBasePointers.push_back(CV); 8755 CurPointers.push_back(CV); 8756 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8757 CurSizes.push_back( 8758 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8759 CGF.Int64Ty, /*isSigned=*/true)); 8760 // Default map type. 8761 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8762 } else if (CI.capturesVariableByCopy()) { 8763 CurBasePointers.push_back(CV); 8764 CurPointers.push_back(CV); 8765 if (!RI.getType()->isAnyPointerType()) { 8766 // We have to signal to the runtime captures passed by value that are 8767 // not pointers. 8768 CurMapTypes.push_back(OMP_MAP_LITERAL); 8769 CurSizes.push_back(CGF.Builder.CreateIntCast( 8770 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8771 } else { 8772 // Pointers are implicitly mapped with a zero size and no flags 8773 // (other than first map that is added for all implicit maps). 8774 CurMapTypes.push_back(OMP_MAP_NONE); 8775 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8776 } 8777 const VarDecl *VD = CI.getCapturedVar(); 8778 auto I = FirstPrivateDecls.find(VD); 8779 if (I != FirstPrivateDecls.end()) 8780 IsImplicit = I->getSecond(); 8781 } else { 8782 assert(CI.capturesVariable() && "Expected captured reference."); 8783 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8784 QualType ElementType = PtrTy->getPointeeType(); 8785 CurSizes.push_back(CGF.Builder.CreateIntCast( 8786 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8787 // The default map type for a scalar/complex type is 'to' because by 8788 // default the value doesn't have to be retrieved. For an aggregate 8789 // type, the default is 'tofrom'. 8790 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8791 const VarDecl *VD = CI.getCapturedVar(); 8792 auto I = FirstPrivateDecls.find(VD); 8793 if (I != FirstPrivateDecls.end() && 8794 VD->getType().isConstant(CGF.getContext())) { 8795 llvm::Constant *Addr = 8796 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8797 // Copy the value of the original variable to the new global copy. 8798 CGF.Builder.CreateMemCpy( 8799 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 8800 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8801 CurSizes.back(), /*IsVolatile=*/false); 8802 // Use new global variable as the base pointers. 8803 CurBasePointers.push_back(Addr); 8804 CurPointers.push_back(Addr); 8805 } else { 8806 CurBasePointers.push_back(CV); 8807 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8808 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8809 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8810 AlignmentSource::Decl)); 8811 CurPointers.push_back(PtrAddr.getPointer()); 8812 } else { 8813 CurPointers.push_back(CV); 8814 } 8815 } 8816 if (I != FirstPrivateDecls.end()) 8817 IsImplicit = I->getSecond(); 8818 } 8819 // Every default map produces a single argument which is a target parameter. 8820 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8821 8822 // Add flag stating this is an implicit map. 8823 if (IsImplicit) 8824 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8825 } 8826 }; 8827 } // anonymous namespace 8828 8829 /// Emit the arrays used to pass the captures and map information to the 8830 /// offloading runtime library. If there is no map or capture information, 8831 /// return nullptr by reference. 8832 static void 8833 emitOffloadingArrays(CodeGenFunction &CGF, 8834 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8835 MappableExprsHandler::MapValuesArrayTy &Pointers, 8836 MappableExprsHandler::MapValuesArrayTy &Sizes, 8837 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8838 CGOpenMPRuntime::TargetDataInfo &Info) { 8839 CodeGenModule &CGM = CGF.CGM; 8840 ASTContext &Ctx = CGF.getContext(); 8841 8842 // Reset the array information. 8843 Info.clearArrayInfo(); 8844 Info.NumberOfPtrs = BasePointers.size(); 8845 8846 if (Info.NumberOfPtrs) { 8847 // Detect if we have any capture size requiring runtime evaluation of the 8848 // size so that a constant array could be eventually used. 8849 bool hasRuntimeEvaluationCaptureSize = false; 8850 for (llvm::Value *S : Sizes) 8851 if (!isa<llvm::Constant>(S)) { 8852 hasRuntimeEvaluationCaptureSize = true; 8853 break; 8854 } 8855 8856 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8857 QualType PointerArrayType = Ctx.getConstantArrayType( 8858 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8859 /*IndexTypeQuals=*/0); 8860 8861 Info.BasePointersArray = 8862 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8863 Info.PointersArray = 8864 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8865 8866 // If we don't have any VLA types or other types that require runtime 8867 // evaluation, we can use a constant array for the map sizes, otherwise we 8868 // need to fill up the arrays as we do for the pointers. 8869 QualType Int64Ty = 8870 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8871 if (hasRuntimeEvaluationCaptureSize) { 8872 QualType SizeArrayType = Ctx.getConstantArrayType( 8873 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8874 /*IndexTypeQuals=*/0); 8875 Info.SizesArray = 8876 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8877 } else { 8878 // We expect all the sizes to be constant, so we collect them to create 8879 // a constant array. 8880 SmallVector<llvm::Constant *, 16> ConstSizes; 8881 for (llvm::Value *S : Sizes) 8882 ConstSizes.push_back(cast<llvm::Constant>(S)); 8883 8884 auto *SizesArrayInit = llvm::ConstantArray::get( 8885 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8886 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8887 auto *SizesArrayGbl = new llvm::GlobalVariable( 8888 CGM.getModule(), SizesArrayInit->getType(), 8889 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8890 SizesArrayInit, Name); 8891 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8892 Info.SizesArray = SizesArrayGbl; 8893 } 8894 8895 // The map types are always constant so we don't need to generate code to 8896 // fill arrays. Instead, we create an array constant. 8897 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8898 llvm::copy(MapTypes, Mapping.begin()); 8899 llvm::Constant *MapTypesArrayInit = 8900 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8901 std::string MaptypesName = 8902 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8903 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8904 CGM.getModule(), MapTypesArrayInit->getType(), 8905 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8906 MapTypesArrayInit, MaptypesName); 8907 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8908 Info.MapTypesArray = MapTypesArrayGbl; 8909 8910 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8911 llvm::Value *BPVal = *BasePointers[I]; 8912 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8913 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8914 Info.BasePointersArray, 0, I); 8915 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8916 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8917 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8918 CGF.Builder.CreateStore(BPVal, BPAddr); 8919 8920 if (Info.requiresDevicePointerInfo()) 8921 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8922 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8923 8924 llvm::Value *PVal = Pointers[I]; 8925 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8926 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8927 Info.PointersArray, 0, I); 8928 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8929 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8930 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8931 CGF.Builder.CreateStore(PVal, PAddr); 8932 8933 if (hasRuntimeEvaluationCaptureSize) { 8934 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8935 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8936 Info.SizesArray, 8937 /*Idx0=*/0, 8938 /*Idx1=*/I); 8939 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8940 CGF.Builder.CreateStore( 8941 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8942 SAddr); 8943 } 8944 } 8945 } 8946 } 8947 8948 /// Emit the arguments to be passed to the runtime library based on the 8949 /// arrays of pointers, sizes and map types. 8950 static void emitOffloadingArraysArgument( 8951 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8952 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8953 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8954 CodeGenModule &CGM = CGF.CGM; 8955 if (Info.NumberOfPtrs) { 8956 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8957 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8958 Info.BasePointersArray, 8959 /*Idx0=*/0, /*Idx1=*/0); 8960 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8961 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8962 Info.PointersArray, 8963 /*Idx0=*/0, 8964 /*Idx1=*/0); 8965 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8966 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8967 /*Idx0=*/0, /*Idx1=*/0); 8968 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8969 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8970 Info.MapTypesArray, 8971 /*Idx0=*/0, 8972 /*Idx1=*/0); 8973 } else { 8974 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8975 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8976 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8977 MapTypesArrayArg = 8978 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8979 } 8980 } 8981 8982 /// Check for inner distribute directive. 8983 static const OMPExecutableDirective * 8984 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8985 const auto *CS = D.getInnermostCapturedStmt(); 8986 const auto *Body = 8987 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8988 const Stmt *ChildStmt = 8989 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8990 8991 if (const auto *NestedDir = 8992 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8993 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8994 switch (D.getDirectiveKind()) { 8995 case OMPD_target: 8996 if (isOpenMPDistributeDirective(DKind)) 8997 return NestedDir; 8998 if (DKind == OMPD_teams) { 8999 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 9000 /*IgnoreCaptured=*/true); 9001 if (!Body) 9002 return nullptr; 9003 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 9004 if (const auto *NND = 9005 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 9006 DKind = NND->getDirectiveKind(); 9007 if (isOpenMPDistributeDirective(DKind)) 9008 return NND; 9009 } 9010 } 9011 return nullptr; 9012 case OMPD_target_teams: 9013 if (isOpenMPDistributeDirective(DKind)) 9014 return NestedDir; 9015 return nullptr; 9016 case OMPD_target_parallel: 9017 case OMPD_target_simd: 9018 case OMPD_target_parallel_for: 9019 case OMPD_target_parallel_for_simd: 9020 return nullptr; 9021 case OMPD_target_teams_distribute: 9022 case OMPD_target_teams_distribute_simd: 9023 case OMPD_target_teams_distribute_parallel_for: 9024 case OMPD_target_teams_distribute_parallel_for_simd: 9025 case OMPD_parallel: 9026 case OMPD_for: 9027 case OMPD_parallel_for: 9028 case OMPD_parallel_master: 9029 case OMPD_parallel_sections: 9030 case OMPD_for_simd: 9031 case OMPD_parallel_for_simd: 9032 case OMPD_cancel: 9033 case OMPD_cancellation_point: 9034 case OMPD_ordered: 9035 case OMPD_threadprivate: 9036 case OMPD_allocate: 9037 case OMPD_task: 9038 case OMPD_simd: 9039 case OMPD_sections: 9040 case OMPD_section: 9041 case OMPD_single: 9042 case OMPD_master: 9043 case OMPD_critical: 9044 case OMPD_taskyield: 9045 case OMPD_barrier: 9046 case OMPD_taskwait: 9047 case OMPD_taskgroup: 9048 case OMPD_atomic: 9049 case OMPD_flush: 9050 case OMPD_depobj: 9051 case OMPD_teams: 9052 case OMPD_target_data: 9053 case OMPD_target_exit_data: 9054 case OMPD_target_enter_data: 9055 case OMPD_distribute: 9056 case OMPD_distribute_simd: 9057 case OMPD_distribute_parallel_for: 9058 case OMPD_distribute_parallel_for_simd: 9059 case OMPD_teams_distribute: 9060 case OMPD_teams_distribute_simd: 9061 case OMPD_teams_distribute_parallel_for: 9062 case OMPD_teams_distribute_parallel_for_simd: 9063 case OMPD_target_update: 9064 case OMPD_declare_simd: 9065 case OMPD_declare_variant: 9066 case OMPD_declare_target: 9067 case OMPD_end_declare_target: 9068 case OMPD_declare_reduction: 9069 case OMPD_declare_mapper: 9070 case OMPD_taskloop: 9071 case OMPD_taskloop_simd: 9072 case OMPD_master_taskloop: 9073 case OMPD_master_taskloop_simd: 9074 case OMPD_parallel_master_taskloop: 9075 case OMPD_parallel_master_taskloop_simd: 9076 case OMPD_requires: 9077 case OMPD_unknown: 9078 llvm_unreachable("Unexpected directive."); 9079 } 9080 } 9081 9082 return nullptr; 9083 } 9084 9085 /// Emit the user-defined mapper function. The code generation follows the 9086 /// pattern in the example below. 9087 /// \code 9088 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 9089 /// void *base, void *begin, 9090 /// int64_t size, int64_t type) { 9091 /// // Allocate space for an array section first. 9092 /// if (size > 1 && !maptype.IsDelete) 9093 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9094 /// size*sizeof(Ty), clearToFrom(type)); 9095 /// // Map members. 9096 /// for (unsigned i = 0; i < size; i++) { 9097 /// // For each component specified by this mapper: 9098 /// for (auto c : all_components) { 9099 /// if (c.hasMapper()) 9100 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 9101 /// c.arg_type); 9102 /// else 9103 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 9104 /// c.arg_begin, c.arg_size, c.arg_type); 9105 /// } 9106 /// } 9107 /// // Delete the array section. 9108 /// if (size > 1 && maptype.IsDelete) 9109 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 9110 /// size*sizeof(Ty), clearToFrom(type)); 9111 /// } 9112 /// \endcode 9113 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 9114 CodeGenFunction *CGF) { 9115 if (UDMMap.count(D) > 0) 9116 return; 9117 ASTContext &C = CGM.getContext(); 9118 QualType Ty = D->getType(); 9119 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 9120 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 9121 auto *MapperVarDecl = 9122 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 9123 SourceLocation Loc = D->getLocation(); 9124 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 9125 9126 // Prepare mapper function arguments and attributes. 9127 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9128 C.VoidPtrTy, ImplicitParamDecl::Other); 9129 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 9130 ImplicitParamDecl::Other); 9131 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 9132 C.VoidPtrTy, ImplicitParamDecl::Other); 9133 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9134 ImplicitParamDecl::Other); 9135 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 9136 ImplicitParamDecl::Other); 9137 FunctionArgList Args; 9138 Args.push_back(&HandleArg); 9139 Args.push_back(&BaseArg); 9140 Args.push_back(&BeginArg); 9141 Args.push_back(&SizeArg); 9142 Args.push_back(&TypeArg); 9143 const CGFunctionInfo &FnInfo = 9144 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 9145 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 9146 SmallString<64> TyStr; 9147 llvm::raw_svector_ostream Out(TyStr); 9148 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 9149 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 9150 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 9151 Name, &CGM.getModule()); 9152 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 9153 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 9154 // Start the mapper function code generation. 9155 CodeGenFunction MapperCGF(CGM); 9156 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 9157 // Compute the starting and end addreses of array elements. 9158 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 9159 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 9160 C.getPointerType(Int64Ty), Loc); 9161 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 9162 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 9163 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 9164 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 9165 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 9166 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 9167 C.getPointerType(Int64Ty), Loc); 9168 // Prepare common arguments for array initiation and deletion. 9169 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 9170 MapperCGF.GetAddrOfLocalVar(&HandleArg), 9171 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9172 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 9173 MapperCGF.GetAddrOfLocalVar(&BaseArg), 9174 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9175 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 9176 MapperCGF.GetAddrOfLocalVar(&BeginArg), 9177 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 9178 9179 // Emit array initiation if this is an array section and \p MapType indicates 9180 // that memory allocation is required. 9181 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 9182 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9183 ElementSize, HeadBB, /*IsInit=*/true); 9184 9185 // Emit a for loop to iterate through SizeArg of elements and map all of them. 9186 9187 // Emit the loop header block. 9188 MapperCGF.EmitBlock(HeadBB); 9189 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 9190 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 9191 // Evaluate whether the initial condition is satisfied. 9192 llvm::Value *IsEmpty = 9193 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 9194 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 9195 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 9196 9197 // Emit the loop body block. 9198 MapperCGF.EmitBlock(BodyBB); 9199 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 9200 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 9201 PtrPHI->addIncoming(PtrBegin, EntryBB); 9202 Address PtrCurrent = 9203 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 9204 .getAlignment() 9205 .alignmentOfArrayElement(ElementSize)); 9206 // Privatize the declared variable of mapper to be the current array element. 9207 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 9208 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 9209 return MapperCGF 9210 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 9211 .getAddress(MapperCGF); 9212 }); 9213 (void)Scope.Privatize(); 9214 9215 // Get map clause information. Fill up the arrays with all mapped variables. 9216 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9217 MappableExprsHandler::MapValuesArrayTy Pointers; 9218 MappableExprsHandler::MapValuesArrayTy Sizes; 9219 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9220 MappableExprsHandler MEHandler(*D, MapperCGF); 9221 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 9222 9223 // Call the runtime API __tgt_mapper_num_components to get the number of 9224 // pre-existing components. 9225 llvm::Value *OffloadingArgs[] = {Handle}; 9226 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 9227 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 9228 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 9229 PreviousSize, 9230 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 9231 9232 // Fill up the runtime mapper handle for all components. 9233 for (unsigned I = 0; I < BasePointers.size(); ++I) { 9234 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 9235 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9236 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9237 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9238 llvm::Value *CurSizeArg = Sizes[I]; 9239 9240 // Extract the MEMBER_OF field from the map type. 9241 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 9242 MapperCGF.EmitBlock(MemberBB); 9243 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 9244 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 9245 OriMapType, 9246 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 9247 llvm::BasicBlock *MemberCombineBB = 9248 MapperCGF.createBasicBlock("omp.member.combine"); 9249 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 9250 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 9251 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 9252 // Add the number of pre-existing components to the MEMBER_OF field if it 9253 // is valid. 9254 MapperCGF.EmitBlock(MemberCombineBB); 9255 llvm::Value *CombinedMember = 9256 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9257 // Do nothing if it is not a member of previous components. 9258 MapperCGF.EmitBlock(TypeBB); 9259 llvm::PHINode *MemberMapType = 9260 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 9261 MemberMapType->addIncoming(OriMapType, MemberBB); 9262 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 9263 9264 // Combine the map type inherited from user-defined mapper with that 9265 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9266 // bits of the \a MapType, which is the input argument of the mapper 9267 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9268 // bits of MemberMapType. 9269 // [OpenMP 5.0], 1.2.6. map-type decay. 9270 // | alloc | to | from | tofrom | release | delete 9271 // ---------------------------------------------------------- 9272 // alloc | alloc | alloc | alloc | alloc | release | delete 9273 // to | alloc | to | alloc | to | release | delete 9274 // from | alloc | alloc | from | from | release | delete 9275 // tofrom | alloc | to | from | tofrom | release | delete 9276 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9277 MapType, 9278 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9279 MappableExprsHandler::OMP_MAP_FROM)); 9280 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9281 llvm::BasicBlock *AllocElseBB = 9282 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9283 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9284 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9285 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9286 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9287 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9288 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9289 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9290 MapperCGF.EmitBlock(AllocBB); 9291 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9292 MemberMapType, 9293 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9294 MappableExprsHandler::OMP_MAP_FROM))); 9295 MapperCGF.Builder.CreateBr(EndBB); 9296 MapperCGF.EmitBlock(AllocElseBB); 9297 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9298 LeftToFrom, 9299 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9300 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9301 // In case of to, clear OMP_MAP_FROM. 9302 MapperCGF.EmitBlock(ToBB); 9303 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9304 MemberMapType, 9305 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9306 MapperCGF.Builder.CreateBr(EndBB); 9307 MapperCGF.EmitBlock(ToElseBB); 9308 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9309 LeftToFrom, 9310 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9311 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9312 // In case of from, clear OMP_MAP_TO. 9313 MapperCGF.EmitBlock(FromBB); 9314 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9315 MemberMapType, 9316 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9317 // In case of tofrom, do nothing. 9318 MapperCGF.EmitBlock(EndBB); 9319 llvm::PHINode *CurMapType = 9320 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9321 CurMapType->addIncoming(AllocMapType, AllocBB); 9322 CurMapType->addIncoming(ToMapType, ToBB); 9323 CurMapType->addIncoming(FromMapType, FromBB); 9324 CurMapType->addIncoming(MemberMapType, ToElseBB); 9325 9326 // TODO: call the corresponding mapper function if a user-defined mapper is 9327 // associated with this map clause. 9328 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9329 // data structure. 9330 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9331 CurSizeArg, CurMapType}; 9332 MapperCGF.EmitRuntimeCall( 9333 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9334 OffloadingArgs); 9335 } 9336 9337 // Update the pointer to point to the next element that needs to be mapped, 9338 // and check whether we have mapped all elements. 9339 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9340 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9341 PtrPHI->addIncoming(PtrNext, BodyBB); 9342 llvm::Value *IsDone = 9343 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9344 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9345 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9346 9347 MapperCGF.EmitBlock(ExitBB); 9348 // Emit array deletion if this is an array section and \p MapType indicates 9349 // that deletion is required. 9350 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9351 ElementSize, DoneBB, /*IsInit=*/false); 9352 9353 // Emit the function exit block. 9354 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9355 MapperCGF.FinishFunction(); 9356 UDMMap.try_emplace(D, Fn); 9357 if (CGF) { 9358 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9359 Decls.second.push_back(D); 9360 } 9361 } 9362 9363 /// Emit the array initialization or deletion portion for user-defined mapper 9364 /// code generation. First, it evaluates whether an array section is mapped and 9365 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9366 /// true, and \a MapType indicates to not delete this array, array 9367 /// initialization code is generated. If \a IsInit is false, and \a MapType 9368 /// indicates to not this array, array deletion code is generated. 9369 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9370 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9371 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9372 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9373 StringRef Prefix = IsInit ? ".init" : ".del"; 9374 9375 // Evaluate if this is an array section. 9376 llvm::BasicBlock *IsDeleteBB = 9377 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"})); 9378 llvm::BasicBlock *BodyBB = 9379 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 9380 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9381 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9382 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9383 9384 // Evaluate if we are going to delete this section. 9385 MapperCGF.EmitBlock(IsDeleteBB); 9386 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9387 MapType, 9388 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9389 llvm::Value *DeleteCond; 9390 if (IsInit) { 9391 DeleteCond = MapperCGF.Builder.CreateIsNull( 9392 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9393 } else { 9394 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9395 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9396 } 9397 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9398 9399 MapperCGF.EmitBlock(BodyBB); 9400 // Get the array size by multiplying element size and element number (i.e., \p 9401 // Size). 9402 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9403 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9404 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9405 // memory allocation/deletion purpose only. 9406 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9407 MapType, 9408 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9409 MappableExprsHandler::OMP_MAP_FROM))); 9410 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9411 // data structure. 9412 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9413 MapperCGF.EmitRuntimeCall( 9414 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9415 } 9416 9417 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9418 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9419 llvm::Value *DeviceID, 9420 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9421 const OMPLoopDirective &D)> 9422 SizeEmitter) { 9423 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9424 const OMPExecutableDirective *TD = &D; 9425 // Get nested teams distribute kind directive, if any. 9426 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9427 TD = getNestedDistributeDirective(CGM.getContext(), D); 9428 if (!TD) 9429 return; 9430 const auto *LD = cast<OMPLoopDirective>(TD); 9431 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9432 PrePostActionTy &) { 9433 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9434 llvm::Value *Args[] = {DeviceID, NumIterations}; 9435 CGF.EmitRuntimeCall( 9436 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9437 } 9438 }; 9439 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9440 } 9441 9442 void CGOpenMPRuntime::emitTargetCall( 9443 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9444 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9445 const Expr *Device, 9446 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9447 const OMPLoopDirective &D)> 9448 SizeEmitter) { 9449 if (!CGF.HaveInsertPoint()) 9450 return; 9451 9452 assert(OutlinedFn && "Invalid outlined function!"); 9453 9454 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9455 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9456 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9457 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9458 PrePostActionTy &) { 9459 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9460 }; 9461 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9462 9463 CodeGenFunction::OMPTargetDataInfo InputInfo; 9464 llvm::Value *MapTypesArray = nullptr; 9465 // Fill up the pointer arrays and transfer execution to the device. 9466 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9467 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9468 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9469 // On top of the arrays that were filled up, the target offloading call 9470 // takes as arguments the device id as well as the host pointer. The host 9471 // pointer is used by the runtime library to identify the current target 9472 // region, so it only has to be unique and not necessarily point to 9473 // anything. It could be the pointer to the outlined function that 9474 // implements the target region, but we aren't using that so that the 9475 // compiler doesn't need to keep that, and could therefore inline the host 9476 // function if proven worthwhile during optimization. 9477 9478 // From this point on, we need to have an ID of the target region defined. 9479 assert(OutlinedFnID && "Invalid outlined function ID!"); 9480 9481 // Emit device ID if any. 9482 llvm::Value *DeviceID; 9483 if (Device) { 9484 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9485 CGF.Int64Ty, /*isSigned=*/true); 9486 } else { 9487 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9488 } 9489 9490 // Emit the number of elements in the offloading arrays. 9491 llvm::Value *PointerNum = 9492 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9493 9494 // Return value of the runtime offloading call. 9495 llvm::Value *Return; 9496 9497 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9498 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9499 9500 // Emit tripcount for the target loop-based directive. 9501 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9502 9503 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9504 // The target region is an outlined function launched by the runtime 9505 // via calls __tgt_target() or __tgt_target_teams(). 9506 // 9507 // __tgt_target() launches a target region with one team and one thread, 9508 // executing a serial region. This master thread may in turn launch 9509 // more threads within its team upon encountering a parallel region, 9510 // however, no additional teams can be launched on the device. 9511 // 9512 // __tgt_target_teams() launches a target region with one or more teams, 9513 // each with one or more threads. This call is required for target 9514 // constructs such as: 9515 // 'target teams' 9516 // 'target' / 'teams' 9517 // 'target teams distribute parallel for' 9518 // 'target parallel' 9519 // and so on. 9520 // 9521 // Note that on the host and CPU targets, the runtime implementation of 9522 // these calls simply call the outlined function without forking threads. 9523 // The outlined functions themselves have runtime calls to 9524 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9525 // the compiler in emitTeamsCall() and emitParallelCall(). 9526 // 9527 // In contrast, on the NVPTX target, the implementation of 9528 // __tgt_target_teams() launches a GPU kernel with the requested number 9529 // of teams and threads so no additional calls to the runtime are required. 9530 if (NumTeams) { 9531 // If we have NumTeams defined this means that we have an enclosed teams 9532 // region. Therefore we also expect to have NumThreads defined. These two 9533 // values should be defined in the presence of a teams directive, 9534 // regardless of having any clauses associated. If the user is using teams 9535 // but no clauses, these two values will be the default that should be 9536 // passed to the runtime library - a 32-bit integer with the value zero. 9537 assert(NumThreads && "Thread limit expression should be available along " 9538 "with number of teams."); 9539 llvm::Value *OffloadingArgs[] = {DeviceID, 9540 OutlinedFnID, 9541 PointerNum, 9542 InputInfo.BasePointersArray.getPointer(), 9543 InputInfo.PointersArray.getPointer(), 9544 InputInfo.SizesArray.getPointer(), 9545 MapTypesArray, 9546 NumTeams, 9547 NumThreads}; 9548 Return = CGF.EmitRuntimeCall( 9549 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9550 : OMPRTL__tgt_target_teams), 9551 OffloadingArgs); 9552 } else { 9553 llvm::Value *OffloadingArgs[] = {DeviceID, 9554 OutlinedFnID, 9555 PointerNum, 9556 InputInfo.BasePointersArray.getPointer(), 9557 InputInfo.PointersArray.getPointer(), 9558 InputInfo.SizesArray.getPointer(), 9559 MapTypesArray}; 9560 Return = CGF.EmitRuntimeCall( 9561 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9562 : OMPRTL__tgt_target), 9563 OffloadingArgs); 9564 } 9565 9566 // Check the error code and execute the host version if required. 9567 llvm::BasicBlock *OffloadFailedBlock = 9568 CGF.createBasicBlock("omp_offload.failed"); 9569 llvm::BasicBlock *OffloadContBlock = 9570 CGF.createBasicBlock("omp_offload.cont"); 9571 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9572 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9573 9574 CGF.EmitBlock(OffloadFailedBlock); 9575 if (RequiresOuterTask) { 9576 CapturedVars.clear(); 9577 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9578 } 9579 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9580 CGF.EmitBranch(OffloadContBlock); 9581 9582 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9583 }; 9584 9585 // Notify that the host version must be executed. 9586 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9587 RequiresOuterTask](CodeGenFunction &CGF, 9588 PrePostActionTy &) { 9589 if (RequiresOuterTask) { 9590 CapturedVars.clear(); 9591 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9592 } 9593 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9594 }; 9595 9596 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9597 &CapturedVars, RequiresOuterTask, 9598 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9599 // Fill up the arrays with all the captured variables. 9600 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9601 MappableExprsHandler::MapValuesArrayTy Pointers; 9602 MappableExprsHandler::MapValuesArrayTy Sizes; 9603 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9604 9605 // Get mappable expression information. 9606 MappableExprsHandler MEHandler(D, CGF); 9607 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9608 9609 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9610 auto CV = CapturedVars.begin(); 9611 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9612 CE = CS.capture_end(); 9613 CI != CE; ++CI, ++RI, ++CV) { 9614 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9615 MappableExprsHandler::MapValuesArrayTy CurPointers; 9616 MappableExprsHandler::MapValuesArrayTy CurSizes; 9617 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9618 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9619 9620 // VLA sizes are passed to the outlined region by copy and do not have map 9621 // information associated. 9622 if (CI->capturesVariableArrayType()) { 9623 CurBasePointers.push_back(*CV); 9624 CurPointers.push_back(*CV); 9625 CurSizes.push_back(CGF.Builder.CreateIntCast( 9626 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9627 // Copy to the device as an argument. No need to retrieve it. 9628 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9629 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9630 MappableExprsHandler::OMP_MAP_IMPLICIT); 9631 } else { 9632 // If we have any information in the map clause, we use it, otherwise we 9633 // just do a default mapping. 9634 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9635 CurSizes, CurMapTypes, PartialStruct); 9636 if (CurBasePointers.empty()) 9637 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9638 CurPointers, CurSizes, CurMapTypes); 9639 // Generate correct mapping for variables captured by reference in 9640 // lambdas. 9641 if (CI->capturesVariable()) 9642 MEHandler.generateInfoForLambdaCaptures( 9643 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9644 CurMapTypes, LambdaPointers); 9645 } 9646 // We expect to have at least an element of information for this capture. 9647 assert(!CurBasePointers.empty() && 9648 "Non-existing map pointer for capture!"); 9649 assert(CurBasePointers.size() == CurPointers.size() && 9650 CurBasePointers.size() == CurSizes.size() && 9651 CurBasePointers.size() == CurMapTypes.size() && 9652 "Inconsistent map information sizes!"); 9653 9654 // If there is an entry in PartialStruct it means we have a struct with 9655 // individual members mapped. Emit an extra combined entry. 9656 if (PartialStruct.Base.isValid()) 9657 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9658 CurMapTypes, PartialStruct); 9659 9660 // We need to append the results of this capture to what we already have. 9661 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9662 Pointers.append(CurPointers.begin(), CurPointers.end()); 9663 Sizes.append(CurSizes.begin(), CurSizes.end()); 9664 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9665 } 9666 // Adjust MEMBER_OF flags for the lambdas captures. 9667 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9668 Pointers, MapTypes); 9669 // Map other list items in the map clause which are not captured variables 9670 // but "declare target link" global variables. 9671 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9672 MapTypes); 9673 9674 TargetDataInfo Info; 9675 // Fill up the arrays and create the arguments. 9676 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9677 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9678 Info.PointersArray, Info.SizesArray, 9679 Info.MapTypesArray, Info); 9680 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9681 InputInfo.BasePointersArray = 9682 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9683 InputInfo.PointersArray = 9684 Address(Info.PointersArray, CGM.getPointerAlign()); 9685 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9686 MapTypesArray = Info.MapTypesArray; 9687 if (RequiresOuterTask) 9688 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9689 else 9690 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9691 }; 9692 9693 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9694 CodeGenFunction &CGF, PrePostActionTy &) { 9695 if (RequiresOuterTask) { 9696 CodeGenFunction::OMPTargetDataInfo InputInfo; 9697 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9698 } else { 9699 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9700 } 9701 }; 9702 9703 // If we have a target function ID it means that we need to support 9704 // offloading, otherwise, just execute on the host. We need to execute on host 9705 // regardless of the conditional in the if clause if, e.g., the user do not 9706 // specify target triples. 9707 if (OutlinedFnID) { 9708 if (IfCond) { 9709 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9710 } else { 9711 RegionCodeGenTy ThenRCG(TargetThenGen); 9712 ThenRCG(CGF); 9713 } 9714 } else { 9715 RegionCodeGenTy ElseRCG(TargetElseGen); 9716 ElseRCG(CGF); 9717 } 9718 } 9719 9720 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9721 StringRef ParentName) { 9722 if (!S) 9723 return; 9724 9725 // Codegen OMP target directives that offload compute to the device. 9726 bool RequiresDeviceCodegen = 9727 isa<OMPExecutableDirective>(S) && 9728 isOpenMPTargetExecutionDirective( 9729 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9730 9731 if (RequiresDeviceCodegen) { 9732 const auto &E = *cast<OMPExecutableDirective>(S); 9733 unsigned DeviceID; 9734 unsigned FileID; 9735 unsigned Line; 9736 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9737 FileID, Line); 9738 9739 // Is this a target region that should not be emitted as an entry point? If 9740 // so just signal we are done with this target region. 9741 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9742 ParentName, Line)) 9743 return; 9744 9745 switch (E.getDirectiveKind()) { 9746 case OMPD_target: 9747 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9748 cast<OMPTargetDirective>(E)); 9749 break; 9750 case OMPD_target_parallel: 9751 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9752 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9753 break; 9754 case OMPD_target_teams: 9755 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9756 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9757 break; 9758 case OMPD_target_teams_distribute: 9759 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9760 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9761 break; 9762 case OMPD_target_teams_distribute_simd: 9763 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9764 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9765 break; 9766 case OMPD_target_parallel_for: 9767 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9768 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9769 break; 9770 case OMPD_target_parallel_for_simd: 9771 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9772 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9773 break; 9774 case OMPD_target_simd: 9775 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9776 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9777 break; 9778 case OMPD_target_teams_distribute_parallel_for: 9779 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9780 CGM, ParentName, 9781 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9782 break; 9783 case OMPD_target_teams_distribute_parallel_for_simd: 9784 CodeGenFunction:: 9785 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9786 CGM, ParentName, 9787 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9788 break; 9789 case OMPD_parallel: 9790 case OMPD_for: 9791 case OMPD_parallel_for: 9792 case OMPD_parallel_master: 9793 case OMPD_parallel_sections: 9794 case OMPD_for_simd: 9795 case OMPD_parallel_for_simd: 9796 case OMPD_cancel: 9797 case OMPD_cancellation_point: 9798 case OMPD_ordered: 9799 case OMPD_threadprivate: 9800 case OMPD_allocate: 9801 case OMPD_task: 9802 case OMPD_simd: 9803 case OMPD_sections: 9804 case OMPD_section: 9805 case OMPD_single: 9806 case OMPD_master: 9807 case OMPD_critical: 9808 case OMPD_taskyield: 9809 case OMPD_barrier: 9810 case OMPD_taskwait: 9811 case OMPD_taskgroup: 9812 case OMPD_atomic: 9813 case OMPD_flush: 9814 case OMPD_depobj: 9815 case OMPD_teams: 9816 case OMPD_target_data: 9817 case OMPD_target_exit_data: 9818 case OMPD_target_enter_data: 9819 case OMPD_distribute: 9820 case OMPD_distribute_simd: 9821 case OMPD_distribute_parallel_for: 9822 case OMPD_distribute_parallel_for_simd: 9823 case OMPD_teams_distribute: 9824 case OMPD_teams_distribute_simd: 9825 case OMPD_teams_distribute_parallel_for: 9826 case OMPD_teams_distribute_parallel_for_simd: 9827 case OMPD_target_update: 9828 case OMPD_declare_simd: 9829 case OMPD_declare_variant: 9830 case OMPD_declare_target: 9831 case OMPD_end_declare_target: 9832 case OMPD_declare_reduction: 9833 case OMPD_declare_mapper: 9834 case OMPD_taskloop: 9835 case OMPD_taskloop_simd: 9836 case OMPD_master_taskloop: 9837 case OMPD_master_taskloop_simd: 9838 case OMPD_parallel_master_taskloop: 9839 case OMPD_parallel_master_taskloop_simd: 9840 case OMPD_requires: 9841 case OMPD_unknown: 9842 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9843 } 9844 return; 9845 } 9846 9847 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9848 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9849 return; 9850 9851 scanForTargetRegionsFunctions( 9852 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9853 return; 9854 } 9855 9856 // If this is a lambda function, look into its body. 9857 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9858 S = L->getBody(); 9859 9860 // Keep looking for target regions recursively. 9861 for (const Stmt *II : S->children()) 9862 scanForTargetRegionsFunctions(II, ParentName); 9863 } 9864 9865 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9866 // If emitting code for the host, we do not process FD here. Instead we do 9867 // the normal code generation. 9868 if (!CGM.getLangOpts().OpenMPIsDevice) { 9869 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9870 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9871 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9872 // Do not emit device_type(nohost) functions for the host. 9873 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9874 return true; 9875 } 9876 return false; 9877 } 9878 9879 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9880 // Try to detect target regions in the function. 9881 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9882 StringRef Name = CGM.getMangledName(GD); 9883 scanForTargetRegionsFunctions(FD->getBody(), Name); 9884 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9885 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9886 // Do not emit device_type(nohost) functions for the host. 9887 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9888 return true; 9889 } 9890 9891 // Do not to emit function if it is not marked as declare target. 9892 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9893 AlreadyEmittedTargetDecls.count(VD) == 0; 9894 } 9895 9896 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9897 if (!CGM.getLangOpts().OpenMPIsDevice) 9898 return false; 9899 9900 // Check if there are Ctors/Dtors in this declaration and look for target 9901 // regions in it. We use the complete variant to produce the kernel name 9902 // mangling. 9903 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9904 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9905 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9906 StringRef ParentName = 9907 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9908 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9909 } 9910 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9911 StringRef ParentName = 9912 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9913 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9914 } 9915 } 9916 9917 // Do not to emit variable if it is not marked as declare target. 9918 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9919 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9920 cast<VarDecl>(GD.getDecl())); 9921 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9922 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9923 HasRequiresUnifiedSharedMemory)) { 9924 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9925 return true; 9926 } 9927 return false; 9928 } 9929 9930 llvm::Constant * 9931 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9932 const VarDecl *VD) { 9933 assert(VD->getType().isConstant(CGM.getContext()) && 9934 "Expected constant variable."); 9935 StringRef VarName; 9936 llvm::Constant *Addr; 9937 llvm::GlobalValue::LinkageTypes Linkage; 9938 QualType Ty = VD->getType(); 9939 SmallString<128> Buffer; 9940 { 9941 unsigned DeviceID; 9942 unsigned FileID; 9943 unsigned Line; 9944 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9945 FileID, Line); 9946 llvm::raw_svector_ostream OS(Buffer); 9947 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9948 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9949 VarName = OS.str(); 9950 } 9951 Linkage = llvm::GlobalValue::InternalLinkage; 9952 Addr = 9953 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9954 getDefaultFirstprivateAddressSpace()); 9955 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9956 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9957 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9958 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9959 VarName, Addr, VarSize, 9960 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9961 return Addr; 9962 } 9963 9964 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9965 llvm::Constant *Addr) { 9966 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9967 !CGM.getLangOpts().OpenMPIsDevice) 9968 return; 9969 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9970 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9971 if (!Res) { 9972 if (CGM.getLangOpts().OpenMPIsDevice) { 9973 // Register non-target variables being emitted in device code (debug info 9974 // may cause this). 9975 StringRef VarName = CGM.getMangledName(VD); 9976 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9977 } 9978 return; 9979 } 9980 // Register declare target variables. 9981 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9982 StringRef VarName; 9983 CharUnits VarSize; 9984 llvm::GlobalValue::LinkageTypes Linkage; 9985 9986 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9987 !HasRequiresUnifiedSharedMemory) { 9988 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9989 VarName = CGM.getMangledName(VD); 9990 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9991 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9992 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9993 } else { 9994 VarSize = CharUnits::Zero(); 9995 } 9996 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9997 // Temp solution to prevent optimizations of the internal variables. 9998 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9999 std::string RefName = getName({VarName, "ref"}); 10000 if (!CGM.GetGlobalValue(RefName)) { 10001 llvm::Constant *AddrRef = 10002 getOrCreateInternalVariable(Addr->getType(), RefName); 10003 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 10004 GVAddrRef->setConstant(/*Val=*/true); 10005 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 10006 GVAddrRef->setInitializer(Addr); 10007 CGM.addCompilerUsedGlobal(GVAddrRef); 10008 } 10009 } 10010 } else { 10011 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 10012 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10013 HasRequiresUnifiedSharedMemory)) && 10014 "Declare target attribute must link or to with unified memory."); 10015 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 10016 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 10017 else 10018 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 10019 10020 if (CGM.getLangOpts().OpenMPIsDevice) { 10021 VarName = Addr->getName(); 10022 Addr = nullptr; 10023 } else { 10024 VarName = getAddrOfDeclareTargetVar(VD).getName(); 10025 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 10026 } 10027 VarSize = CGM.getPointerSize(); 10028 Linkage = llvm::GlobalValue::WeakAnyLinkage; 10029 } 10030 10031 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 10032 VarName, Addr, VarSize, Flags, Linkage); 10033 } 10034 10035 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 10036 if (isa<FunctionDecl>(GD.getDecl()) || 10037 isa<OMPDeclareReductionDecl>(GD.getDecl())) 10038 return emitTargetFunctions(GD); 10039 10040 return emitTargetGlobalVariable(GD); 10041 } 10042 10043 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 10044 for (const VarDecl *VD : DeferredGlobalVariables) { 10045 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 10046 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 10047 if (!Res) 10048 continue; 10049 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 10050 !HasRequiresUnifiedSharedMemory) { 10051 CGM.EmitGlobal(VD); 10052 } else { 10053 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 10054 (*Res == OMPDeclareTargetDeclAttr::MT_To && 10055 HasRequiresUnifiedSharedMemory)) && 10056 "Expected link clause or to clause with unified memory."); 10057 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 10058 } 10059 } 10060 } 10061 10062 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 10063 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 10064 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 10065 " Expected target-based directive."); 10066 } 10067 10068 void CGOpenMPRuntime::processRequiresDirective(const OMPRequiresDecl *D) { 10069 for (const OMPClause *Clause : D->clauselists()) { 10070 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 10071 HasRequiresUnifiedSharedMemory = true; 10072 } else if (const auto *AC = 10073 dyn_cast<OMPAtomicDefaultMemOrderClause>(Clause)) { 10074 switch (AC->getAtomicDefaultMemOrderKind()) { 10075 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_acq_rel: 10076 RequiresAtomicOrdering = llvm::AtomicOrdering::AcquireRelease; 10077 break; 10078 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_seq_cst: 10079 RequiresAtomicOrdering = llvm::AtomicOrdering::SequentiallyConsistent; 10080 break; 10081 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_relaxed: 10082 RequiresAtomicOrdering = llvm::AtomicOrdering::Monotonic; 10083 break; 10084 case OMPC_ATOMIC_DEFAULT_MEM_ORDER_unknown: 10085 break; 10086 } 10087 } 10088 } 10089 } 10090 10091 llvm::AtomicOrdering CGOpenMPRuntime::getDefaultMemoryOrdering() const { 10092 return RequiresAtomicOrdering; 10093 } 10094 10095 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 10096 LangAS &AS) { 10097 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 10098 return false; 10099 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 10100 switch(A->getAllocatorType()) { 10101 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 10102 // Not supported, fallback to the default mem space. 10103 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 10104 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 10105 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 10106 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 10107 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 10108 case OMPAllocateDeclAttr::OMPConstMemAlloc: 10109 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 10110 AS = LangAS::Default; 10111 return true; 10112 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 10113 llvm_unreachable("Expected predefined allocator for the variables with the " 10114 "static storage."); 10115 } 10116 return false; 10117 } 10118 10119 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 10120 return HasRequiresUnifiedSharedMemory; 10121 } 10122 10123 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 10124 CodeGenModule &CGM) 10125 : CGM(CGM) { 10126 if (CGM.getLangOpts().OpenMPIsDevice) { 10127 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 10128 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 10129 } 10130 } 10131 10132 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 10133 if (CGM.getLangOpts().OpenMPIsDevice) 10134 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 10135 } 10136 10137 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 10138 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 10139 return true; 10140 10141 const auto *D = cast<FunctionDecl>(GD.getDecl()); 10142 // Do not to emit function if it is marked as declare target as it was already 10143 // emitted. 10144 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 10145 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 10146 if (auto *F = dyn_cast_or_null<llvm::Function>( 10147 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 10148 return !F->isDeclaration(); 10149 return false; 10150 } 10151 return true; 10152 } 10153 10154 return !AlreadyEmittedTargetDecls.insert(D).second; 10155 } 10156 10157 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 10158 // If we don't have entries or if we are emitting code for the device, we 10159 // don't need to do anything. 10160 if (CGM.getLangOpts().OMPTargetTriples.empty() || 10161 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 10162 (OffloadEntriesInfoManager.empty() && 10163 !HasEmittedDeclareTargetRegion && 10164 !HasEmittedTargetRegion)) 10165 return nullptr; 10166 10167 // Create and register the function that handles the requires directives. 10168 ASTContext &C = CGM.getContext(); 10169 10170 llvm::Function *RequiresRegFn; 10171 { 10172 CodeGenFunction CGF(CGM); 10173 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 10174 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 10175 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 10176 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 10177 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 10178 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 10179 // TODO: check for other requires clauses. 10180 // The requires directive takes effect only when a target region is 10181 // present in the compilation unit. Otherwise it is ignored and not 10182 // passed to the runtime. This avoids the runtime from throwing an error 10183 // for mismatching requires clauses across compilation units that don't 10184 // contain at least 1 target region. 10185 assert((HasEmittedTargetRegion || 10186 HasEmittedDeclareTargetRegion || 10187 !OffloadEntriesInfoManager.empty()) && 10188 "Target or declare target region expected."); 10189 if (HasRequiresUnifiedSharedMemory) 10190 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 10191 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 10192 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 10193 CGF.FinishFunction(); 10194 } 10195 return RequiresRegFn; 10196 } 10197 10198 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 10199 const OMPExecutableDirective &D, 10200 SourceLocation Loc, 10201 llvm::Function *OutlinedFn, 10202 ArrayRef<llvm::Value *> CapturedVars) { 10203 if (!CGF.HaveInsertPoint()) 10204 return; 10205 10206 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10207 CodeGenFunction::RunCleanupsScope Scope(CGF); 10208 10209 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 10210 llvm::Value *Args[] = { 10211 RTLoc, 10212 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 10213 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 10214 llvm::SmallVector<llvm::Value *, 16> RealArgs; 10215 RealArgs.append(std::begin(Args), std::end(Args)); 10216 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 10217 10218 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 10219 CGF.EmitRuntimeCall(RTLFn, RealArgs); 10220 } 10221 10222 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 10223 const Expr *NumTeams, 10224 const Expr *ThreadLimit, 10225 SourceLocation Loc) { 10226 if (!CGF.HaveInsertPoint()) 10227 return; 10228 10229 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 10230 10231 llvm::Value *NumTeamsVal = 10232 NumTeams 10233 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 10234 CGF.CGM.Int32Ty, /* isSigned = */ true) 10235 : CGF.Builder.getInt32(0); 10236 10237 llvm::Value *ThreadLimitVal = 10238 ThreadLimit 10239 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 10240 CGF.CGM.Int32Ty, /* isSigned = */ true) 10241 : CGF.Builder.getInt32(0); 10242 10243 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 10244 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 10245 ThreadLimitVal}; 10246 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 10247 PushNumTeamsArgs); 10248 } 10249 10250 void CGOpenMPRuntime::emitTargetDataCalls( 10251 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10252 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 10253 if (!CGF.HaveInsertPoint()) 10254 return; 10255 10256 // Action used to replace the default codegen action and turn privatization 10257 // off. 10258 PrePostActionTy NoPrivAction; 10259 10260 // Generate the code for the opening of the data environment. Capture all the 10261 // arguments of the runtime call by reference because they are used in the 10262 // closing of the region. 10263 auto &&BeginThenGen = [this, &D, Device, &Info, 10264 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 10265 // Fill up the arrays with all the mapped variables. 10266 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10267 MappableExprsHandler::MapValuesArrayTy Pointers; 10268 MappableExprsHandler::MapValuesArrayTy Sizes; 10269 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10270 10271 // Get map clause information. 10272 MappableExprsHandler MCHandler(D, CGF); 10273 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10274 10275 // Fill up the arrays and create the arguments. 10276 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10277 10278 llvm::Value *BasePointersArrayArg = nullptr; 10279 llvm::Value *PointersArrayArg = nullptr; 10280 llvm::Value *SizesArrayArg = nullptr; 10281 llvm::Value *MapTypesArrayArg = nullptr; 10282 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10283 SizesArrayArg, MapTypesArrayArg, Info); 10284 10285 // Emit device ID if any. 10286 llvm::Value *DeviceID = nullptr; 10287 if (Device) { 10288 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10289 CGF.Int64Ty, /*isSigned=*/true); 10290 } else { 10291 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10292 } 10293 10294 // Emit the number of elements in the offloading arrays. 10295 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10296 10297 llvm::Value *OffloadingArgs[] = { 10298 DeviceID, PointerNum, BasePointersArrayArg, 10299 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10300 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 10301 OffloadingArgs); 10302 10303 // If device pointer privatization is required, emit the body of the region 10304 // here. It will have to be duplicated: with and without privatization. 10305 if (!Info.CaptureDeviceAddrMap.empty()) 10306 CodeGen(CGF); 10307 }; 10308 10309 // Generate code for the closing of the data region. 10310 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10311 PrePostActionTy &) { 10312 assert(Info.isValid() && "Invalid data environment closing arguments."); 10313 10314 llvm::Value *BasePointersArrayArg = nullptr; 10315 llvm::Value *PointersArrayArg = nullptr; 10316 llvm::Value *SizesArrayArg = nullptr; 10317 llvm::Value *MapTypesArrayArg = nullptr; 10318 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10319 SizesArrayArg, MapTypesArrayArg, Info); 10320 10321 // Emit device ID if any. 10322 llvm::Value *DeviceID = nullptr; 10323 if (Device) { 10324 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10325 CGF.Int64Ty, /*isSigned=*/true); 10326 } else { 10327 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10328 } 10329 10330 // Emit the number of elements in the offloading arrays. 10331 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10332 10333 llvm::Value *OffloadingArgs[] = { 10334 DeviceID, PointerNum, BasePointersArrayArg, 10335 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10336 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10337 OffloadingArgs); 10338 }; 10339 10340 // If we need device pointer privatization, we need to emit the body of the 10341 // region with no privatization in the 'else' branch of the conditional. 10342 // Otherwise, we don't have to do anything. 10343 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10344 PrePostActionTy &) { 10345 if (!Info.CaptureDeviceAddrMap.empty()) { 10346 CodeGen.setAction(NoPrivAction); 10347 CodeGen(CGF); 10348 } 10349 }; 10350 10351 // We don't have to do anything to close the region if the if clause evaluates 10352 // to false. 10353 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10354 10355 if (IfCond) { 10356 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10357 } else { 10358 RegionCodeGenTy RCG(BeginThenGen); 10359 RCG(CGF); 10360 } 10361 10362 // If we don't require privatization of device pointers, we emit the body in 10363 // between the runtime calls. This avoids duplicating the body code. 10364 if (Info.CaptureDeviceAddrMap.empty()) { 10365 CodeGen.setAction(NoPrivAction); 10366 CodeGen(CGF); 10367 } 10368 10369 if (IfCond) { 10370 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10371 } else { 10372 RegionCodeGenTy RCG(EndThenGen); 10373 RCG(CGF); 10374 } 10375 } 10376 10377 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10378 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10379 const Expr *Device) { 10380 if (!CGF.HaveInsertPoint()) 10381 return; 10382 10383 assert((isa<OMPTargetEnterDataDirective>(D) || 10384 isa<OMPTargetExitDataDirective>(D) || 10385 isa<OMPTargetUpdateDirective>(D)) && 10386 "Expecting either target enter, exit data, or update directives."); 10387 10388 CodeGenFunction::OMPTargetDataInfo InputInfo; 10389 llvm::Value *MapTypesArray = nullptr; 10390 // Generate the code for the opening of the data environment. 10391 auto &&ThenGen = [this, &D, Device, &InputInfo, 10392 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10393 // Emit device ID if any. 10394 llvm::Value *DeviceID = nullptr; 10395 if (Device) { 10396 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10397 CGF.Int64Ty, /*isSigned=*/true); 10398 } else { 10399 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10400 } 10401 10402 // Emit the number of elements in the offloading arrays. 10403 llvm::Constant *PointerNum = 10404 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10405 10406 llvm::Value *OffloadingArgs[] = {DeviceID, 10407 PointerNum, 10408 InputInfo.BasePointersArray.getPointer(), 10409 InputInfo.PointersArray.getPointer(), 10410 InputInfo.SizesArray.getPointer(), 10411 MapTypesArray}; 10412 10413 // Select the right runtime function call for each expected standalone 10414 // directive. 10415 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10416 OpenMPRTLFunction RTLFn; 10417 switch (D.getDirectiveKind()) { 10418 case OMPD_target_enter_data: 10419 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10420 : OMPRTL__tgt_target_data_begin; 10421 break; 10422 case OMPD_target_exit_data: 10423 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10424 : OMPRTL__tgt_target_data_end; 10425 break; 10426 case OMPD_target_update: 10427 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10428 : OMPRTL__tgt_target_data_update; 10429 break; 10430 case OMPD_parallel: 10431 case OMPD_for: 10432 case OMPD_parallel_for: 10433 case OMPD_parallel_master: 10434 case OMPD_parallel_sections: 10435 case OMPD_for_simd: 10436 case OMPD_parallel_for_simd: 10437 case OMPD_cancel: 10438 case OMPD_cancellation_point: 10439 case OMPD_ordered: 10440 case OMPD_threadprivate: 10441 case OMPD_allocate: 10442 case OMPD_task: 10443 case OMPD_simd: 10444 case OMPD_sections: 10445 case OMPD_section: 10446 case OMPD_single: 10447 case OMPD_master: 10448 case OMPD_critical: 10449 case OMPD_taskyield: 10450 case OMPD_barrier: 10451 case OMPD_taskwait: 10452 case OMPD_taskgroup: 10453 case OMPD_atomic: 10454 case OMPD_flush: 10455 case OMPD_depobj: 10456 case OMPD_teams: 10457 case OMPD_target_data: 10458 case OMPD_distribute: 10459 case OMPD_distribute_simd: 10460 case OMPD_distribute_parallel_for: 10461 case OMPD_distribute_parallel_for_simd: 10462 case OMPD_teams_distribute: 10463 case OMPD_teams_distribute_simd: 10464 case OMPD_teams_distribute_parallel_for: 10465 case OMPD_teams_distribute_parallel_for_simd: 10466 case OMPD_declare_simd: 10467 case OMPD_declare_variant: 10468 case OMPD_declare_target: 10469 case OMPD_end_declare_target: 10470 case OMPD_declare_reduction: 10471 case OMPD_declare_mapper: 10472 case OMPD_taskloop: 10473 case OMPD_taskloop_simd: 10474 case OMPD_master_taskloop: 10475 case OMPD_master_taskloop_simd: 10476 case OMPD_parallel_master_taskloop: 10477 case OMPD_parallel_master_taskloop_simd: 10478 case OMPD_target: 10479 case OMPD_target_simd: 10480 case OMPD_target_teams_distribute: 10481 case OMPD_target_teams_distribute_simd: 10482 case OMPD_target_teams_distribute_parallel_for: 10483 case OMPD_target_teams_distribute_parallel_for_simd: 10484 case OMPD_target_teams: 10485 case OMPD_target_parallel: 10486 case OMPD_target_parallel_for: 10487 case OMPD_target_parallel_for_simd: 10488 case OMPD_requires: 10489 case OMPD_unknown: 10490 llvm_unreachable("Unexpected standalone target data directive."); 10491 break; 10492 } 10493 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10494 }; 10495 10496 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10497 CodeGenFunction &CGF, PrePostActionTy &) { 10498 // Fill up the arrays with all the mapped variables. 10499 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10500 MappableExprsHandler::MapValuesArrayTy Pointers; 10501 MappableExprsHandler::MapValuesArrayTy Sizes; 10502 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10503 10504 // Get map clause information. 10505 MappableExprsHandler MEHandler(D, CGF); 10506 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10507 10508 TargetDataInfo Info; 10509 // Fill up the arrays and create the arguments. 10510 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10511 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10512 Info.PointersArray, Info.SizesArray, 10513 Info.MapTypesArray, Info); 10514 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10515 InputInfo.BasePointersArray = 10516 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10517 InputInfo.PointersArray = 10518 Address(Info.PointersArray, CGM.getPointerAlign()); 10519 InputInfo.SizesArray = 10520 Address(Info.SizesArray, CGM.getPointerAlign()); 10521 MapTypesArray = Info.MapTypesArray; 10522 if (D.hasClausesOfKind<OMPDependClause>()) 10523 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10524 else 10525 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10526 }; 10527 10528 if (IfCond) { 10529 emitIfClause(CGF, IfCond, TargetThenGen, 10530 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10531 } else { 10532 RegionCodeGenTy ThenRCG(TargetThenGen); 10533 ThenRCG(CGF); 10534 } 10535 } 10536 10537 namespace { 10538 /// Kind of parameter in a function with 'declare simd' directive. 10539 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10540 /// Attribute set of the parameter. 10541 struct ParamAttrTy { 10542 ParamKindTy Kind = Vector; 10543 llvm::APSInt StrideOrArg; 10544 llvm::APSInt Alignment; 10545 }; 10546 } // namespace 10547 10548 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10549 ArrayRef<ParamAttrTy> ParamAttrs) { 10550 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10551 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10552 // of that clause. The VLEN value must be power of 2. 10553 // In other case the notion of the function`s "characteristic data type" (CDT) 10554 // is used to compute the vector length. 10555 // CDT is defined in the following order: 10556 // a) For non-void function, the CDT is the return type. 10557 // b) If the function has any non-uniform, non-linear parameters, then the 10558 // CDT is the type of the first such parameter. 10559 // c) If the CDT determined by a) or b) above is struct, union, or class 10560 // type which is pass-by-value (except for the type that maps to the 10561 // built-in complex data type), the characteristic data type is int. 10562 // d) If none of the above three cases is applicable, the CDT is int. 10563 // The VLEN is then determined based on the CDT and the size of vector 10564 // register of that ISA for which current vector version is generated. The 10565 // VLEN is computed using the formula below: 10566 // VLEN = sizeof(vector_register) / sizeof(CDT), 10567 // where vector register size specified in section 3.2.1 Registers and the 10568 // Stack Frame of original AMD64 ABI document. 10569 QualType RetType = FD->getReturnType(); 10570 if (RetType.isNull()) 10571 return 0; 10572 ASTContext &C = FD->getASTContext(); 10573 QualType CDT; 10574 if (!RetType.isNull() && !RetType->isVoidType()) { 10575 CDT = RetType; 10576 } else { 10577 unsigned Offset = 0; 10578 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10579 if (ParamAttrs[Offset].Kind == Vector) 10580 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10581 ++Offset; 10582 } 10583 if (CDT.isNull()) { 10584 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10585 if (ParamAttrs[I + Offset].Kind == Vector) { 10586 CDT = FD->getParamDecl(I)->getType(); 10587 break; 10588 } 10589 } 10590 } 10591 } 10592 if (CDT.isNull()) 10593 CDT = C.IntTy; 10594 CDT = CDT->getCanonicalTypeUnqualified(); 10595 if (CDT->isRecordType() || CDT->isUnionType()) 10596 CDT = C.IntTy; 10597 return C.getTypeSize(CDT); 10598 } 10599 10600 static void 10601 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10602 const llvm::APSInt &VLENVal, 10603 ArrayRef<ParamAttrTy> ParamAttrs, 10604 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10605 struct ISADataTy { 10606 char ISA; 10607 unsigned VecRegSize; 10608 }; 10609 ISADataTy ISAData[] = { 10610 { 10611 'b', 128 10612 }, // SSE 10613 { 10614 'c', 256 10615 }, // AVX 10616 { 10617 'd', 256 10618 }, // AVX2 10619 { 10620 'e', 512 10621 }, // AVX512 10622 }; 10623 llvm::SmallVector<char, 2> Masked; 10624 switch (State) { 10625 case OMPDeclareSimdDeclAttr::BS_Undefined: 10626 Masked.push_back('N'); 10627 Masked.push_back('M'); 10628 break; 10629 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10630 Masked.push_back('N'); 10631 break; 10632 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10633 Masked.push_back('M'); 10634 break; 10635 } 10636 for (char Mask : Masked) { 10637 for (const ISADataTy &Data : ISAData) { 10638 SmallString<256> Buffer; 10639 llvm::raw_svector_ostream Out(Buffer); 10640 Out << "_ZGV" << Data.ISA << Mask; 10641 if (!VLENVal) { 10642 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10643 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10644 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10645 } else { 10646 Out << VLENVal; 10647 } 10648 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10649 switch (ParamAttr.Kind){ 10650 case LinearWithVarStride: 10651 Out << 's' << ParamAttr.StrideOrArg; 10652 break; 10653 case Linear: 10654 Out << 'l'; 10655 if (!!ParamAttr.StrideOrArg) 10656 Out << ParamAttr.StrideOrArg; 10657 break; 10658 case Uniform: 10659 Out << 'u'; 10660 break; 10661 case Vector: 10662 Out << 'v'; 10663 break; 10664 } 10665 if (!!ParamAttr.Alignment) 10666 Out << 'a' << ParamAttr.Alignment; 10667 } 10668 Out << '_' << Fn->getName(); 10669 Fn->addFnAttr(Out.str()); 10670 } 10671 } 10672 } 10673 10674 // This are the Functions that are needed to mangle the name of the 10675 // vector functions generated by the compiler, according to the rules 10676 // defined in the "Vector Function ABI specifications for AArch64", 10677 // available at 10678 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10679 10680 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10681 /// 10682 /// TODO: Need to implement the behavior for reference marked with a 10683 /// var or no linear modifiers (1.b in the section). For this, we 10684 /// need to extend ParamKindTy to support the linear modifiers. 10685 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10686 QT = QT.getCanonicalType(); 10687 10688 if (QT->isVoidType()) 10689 return false; 10690 10691 if (Kind == ParamKindTy::Uniform) 10692 return false; 10693 10694 if (Kind == ParamKindTy::Linear) 10695 return false; 10696 10697 // TODO: Handle linear references with modifiers 10698 10699 if (Kind == ParamKindTy::LinearWithVarStride) 10700 return false; 10701 10702 return true; 10703 } 10704 10705 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10706 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10707 QT = QT.getCanonicalType(); 10708 unsigned Size = C.getTypeSize(QT); 10709 10710 // Only scalars and complex within 16 bytes wide set PVB to true. 10711 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10712 return false; 10713 10714 if (QT->isFloatingType()) 10715 return true; 10716 10717 if (QT->isIntegerType()) 10718 return true; 10719 10720 if (QT->isPointerType()) 10721 return true; 10722 10723 // TODO: Add support for complex types (section 3.1.2, item 2). 10724 10725 return false; 10726 } 10727 10728 /// Computes the lane size (LS) of a return type or of an input parameter, 10729 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10730 /// TODO: Add support for references, section 3.2.1, item 1. 10731 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10732 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10733 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10734 if (getAArch64PBV(PTy, C)) 10735 return C.getTypeSize(PTy); 10736 } 10737 if (getAArch64PBV(QT, C)) 10738 return C.getTypeSize(QT); 10739 10740 return C.getTypeSize(C.getUIntPtrType()); 10741 } 10742 10743 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10744 // signature of the scalar function, as defined in 3.2.2 of the 10745 // AAVFABI. 10746 static std::tuple<unsigned, unsigned, bool> 10747 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10748 QualType RetType = FD->getReturnType().getCanonicalType(); 10749 10750 ASTContext &C = FD->getASTContext(); 10751 10752 bool OutputBecomesInput = false; 10753 10754 llvm::SmallVector<unsigned, 8> Sizes; 10755 if (!RetType->isVoidType()) { 10756 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10757 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10758 OutputBecomesInput = true; 10759 } 10760 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10761 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10762 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10763 } 10764 10765 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10766 // The LS of a function parameter / return value can only be a power 10767 // of 2, starting from 8 bits, up to 128. 10768 assert(std::all_of(Sizes.begin(), Sizes.end(), 10769 [](unsigned Size) { 10770 return Size == 8 || Size == 16 || Size == 32 || 10771 Size == 64 || Size == 128; 10772 }) && 10773 "Invalid size"); 10774 10775 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10776 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10777 OutputBecomesInput); 10778 } 10779 10780 /// Mangle the parameter part of the vector function name according to 10781 /// their OpenMP classification. The mangling function is defined in 10782 /// section 3.5 of the AAVFABI. 10783 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10784 SmallString<256> Buffer; 10785 llvm::raw_svector_ostream Out(Buffer); 10786 for (const auto &ParamAttr : ParamAttrs) { 10787 switch (ParamAttr.Kind) { 10788 case LinearWithVarStride: 10789 Out << "ls" << ParamAttr.StrideOrArg; 10790 break; 10791 case Linear: 10792 Out << 'l'; 10793 // Don't print the step value if it is not present or if it is 10794 // equal to 1. 10795 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10796 Out << ParamAttr.StrideOrArg; 10797 break; 10798 case Uniform: 10799 Out << 'u'; 10800 break; 10801 case Vector: 10802 Out << 'v'; 10803 break; 10804 } 10805 10806 if (!!ParamAttr.Alignment) 10807 Out << 'a' << ParamAttr.Alignment; 10808 } 10809 10810 return std::string(Out.str()); 10811 } 10812 10813 // Function used to add the attribute. The parameter `VLEN` is 10814 // templated to allow the use of "x" when targeting scalable functions 10815 // for SVE. 10816 template <typename T> 10817 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10818 char ISA, StringRef ParSeq, 10819 StringRef MangledName, bool OutputBecomesInput, 10820 llvm::Function *Fn) { 10821 SmallString<256> Buffer; 10822 llvm::raw_svector_ostream Out(Buffer); 10823 Out << Prefix << ISA << LMask << VLEN; 10824 if (OutputBecomesInput) 10825 Out << "v"; 10826 Out << ParSeq << "_" << MangledName; 10827 Fn->addFnAttr(Out.str()); 10828 } 10829 10830 // Helper function to generate the Advanced SIMD names depending on 10831 // the value of the NDS when simdlen is not present. 10832 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10833 StringRef Prefix, char ISA, 10834 StringRef ParSeq, StringRef MangledName, 10835 bool OutputBecomesInput, 10836 llvm::Function *Fn) { 10837 switch (NDS) { 10838 case 8: 10839 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10840 OutputBecomesInput, Fn); 10841 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10842 OutputBecomesInput, Fn); 10843 break; 10844 case 16: 10845 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10846 OutputBecomesInput, Fn); 10847 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10848 OutputBecomesInput, Fn); 10849 break; 10850 case 32: 10851 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10852 OutputBecomesInput, Fn); 10853 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10854 OutputBecomesInput, Fn); 10855 break; 10856 case 64: 10857 case 128: 10858 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10859 OutputBecomesInput, Fn); 10860 break; 10861 default: 10862 llvm_unreachable("Scalar type is too wide."); 10863 } 10864 } 10865 10866 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10867 static void emitAArch64DeclareSimdFunction( 10868 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10869 ArrayRef<ParamAttrTy> ParamAttrs, 10870 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10871 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10872 10873 // Get basic data for building the vector signature. 10874 const auto Data = getNDSWDS(FD, ParamAttrs); 10875 const unsigned NDS = std::get<0>(Data); 10876 const unsigned WDS = std::get<1>(Data); 10877 const bool OutputBecomesInput = std::get<2>(Data); 10878 10879 // Check the values provided via `simdlen` by the user. 10880 // 1. A `simdlen(1)` doesn't produce vector signatures, 10881 if (UserVLEN == 1) { 10882 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10883 DiagnosticsEngine::Warning, 10884 "The clause simdlen(1) has no effect when targeting aarch64."); 10885 CGM.getDiags().Report(SLoc, DiagID); 10886 return; 10887 } 10888 10889 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10890 // Advanced SIMD output. 10891 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10892 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10893 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10894 "power of 2 when targeting Advanced SIMD."); 10895 CGM.getDiags().Report(SLoc, DiagID); 10896 return; 10897 } 10898 10899 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10900 // limits. 10901 if (ISA == 's' && UserVLEN != 0) { 10902 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10903 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10904 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10905 "lanes in the architectural constraints " 10906 "for SVE (min is 128-bit, max is " 10907 "2048-bit, by steps of 128-bit)"); 10908 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10909 return; 10910 } 10911 } 10912 10913 // Sort out parameter sequence. 10914 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10915 StringRef Prefix = "_ZGV"; 10916 // Generate simdlen from user input (if any). 10917 if (UserVLEN) { 10918 if (ISA == 's') { 10919 // SVE generates only a masked function. 10920 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10921 OutputBecomesInput, Fn); 10922 } else { 10923 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10924 // Advanced SIMD generates one or two functions, depending on 10925 // the `[not]inbranch` clause. 10926 switch (State) { 10927 case OMPDeclareSimdDeclAttr::BS_Undefined: 10928 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10929 OutputBecomesInput, Fn); 10930 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10931 OutputBecomesInput, Fn); 10932 break; 10933 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10934 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10935 OutputBecomesInput, Fn); 10936 break; 10937 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10938 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10939 OutputBecomesInput, Fn); 10940 break; 10941 } 10942 } 10943 } else { 10944 // If no user simdlen is provided, follow the AAVFABI rules for 10945 // generating the vector length. 10946 if (ISA == 's') { 10947 // SVE, section 3.4.1, item 1. 10948 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10949 OutputBecomesInput, Fn); 10950 } else { 10951 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10952 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10953 // two vector names depending on the use of the clause 10954 // `[not]inbranch`. 10955 switch (State) { 10956 case OMPDeclareSimdDeclAttr::BS_Undefined: 10957 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10958 OutputBecomesInput, Fn); 10959 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10960 OutputBecomesInput, Fn); 10961 break; 10962 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10963 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10964 OutputBecomesInput, Fn); 10965 break; 10966 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10967 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10968 OutputBecomesInput, Fn); 10969 break; 10970 } 10971 } 10972 } 10973 } 10974 10975 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10976 llvm::Function *Fn) { 10977 ASTContext &C = CGM.getContext(); 10978 FD = FD->getMostRecentDecl(); 10979 // Map params to their positions in function decl. 10980 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10981 if (isa<CXXMethodDecl>(FD)) 10982 ParamPositions.try_emplace(FD, 0); 10983 unsigned ParamPos = ParamPositions.size(); 10984 for (const ParmVarDecl *P : FD->parameters()) { 10985 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10986 ++ParamPos; 10987 } 10988 while (FD) { 10989 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10990 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10991 // Mark uniform parameters. 10992 for (const Expr *E : Attr->uniforms()) { 10993 E = E->IgnoreParenImpCasts(); 10994 unsigned Pos; 10995 if (isa<CXXThisExpr>(E)) { 10996 Pos = ParamPositions[FD]; 10997 } else { 10998 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10999 ->getCanonicalDecl(); 11000 Pos = ParamPositions[PVD]; 11001 } 11002 ParamAttrs[Pos].Kind = Uniform; 11003 } 11004 // Get alignment info. 11005 auto NI = Attr->alignments_begin(); 11006 for (const Expr *E : Attr->aligneds()) { 11007 E = E->IgnoreParenImpCasts(); 11008 unsigned Pos; 11009 QualType ParmTy; 11010 if (isa<CXXThisExpr>(E)) { 11011 Pos = ParamPositions[FD]; 11012 ParmTy = E->getType(); 11013 } else { 11014 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11015 ->getCanonicalDecl(); 11016 Pos = ParamPositions[PVD]; 11017 ParmTy = PVD->getType(); 11018 } 11019 ParamAttrs[Pos].Alignment = 11020 (*NI) 11021 ? (*NI)->EvaluateKnownConstInt(C) 11022 : llvm::APSInt::getUnsigned( 11023 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 11024 .getQuantity()); 11025 ++NI; 11026 } 11027 // Mark linear parameters. 11028 auto SI = Attr->steps_begin(); 11029 auto MI = Attr->modifiers_begin(); 11030 for (const Expr *E : Attr->linears()) { 11031 E = E->IgnoreParenImpCasts(); 11032 unsigned Pos; 11033 if (isa<CXXThisExpr>(E)) { 11034 Pos = ParamPositions[FD]; 11035 } else { 11036 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 11037 ->getCanonicalDecl(); 11038 Pos = ParamPositions[PVD]; 11039 } 11040 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 11041 ParamAttr.Kind = Linear; 11042 if (*SI) { 11043 Expr::EvalResult Result; 11044 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 11045 if (const auto *DRE = 11046 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 11047 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 11048 ParamAttr.Kind = LinearWithVarStride; 11049 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 11050 ParamPositions[StridePVD->getCanonicalDecl()]); 11051 } 11052 } 11053 } else { 11054 ParamAttr.StrideOrArg = Result.Val.getInt(); 11055 } 11056 } 11057 ++SI; 11058 ++MI; 11059 } 11060 llvm::APSInt VLENVal; 11061 SourceLocation ExprLoc; 11062 const Expr *VLENExpr = Attr->getSimdlen(); 11063 if (VLENExpr) { 11064 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 11065 ExprLoc = VLENExpr->getExprLoc(); 11066 } 11067 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 11068 if (CGM.getTriple().isX86()) { 11069 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 11070 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 11071 unsigned VLEN = VLENVal.getExtValue(); 11072 StringRef MangledName = Fn->getName(); 11073 if (CGM.getTarget().hasFeature("sve")) 11074 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11075 MangledName, 's', 128, Fn, ExprLoc); 11076 if (CGM.getTarget().hasFeature("neon")) 11077 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 11078 MangledName, 'n', 128, Fn, ExprLoc); 11079 } 11080 } 11081 FD = FD->getPreviousDecl(); 11082 } 11083 } 11084 11085 namespace { 11086 /// Cleanup action for doacross support. 11087 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 11088 public: 11089 static const int DoacrossFinArgs = 2; 11090 11091 private: 11092 llvm::FunctionCallee RTLFn; 11093 llvm::Value *Args[DoacrossFinArgs]; 11094 11095 public: 11096 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 11097 ArrayRef<llvm::Value *> CallArgs) 11098 : RTLFn(RTLFn) { 11099 assert(CallArgs.size() == DoacrossFinArgs); 11100 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11101 } 11102 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11103 if (!CGF.HaveInsertPoint()) 11104 return; 11105 CGF.EmitRuntimeCall(RTLFn, Args); 11106 } 11107 }; 11108 } // namespace 11109 11110 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11111 const OMPLoopDirective &D, 11112 ArrayRef<Expr *> NumIterations) { 11113 if (!CGF.HaveInsertPoint()) 11114 return; 11115 11116 ASTContext &C = CGM.getContext(); 11117 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 11118 RecordDecl *RD; 11119 if (KmpDimTy.isNull()) { 11120 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 11121 // kmp_int64 lo; // lower 11122 // kmp_int64 up; // upper 11123 // kmp_int64 st; // stride 11124 // }; 11125 RD = C.buildImplicitRecord("kmp_dim"); 11126 RD->startDefinition(); 11127 addFieldToRecordDecl(C, RD, Int64Ty); 11128 addFieldToRecordDecl(C, RD, Int64Ty); 11129 addFieldToRecordDecl(C, RD, Int64Ty); 11130 RD->completeDefinition(); 11131 KmpDimTy = C.getRecordType(RD); 11132 } else { 11133 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 11134 } 11135 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 11136 QualType ArrayTy = 11137 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 11138 11139 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 11140 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 11141 enum { LowerFD = 0, UpperFD, StrideFD }; 11142 // Fill dims with data. 11143 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 11144 LValue DimsLVal = CGF.MakeAddrLValue( 11145 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 11146 // dims.upper = num_iterations; 11147 LValue UpperLVal = CGF.EmitLValueForField( 11148 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 11149 llvm::Value *NumIterVal = 11150 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 11151 D.getNumIterations()->getType(), Int64Ty, 11152 D.getNumIterations()->getExprLoc()); 11153 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 11154 // dims.stride = 1; 11155 LValue StrideLVal = CGF.EmitLValueForField( 11156 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 11157 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 11158 StrideLVal); 11159 } 11160 11161 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 11162 // kmp_int32 num_dims, struct kmp_dim * dims); 11163 llvm::Value *Args[] = { 11164 emitUpdateLocation(CGF, D.getBeginLoc()), 11165 getThreadID(CGF, D.getBeginLoc()), 11166 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 11167 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11168 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 11169 CGM.VoidPtrTy)}; 11170 11171 llvm::FunctionCallee RTLFn = 11172 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 11173 CGF.EmitRuntimeCall(RTLFn, Args); 11174 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 11175 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 11176 llvm::FunctionCallee FiniRTLFn = 11177 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 11178 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11179 llvm::makeArrayRef(FiniArgs)); 11180 } 11181 11182 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11183 const OMPDependClause *C) { 11184 QualType Int64Ty = 11185 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 11186 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 11187 QualType ArrayTy = CGM.getContext().getConstantArrayType( 11188 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 11189 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 11190 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 11191 const Expr *CounterVal = C->getLoopData(I); 11192 assert(CounterVal); 11193 llvm::Value *CntVal = CGF.EmitScalarConversion( 11194 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 11195 CounterVal->getExprLoc()); 11196 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 11197 /*Volatile=*/false, Int64Ty); 11198 } 11199 llvm::Value *Args[] = { 11200 emitUpdateLocation(CGF, C->getBeginLoc()), 11201 getThreadID(CGF, C->getBeginLoc()), 11202 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 11203 llvm::FunctionCallee RTLFn; 11204 if (C->getDependencyKind() == OMPC_DEPEND_source) { 11205 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 11206 } else { 11207 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 11208 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 11209 } 11210 CGF.EmitRuntimeCall(RTLFn, Args); 11211 } 11212 11213 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 11214 llvm::FunctionCallee Callee, 11215 ArrayRef<llvm::Value *> Args) const { 11216 assert(Loc.isValid() && "Outlined function call location must be valid."); 11217 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 11218 11219 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 11220 if (Fn->doesNotThrow()) { 11221 CGF.EmitNounwindRuntimeCall(Fn, Args); 11222 return; 11223 } 11224 } 11225 CGF.EmitRuntimeCall(Callee, Args); 11226 } 11227 11228 void CGOpenMPRuntime::emitOutlinedFunctionCall( 11229 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 11230 ArrayRef<llvm::Value *> Args) const { 11231 emitCall(CGF, Loc, OutlinedFn, Args); 11232 } 11233 11234 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 11235 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 11236 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 11237 HasEmittedDeclareTargetRegion = true; 11238 } 11239 11240 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 11241 const VarDecl *NativeParam, 11242 const VarDecl *TargetParam) const { 11243 return CGF.GetAddrOfLocalVar(NativeParam); 11244 } 11245 11246 namespace { 11247 /// Cleanup action for allocate support. 11248 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 11249 public: 11250 static const int CleanupArgs = 3; 11251 11252 private: 11253 llvm::FunctionCallee RTLFn; 11254 llvm::Value *Args[CleanupArgs]; 11255 11256 public: 11257 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 11258 ArrayRef<llvm::Value *> CallArgs) 11259 : RTLFn(RTLFn) { 11260 assert(CallArgs.size() == CleanupArgs && 11261 "Size of arguments does not match."); 11262 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11263 } 11264 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11265 if (!CGF.HaveInsertPoint()) 11266 return; 11267 CGF.EmitRuntimeCall(RTLFn, Args); 11268 } 11269 }; 11270 } // namespace 11271 11272 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11273 const VarDecl *VD) { 11274 if (!VD) 11275 return Address::invalid(); 11276 const VarDecl *CVD = VD->getCanonicalDecl(); 11277 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 11278 return Address::invalid(); 11279 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 11280 // Use the default allocation. 11281 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 11282 !AA->getAllocator()) 11283 return Address::invalid(); 11284 llvm::Value *Size; 11285 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11286 if (CVD->getType()->isVariablyModifiedType()) { 11287 Size = CGF.getTypeSize(CVD->getType()); 11288 // Align the size: ((size + align - 1) / align) * align 11289 Size = CGF.Builder.CreateNUWAdd( 11290 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11291 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11292 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11293 } else { 11294 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11295 Size = CGM.getSize(Sz.alignTo(Align)); 11296 } 11297 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11298 assert(AA->getAllocator() && 11299 "Expected allocator expression for non-default allocator."); 11300 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11301 // According to the standard, the original allocator type is a enum (integer). 11302 // Convert to pointer type, if required. 11303 if (Allocator->getType()->isIntegerTy()) 11304 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11305 else if (Allocator->getType()->isPointerTy()) 11306 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11307 CGM.VoidPtrTy); 11308 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11309 11310 llvm::Value *Addr = 11311 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11312 getName({CVD->getName(), ".void.addr"})); 11313 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11314 Allocator}; 11315 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11316 11317 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11318 llvm::makeArrayRef(FiniArgs)); 11319 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11320 Addr, 11321 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11322 getName({CVD->getName(), ".addr"})); 11323 return Address(Addr, Align); 11324 } 11325 11326 /// Finds the variant function that matches current context with its context 11327 /// selector. 11328 static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, 11329 const FunctionDecl *FD) { 11330 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11331 return FD; 11332 11333 SmallVector<Expr *, 8> VariantExprs; 11334 SmallVector<VariantMatchInfo, 8> VMIs; 11335 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11336 const OMPTraitInfo &TI = A->getTraitInfos(); 11337 VMIs.push_back(VariantMatchInfo()); 11338 TI.getAsVariantMatchInfo(CGM.getContext(), VMIs.back()); 11339 VariantExprs.push_back(A->getVariantFuncRef()); 11340 } 11341 11342 OMPContext Ctx(CGM.getLangOpts().OpenMPIsDevice, CGM.getTriple()); 11343 // FIXME: Keep the context in the OMPIRBuilder so we can add constructs as we 11344 // build them. 11345 11346 int BestMatchIdx = getBestVariantMatchForContext(VMIs, Ctx); 11347 if (BestMatchIdx < 0) 11348 return FD; 11349 11350 return cast<FunctionDecl>( 11351 cast<DeclRefExpr>(VariantExprs[BestMatchIdx]->IgnoreParenImpCasts()) 11352 ->getDecl()); 11353 } 11354 11355 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11356 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11357 // If the original function is defined already, use its definition. 11358 StringRef MangledName = CGM.getMangledName(GD); 11359 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11360 if (Orig && !Orig->isDeclaration()) 11361 return false; 11362 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D); 11363 // Emit original function if it does not have declare variant attribute or the 11364 // context does not match. 11365 if (NewFD == D) 11366 return false; 11367 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11368 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) { 11369 DeferredVariantFunction.erase(D); 11370 return true; 11371 } 11372 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11373 return true; 11374 } 11375 11376 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 11377 CodeGenModule &CGM, const OMPLoopDirective &S) 11378 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 11379 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11380 if (!NeedToPush) 11381 return; 11382 NontemporalDeclsSet &DS = 11383 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 11384 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 11385 for (const Stmt *Ref : C->private_refs()) { 11386 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 11387 const ValueDecl *VD; 11388 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 11389 VD = DRE->getDecl(); 11390 } else { 11391 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 11392 assert((ME->isImplicitCXXThis() || 11393 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 11394 "Expected member of current class."); 11395 VD = ME->getMemberDecl(); 11396 } 11397 DS.insert(VD); 11398 } 11399 } 11400 } 11401 11402 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 11403 if (!NeedToPush) 11404 return; 11405 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 11406 } 11407 11408 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 11409 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11410 11411 return llvm::any_of( 11412 CGM.getOpenMPRuntime().NontemporalDeclsStack, 11413 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 11414 } 11415 11416 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 11417 const OMPExecutableDirective &S, 11418 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 11419 const { 11420 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 11421 // Vars in target/task regions must be excluded completely. 11422 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 11423 isOpenMPTaskingDirective(S.getDirectiveKind())) { 11424 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11425 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 11426 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 11427 for (const CapturedStmt::Capture &Cap : CS->captures()) { 11428 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 11429 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 11430 } 11431 } 11432 // Exclude vars in private clauses. 11433 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 11434 for (const Expr *Ref : C->varlists()) { 11435 if (!Ref->getType()->isScalarType()) 11436 continue; 11437 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11438 if (!DRE) 11439 continue; 11440 NeedToCheckForLPCs.insert(DRE->getDecl()); 11441 } 11442 } 11443 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 11444 for (const Expr *Ref : C->varlists()) { 11445 if (!Ref->getType()->isScalarType()) 11446 continue; 11447 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11448 if (!DRE) 11449 continue; 11450 NeedToCheckForLPCs.insert(DRE->getDecl()); 11451 } 11452 } 11453 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11454 for (const Expr *Ref : C->varlists()) { 11455 if (!Ref->getType()->isScalarType()) 11456 continue; 11457 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11458 if (!DRE) 11459 continue; 11460 NeedToCheckForLPCs.insert(DRE->getDecl()); 11461 } 11462 } 11463 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 11464 for (const Expr *Ref : C->varlists()) { 11465 if (!Ref->getType()->isScalarType()) 11466 continue; 11467 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11468 if (!DRE) 11469 continue; 11470 NeedToCheckForLPCs.insert(DRE->getDecl()); 11471 } 11472 } 11473 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 11474 for (const Expr *Ref : C->varlists()) { 11475 if (!Ref->getType()->isScalarType()) 11476 continue; 11477 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11478 if (!DRE) 11479 continue; 11480 NeedToCheckForLPCs.insert(DRE->getDecl()); 11481 } 11482 } 11483 for (const Decl *VD : NeedToCheckForLPCs) { 11484 for (const LastprivateConditionalData &Data : 11485 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 11486 if (Data.DeclToUniqueName.count(VD) > 0) { 11487 if (!Data.Disabled) 11488 NeedToAddForLPCsAsDisabled.insert(VD); 11489 break; 11490 } 11491 } 11492 } 11493 } 11494 11495 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11496 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 11497 : CGM(CGF.CGM), 11498 Action((CGM.getLangOpts().OpenMP >= 50 && 11499 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 11500 [](const OMPLastprivateClause *C) { 11501 return C->getKind() == 11502 OMPC_LASTPRIVATE_conditional; 11503 })) 11504 ? ActionToDo::PushAsLastprivateConditional 11505 : ActionToDo::DoNotPush) { 11506 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11507 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 11508 return; 11509 assert(Action == ActionToDo::PushAsLastprivateConditional && 11510 "Expected a push action."); 11511 LastprivateConditionalData &Data = 11512 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11513 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11514 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 11515 continue; 11516 11517 for (const Expr *Ref : C->varlists()) { 11518 Data.DeclToUniqueName.insert(std::make_pair( 11519 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 11520 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 11521 } 11522 } 11523 Data.IVLVal = IVLVal; 11524 Data.Fn = CGF.CurFn; 11525 } 11526 11527 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11528 CodeGenFunction &CGF, const OMPExecutableDirective &S) 11529 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 11530 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11531 if (CGM.getLangOpts().OpenMP < 50) 11532 return; 11533 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 11534 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 11535 if (!NeedToAddForLPCsAsDisabled.empty()) { 11536 Action = ActionToDo::DisableLastprivateConditional; 11537 LastprivateConditionalData &Data = 11538 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11539 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 11540 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 11541 Data.Fn = CGF.CurFn; 11542 Data.Disabled = true; 11543 } 11544 } 11545 11546 CGOpenMPRuntime::LastprivateConditionalRAII 11547 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 11548 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 11549 return LastprivateConditionalRAII(CGF, S); 11550 } 11551 11552 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 11553 if (CGM.getLangOpts().OpenMP < 50) 11554 return; 11555 if (Action == ActionToDo::DisableLastprivateConditional) { 11556 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11557 "Expected list of disabled private vars."); 11558 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11559 } 11560 if (Action == ActionToDo::PushAsLastprivateConditional) { 11561 assert( 11562 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11563 "Expected list of lastprivate conditional vars."); 11564 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11565 } 11566 } 11567 11568 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 11569 const VarDecl *VD) { 11570 ASTContext &C = CGM.getContext(); 11571 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 11572 if (I == LastprivateConditionalToTypes.end()) 11573 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 11574 QualType NewType; 11575 const FieldDecl *VDField; 11576 const FieldDecl *FiredField; 11577 LValue BaseLVal; 11578 auto VI = I->getSecond().find(VD); 11579 if (VI == I->getSecond().end()) { 11580 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 11581 RD->startDefinition(); 11582 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 11583 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 11584 RD->completeDefinition(); 11585 NewType = C.getRecordType(RD); 11586 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 11587 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 11588 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 11589 } else { 11590 NewType = std::get<0>(VI->getSecond()); 11591 VDField = std::get<1>(VI->getSecond()); 11592 FiredField = std::get<2>(VI->getSecond()); 11593 BaseLVal = std::get<3>(VI->getSecond()); 11594 } 11595 LValue FiredLVal = 11596 CGF.EmitLValueForField(BaseLVal, FiredField); 11597 CGF.EmitStoreOfScalar( 11598 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 11599 FiredLVal); 11600 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 11601 } 11602 11603 namespace { 11604 /// Checks if the lastprivate conditional variable is referenced in LHS. 11605 class LastprivateConditionalRefChecker final 11606 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 11607 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 11608 const Expr *FoundE = nullptr; 11609 const Decl *FoundD = nullptr; 11610 StringRef UniqueDeclName; 11611 LValue IVLVal; 11612 llvm::Function *FoundFn = nullptr; 11613 SourceLocation Loc; 11614 11615 public: 11616 bool VisitDeclRefExpr(const DeclRefExpr *E) { 11617 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11618 llvm::reverse(LPM)) { 11619 auto It = D.DeclToUniqueName.find(E->getDecl()); 11620 if (It == D.DeclToUniqueName.end()) 11621 continue; 11622 if (D.Disabled) 11623 return false; 11624 FoundE = E; 11625 FoundD = E->getDecl()->getCanonicalDecl(); 11626 UniqueDeclName = It->second; 11627 IVLVal = D.IVLVal; 11628 FoundFn = D.Fn; 11629 break; 11630 } 11631 return FoundE == E; 11632 } 11633 bool VisitMemberExpr(const MemberExpr *E) { 11634 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 11635 return false; 11636 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11637 llvm::reverse(LPM)) { 11638 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 11639 if (It == D.DeclToUniqueName.end()) 11640 continue; 11641 if (D.Disabled) 11642 return false; 11643 FoundE = E; 11644 FoundD = E->getMemberDecl()->getCanonicalDecl(); 11645 UniqueDeclName = It->second; 11646 IVLVal = D.IVLVal; 11647 FoundFn = D.Fn; 11648 break; 11649 } 11650 return FoundE == E; 11651 } 11652 bool VisitStmt(const Stmt *S) { 11653 for (const Stmt *Child : S->children()) { 11654 if (!Child) 11655 continue; 11656 if (const auto *E = dyn_cast<Expr>(Child)) 11657 if (!E->isGLValue()) 11658 continue; 11659 if (Visit(Child)) 11660 return true; 11661 } 11662 return false; 11663 } 11664 explicit LastprivateConditionalRefChecker( 11665 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 11666 : LPM(LPM) {} 11667 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 11668 getFoundData() const { 11669 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 11670 } 11671 }; 11672 } // namespace 11673 11674 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 11675 LValue IVLVal, 11676 StringRef UniqueDeclName, 11677 LValue LVal, 11678 SourceLocation Loc) { 11679 // Last updated loop counter for the lastprivate conditional var. 11680 // int<xx> last_iv = 0; 11681 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 11682 llvm::Constant *LastIV = 11683 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 11684 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 11685 IVLVal.getAlignment().getAsAlign()); 11686 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 11687 11688 // Last value of the lastprivate conditional. 11689 // decltype(priv_a) last_a; 11690 llvm::Constant *Last = getOrCreateInternalVariable( 11691 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 11692 cast<llvm::GlobalVariable>(Last)->setAlignment( 11693 LVal.getAlignment().getAsAlign()); 11694 LValue LastLVal = 11695 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 11696 11697 // Global loop counter. Required to handle inner parallel-for regions. 11698 // iv 11699 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 11700 11701 // #pragma omp critical(a) 11702 // if (last_iv <= iv) { 11703 // last_iv = iv; 11704 // last_a = priv_a; 11705 // } 11706 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 11707 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 11708 Action.Enter(CGF); 11709 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 11710 // (last_iv <= iv) ? Check if the variable is updated and store new 11711 // value in global var. 11712 llvm::Value *CmpRes; 11713 if (IVLVal.getType()->isSignedIntegerType()) { 11714 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 11715 } else { 11716 assert(IVLVal.getType()->isUnsignedIntegerType() && 11717 "Loop iteration variable must be integer."); 11718 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 11719 } 11720 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 11721 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 11722 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 11723 // { 11724 CGF.EmitBlock(ThenBB); 11725 11726 // last_iv = iv; 11727 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 11728 11729 // last_a = priv_a; 11730 switch (CGF.getEvaluationKind(LVal.getType())) { 11731 case TEK_Scalar: { 11732 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 11733 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 11734 break; 11735 } 11736 case TEK_Complex: { 11737 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 11738 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 11739 break; 11740 } 11741 case TEK_Aggregate: 11742 llvm_unreachable( 11743 "Aggregates are not supported in lastprivate conditional."); 11744 } 11745 // } 11746 CGF.EmitBranch(ExitBB); 11747 // There is no need to emit line number for unconditional branch. 11748 (void)ApplyDebugLocation::CreateEmpty(CGF); 11749 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 11750 }; 11751 11752 if (CGM.getLangOpts().OpenMPSimd) { 11753 // Do not emit as a critical region as no parallel region could be emitted. 11754 RegionCodeGenTy ThenRCG(CodeGen); 11755 ThenRCG(CGF); 11756 } else { 11757 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 11758 } 11759 } 11760 11761 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 11762 const Expr *LHS) { 11763 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11764 return; 11765 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 11766 if (!Checker.Visit(LHS)) 11767 return; 11768 const Expr *FoundE; 11769 const Decl *FoundD; 11770 StringRef UniqueDeclName; 11771 LValue IVLVal; 11772 llvm::Function *FoundFn; 11773 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 11774 Checker.getFoundData(); 11775 if (FoundFn != CGF.CurFn) { 11776 // Special codegen for inner parallel regions. 11777 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 11778 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 11779 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 11780 "Lastprivate conditional is not found in outer region."); 11781 QualType StructTy = std::get<0>(It->getSecond()); 11782 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 11783 LValue PrivLVal = CGF.EmitLValue(FoundE); 11784 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11785 PrivLVal.getAddress(CGF), 11786 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 11787 LValue BaseLVal = 11788 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 11789 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 11790 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 11791 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 11792 FiredLVal, llvm::AtomicOrdering::Unordered, 11793 /*IsVolatile=*/true, /*isInit=*/false); 11794 return; 11795 } 11796 11797 // Private address of the lastprivate conditional in the current context. 11798 // priv_a 11799 LValue LVal = CGF.EmitLValue(FoundE); 11800 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 11801 FoundE->getExprLoc()); 11802 } 11803 11804 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 11805 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11806 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 11807 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11808 return; 11809 auto Range = llvm::reverse(LastprivateConditionalStack); 11810 auto It = llvm::find_if( 11811 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 11812 if (It == Range.end() || It->Fn != CGF.CurFn) 11813 return; 11814 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 11815 assert(LPCI != LastprivateConditionalToTypes.end() && 11816 "Lastprivates must be registered already."); 11817 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11818 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 11819 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 11820 for (const auto &Pair : It->DeclToUniqueName) { 11821 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 11822 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 11823 continue; 11824 auto I = LPCI->getSecond().find(Pair.first); 11825 assert(I != LPCI->getSecond().end() && 11826 "Lastprivate must be rehistered already."); 11827 // bool Cmp = priv_a.Fired != 0; 11828 LValue BaseLVal = std::get<3>(I->getSecond()); 11829 LValue FiredLVal = 11830 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 11831 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 11832 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 11833 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 11834 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 11835 // if (Cmp) { 11836 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 11837 CGF.EmitBlock(ThenBB); 11838 Address Addr = CGF.GetAddrOfLocalVar(VD); 11839 LValue LVal; 11840 if (VD->getType()->isReferenceType()) 11841 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 11842 AlignmentSource::Decl); 11843 else 11844 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 11845 AlignmentSource::Decl); 11846 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 11847 D.getBeginLoc()); 11848 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 11849 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 11850 // } 11851 } 11852 } 11853 11854 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 11855 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 11856 SourceLocation Loc) { 11857 if (CGF.getLangOpts().OpenMP < 50) 11858 return; 11859 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 11860 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 11861 "Unknown lastprivate conditional variable."); 11862 StringRef UniqueName = It->second; 11863 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 11864 // The variable was not updated in the region - exit. 11865 if (!GV) 11866 return; 11867 LValue LPLVal = CGF.MakeAddrLValue( 11868 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 11869 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 11870 CGF.EmitStoreOfScalar(Res, PrivLVal); 11871 } 11872 11873 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11874 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11875 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11876 llvm_unreachable("Not supported in SIMD-only mode"); 11877 } 11878 11879 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11880 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11881 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11882 llvm_unreachable("Not supported in SIMD-only mode"); 11883 } 11884 11885 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11886 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11887 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11888 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11889 bool Tied, unsigned &NumberOfParts) { 11890 llvm_unreachable("Not supported in SIMD-only mode"); 11891 } 11892 11893 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11894 SourceLocation Loc, 11895 llvm::Function *OutlinedFn, 11896 ArrayRef<llvm::Value *> CapturedVars, 11897 const Expr *IfCond) { 11898 llvm_unreachable("Not supported in SIMD-only mode"); 11899 } 11900 11901 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11902 CodeGenFunction &CGF, StringRef CriticalName, 11903 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11904 const Expr *Hint) { 11905 llvm_unreachable("Not supported in SIMD-only mode"); 11906 } 11907 11908 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11909 const RegionCodeGenTy &MasterOpGen, 11910 SourceLocation Loc) { 11911 llvm_unreachable("Not supported in SIMD-only mode"); 11912 } 11913 11914 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11915 SourceLocation Loc) { 11916 llvm_unreachable("Not supported in SIMD-only mode"); 11917 } 11918 11919 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11920 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11921 SourceLocation Loc) { 11922 llvm_unreachable("Not supported in SIMD-only mode"); 11923 } 11924 11925 void CGOpenMPSIMDRuntime::emitSingleRegion( 11926 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11927 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11928 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11929 ArrayRef<const Expr *> AssignmentOps) { 11930 llvm_unreachable("Not supported in SIMD-only mode"); 11931 } 11932 11933 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11934 const RegionCodeGenTy &OrderedOpGen, 11935 SourceLocation Loc, 11936 bool IsThreads) { 11937 llvm_unreachable("Not supported in SIMD-only mode"); 11938 } 11939 11940 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11941 SourceLocation Loc, 11942 OpenMPDirectiveKind Kind, 11943 bool EmitChecks, 11944 bool ForceSimpleCall) { 11945 llvm_unreachable("Not supported in SIMD-only mode"); 11946 } 11947 11948 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11949 CodeGenFunction &CGF, SourceLocation Loc, 11950 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11951 bool Ordered, const DispatchRTInput &DispatchValues) { 11952 llvm_unreachable("Not supported in SIMD-only mode"); 11953 } 11954 11955 void CGOpenMPSIMDRuntime::emitForStaticInit( 11956 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11957 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11958 llvm_unreachable("Not supported in SIMD-only mode"); 11959 } 11960 11961 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11962 CodeGenFunction &CGF, SourceLocation Loc, 11963 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11964 llvm_unreachable("Not supported in SIMD-only mode"); 11965 } 11966 11967 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11968 SourceLocation Loc, 11969 unsigned IVSize, 11970 bool IVSigned) { 11971 llvm_unreachable("Not supported in SIMD-only mode"); 11972 } 11973 11974 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11975 SourceLocation Loc, 11976 OpenMPDirectiveKind DKind) { 11977 llvm_unreachable("Not supported in SIMD-only mode"); 11978 } 11979 11980 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11981 SourceLocation Loc, 11982 unsigned IVSize, bool IVSigned, 11983 Address IL, Address LB, 11984 Address UB, Address ST) { 11985 llvm_unreachable("Not supported in SIMD-only mode"); 11986 } 11987 11988 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11989 llvm::Value *NumThreads, 11990 SourceLocation Loc) { 11991 llvm_unreachable("Not supported in SIMD-only mode"); 11992 } 11993 11994 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11995 ProcBindKind ProcBind, 11996 SourceLocation Loc) { 11997 llvm_unreachable("Not supported in SIMD-only mode"); 11998 } 11999 12000 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 12001 const VarDecl *VD, 12002 Address VDAddr, 12003 SourceLocation Loc) { 12004 llvm_unreachable("Not supported in SIMD-only mode"); 12005 } 12006 12007 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 12008 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 12009 CodeGenFunction *CGF) { 12010 llvm_unreachable("Not supported in SIMD-only mode"); 12011 } 12012 12013 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 12014 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 12015 llvm_unreachable("Not supported in SIMD-only mode"); 12016 } 12017 12018 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 12019 ArrayRef<const Expr *> Vars, 12020 SourceLocation Loc, 12021 llvm::AtomicOrdering AO) { 12022 llvm_unreachable("Not supported in SIMD-only mode"); 12023 } 12024 12025 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 12026 const OMPExecutableDirective &D, 12027 llvm::Function *TaskFunction, 12028 QualType SharedsTy, Address Shareds, 12029 const Expr *IfCond, 12030 const OMPTaskDataTy &Data) { 12031 llvm_unreachable("Not supported in SIMD-only mode"); 12032 } 12033 12034 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 12035 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 12036 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 12037 const Expr *IfCond, const OMPTaskDataTy &Data) { 12038 llvm_unreachable("Not supported in SIMD-only mode"); 12039 } 12040 12041 void CGOpenMPSIMDRuntime::emitReduction( 12042 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 12043 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 12044 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 12045 assert(Options.SimpleReduction && "Only simple reduction is expected."); 12046 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 12047 ReductionOps, Options); 12048 } 12049 12050 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 12051 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 12052 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 12053 llvm_unreachable("Not supported in SIMD-only mode"); 12054 } 12055 12056 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 12057 SourceLocation Loc, 12058 ReductionCodeGen &RCG, 12059 unsigned N) { 12060 llvm_unreachable("Not supported in SIMD-only mode"); 12061 } 12062 12063 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 12064 SourceLocation Loc, 12065 llvm::Value *ReductionsPtr, 12066 LValue SharedLVal) { 12067 llvm_unreachable("Not supported in SIMD-only mode"); 12068 } 12069 12070 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 12071 SourceLocation Loc) { 12072 llvm_unreachable("Not supported in SIMD-only mode"); 12073 } 12074 12075 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 12076 CodeGenFunction &CGF, SourceLocation Loc, 12077 OpenMPDirectiveKind CancelRegion) { 12078 llvm_unreachable("Not supported in SIMD-only mode"); 12079 } 12080 12081 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 12082 SourceLocation Loc, const Expr *IfCond, 12083 OpenMPDirectiveKind CancelRegion) { 12084 llvm_unreachable("Not supported in SIMD-only mode"); 12085 } 12086 12087 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 12088 const OMPExecutableDirective &D, StringRef ParentName, 12089 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 12090 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 12091 llvm_unreachable("Not supported in SIMD-only mode"); 12092 } 12093 12094 void CGOpenMPSIMDRuntime::emitTargetCall( 12095 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12096 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 12097 const Expr *Device, 12098 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 12099 const OMPLoopDirective &D)> 12100 SizeEmitter) { 12101 llvm_unreachable("Not supported in SIMD-only mode"); 12102 } 12103 12104 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 12105 llvm_unreachable("Not supported in SIMD-only mode"); 12106 } 12107 12108 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 12109 llvm_unreachable("Not supported in SIMD-only mode"); 12110 } 12111 12112 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 12113 return false; 12114 } 12115 12116 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 12117 const OMPExecutableDirective &D, 12118 SourceLocation Loc, 12119 llvm::Function *OutlinedFn, 12120 ArrayRef<llvm::Value *> CapturedVars) { 12121 llvm_unreachable("Not supported in SIMD-only mode"); 12122 } 12123 12124 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 12125 const Expr *NumTeams, 12126 const Expr *ThreadLimit, 12127 SourceLocation Loc) { 12128 llvm_unreachable("Not supported in SIMD-only mode"); 12129 } 12130 12131 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 12132 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12133 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 12134 llvm_unreachable("Not supported in SIMD-only mode"); 12135 } 12136 12137 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 12138 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12139 const Expr *Device) { 12140 llvm_unreachable("Not supported in SIMD-only mode"); 12141 } 12142 12143 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12144 const OMPLoopDirective &D, 12145 ArrayRef<Expr *> NumIterations) { 12146 llvm_unreachable("Not supported in SIMD-only mode"); 12147 } 12148 12149 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12150 const OMPDependClause *C) { 12151 llvm_unreachable("Not supported in SIMD-only mode"); 12152 } 12153 12154 const VarDecl * 12155 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 12156 const VarDecl *NativeParam) const { 12157 llvm_unreachable("Not supported in SIMD-only mode"); 12158 } 12159 12160 Address 12161 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 12162 const VarDecl *NativeParam, 12163 const VarDecl *TargetParam) const { 12164 llvm_unreachable("Not supported in SIMD-only mode"); 12165 } 12166