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/CodeGen/ConstantInitBuilder.h" 25 #include "llvm/ADT/ArrayRef.h" 26 #include "llvm/ADT/SetOperations.h" 27 #include "llvm/ADT/StringExtras.h" 28 #include "llvm/Bitcode/BitcodeReader.h" 29 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 30 #include "llvm/IR/DerivedTypes.h" 31 #include "llvm/IR/GlobalValue.h" 32 #include "llvm/IR/Value.h" 33 #include "llvm/Support/Format.h" 34 #include "llvm/Support/raw_ostream.h" 35 #include <cassert> 36 37 using namespace clang; 38 using namespace CodeGen; 39 using namespace llvm::omp; 40 41 namespace { 42 /// Base class for handling code generation inside OpenMP regions. 43 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 44 public: 45 /// Kinds of OpenMP regions used in codegen. 46 enum CGOpenMPRegionKind { 47 /// Region with outlined function for standalone 'parallel' 48 /// directive. 49 ParallelOutlinedRegion, 50 /// Region with outlined function for standalone 'task' directive. 51 TaskOutlinedRegion, 52 /// Region for constructs that do not require function outlining, 53 /// like 'for', 'sections', 'atomic' etc. directives. 54 InlinedRegion, 55 /// Region with outlined function for standalone 'target' directive. 56 TargetRegion, 57 }; 58 59 CGOpenMPRegionInfo(const CapturedStmt &CS, 60 const CGOpenMPRegionKind RegionKind, 61 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 62 bool HasCancel) 63 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 64 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 65 66 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 67 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 68 bool HasCancel) 69 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 70 Kind(Kind), HasCancel(HasCancel) {} 71 72 /// Get a variable or parameter for storing global thread id 73 /// inside OpenMP construct. 74 virtual const VarDecl *getThreadIDVariable() const = 0; 75 76 /// Emit the captured statement body. 77 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 78 79 /// Get an LValue for the current ThreadID variable. 80 /// \return LValue for thread id variable. This LValue always has type int32*. 81 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 82 83 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 84 85 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 86 87 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 88 89 bool hasCancel() const { return HasCancel; } 90 91 static bool classof(const CGCapturedStmtInfo *Info) { 92 return Info->getKind() == CR_OpenMP; 93 } 94 95 ~CGOpenMPRegionInfo() override = default; 96 97 protected: 98 CGOpenMPRegionKind RegionKind; 99 RegionCodeGenTy CodeGen; 100 OpenMPDirectiveKind Kind; 101 bool HasCancel; 102 }; 103 104 /// API for captured statement code generation in OpenMP constructs. 105 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 106 public: 107 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 108 const RegionCodeGenTy &CodeGen, 109 OpenMPDirectiveKind Kind, bool HasCancel, 110 StringRef HelperName) 111 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 112 HasCancel), 113 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 114 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 115 } 116 117 /// Get a variable or parameter for storing global thread id 118 /// inside OpenMP construct. 119 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 120 121 /// Get the name of the capture helper. 122 StringRef getHelperName() const override { return HelperName; } 123 124 static bool classof(const CGCapturedStmtInfo *Info) { 125 return CGOpenMPRegionInfo::classof(Info) && 126 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 127 ParallelOutlinedRegion; 128 } 129 130 private: 131 /// A variable or parameter storing global thread id for OpenMP 132 /// constructs. 133 const VarDecl *ThreadIDVar; 134 StringRef HelperName; 135 }; 136 137 /// API for captured statement code generation in OpenMP constructs. 138 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 139 public: 140 class UntiedTaskActionTy final : public PrePostActionTy { 141 bool Untied; 142 const VarDecl *PartIDVar; 143 const RegionCodeGenTy UntiedCodeGen; 144 llvm::SwitchInst *UntiedSwitch = nullptr; 145 146 public: 147 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 148 const RegionCodeGenTy &UntiedCodeGen) 149 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 150 void Enter(CodeGenFunction &CGF) override { 151 if (Untied) { 152 // Emit task switching point. 153 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 154 CGF.GetAddrOfLocalVar(PartIDVar), 155 PartIDVar->getType()->castAs<PointerType>()); 156 llvm::Value *Res = 157 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 158 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 159 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 160 CGF.EmitBlock(DoneBB); 161 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 162 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 163 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 164 CGF.Builder.GetInsertBlock()); 165 emitUntiedSwitch(CGF); 166 } 167 } 168 void emitUntiedSwitch(CodeGenFunction &CGF) const { 169 if (Untied) { 170 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 171 CGF.GetAddrOfLocalVar(PartIDVar), 172 PartIDVar->getType()->castAs<PointerType>()); 173 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 174 PartIdLVal); 175 UntiedCodeGen(CGF); 176 CodeGenFunction::JumpDest CurPoint = 177 CGF.getJumpDestInCurrentScope(".untied.next."); 178 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 179 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 180 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 181 CGF.Builder.GetInsertBlock()); 182 CGF.EmitBranchThroughCleanup(CurPoint); 183 CGF.EmitBlock(CurPoint.getBlock()); 184 } 185 } 186 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 187 }; 188 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 189 const VarDecl *ThreadIDVar, 190 const RegionCodeGenTy &CodeGen, 191 OpenMPDirectiveKind Kind, bool HasCancel, 192 const UntiedTaskActionTy &Action) 193 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 194 ThreadIDVar(ThreadIDVar), Action(Action) { 195 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 196 } 197 198 /// Get a variable or parameter for storing global thread id 199 /// inside OpenMP construct. 200 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 201 202 /// Get an LValue for the current ThreadID variable. 203 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 204 205 /// Get the name of the capture helper. 206 StringRef getHelperName() const override { return ".omp_outlined."; } 207 208 void emitUntiedSwitch(CodeGenFunction &CGF) override { 209 Action.emitUntiedSwitch(CGF); 210 } 211 212 static bool classof(const CGCapturedStmtInfo *Info) { 213 return CGOpenMPRegionInfo::classof(Info) && 214 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 215 TaskOutlinedRegion; 216 } 217 218 private: 219 /// A variable or parameter storing global thread id for OpenMP 220 /// constructs. 221 const VarDecl *ThreadIDVar; 222 /// Action for emitting code for untied tasks. 223 const UntiedTaskActionTy &Action; 224 }; 225 226 /// API for inlined captured statement code generation in OpenMP 227 /// constructs. 228 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 229 public: 230 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 231 const RegionCodeGenTy &CodeGen, 232 OpenMPDirectiveKind Kind, bool HasCancel) 233 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 234 OldCSI(OldCSI), 235 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 236 237 // Retrieve the value of the context parameter. 238 llvm::Value *getContextValue() const override { 239 if (OuterRegionInfo) 240 return OuterRegionInfo->getContextValue(); 241 llvm_unreachable("No context value for inlined OpenMP region"); 242 } 243 244 void setContextValue(llvm::Value *V) override { 245 if (OuterRegionInfo) { 246 OuterRegionInfo->setContextValue(V); 247 return; 248 } 249 llvm_unreachable("No context value for inlined OpenMP region"); 250 } 251 252 /// Lookup the captured field decl for a variable. 253 const FieldDecl *lookup(const VarDecl *VD) const override { 254 if (OuterRegionInfo) 255 return OuterRegionInfo->lookup(VD); 256 // If there is no outer outlined region,no need to lookup in a list of 257 // captured variables, we can use the original one. 258 return nullptr; 259 } 260 261 FieldDecl *getThisFieldDecl() const override { 262 if (OuterRegionInfo) 263 return OuterRegionInfo->getThisFieldDecl(); 264 return nullptr; 265 } 266 267 /// Get a variable or parameter for storing global thread id 268 /// inside OpenMP construct. 269 const VarDecl *getThreadIDVariable() const override { 270 if (OuterRegionInfo) 271 return OuterRegionInfo->getThreadIDVariable(); 272 return nullptr; 273 } 274 275 /// Get an LValue for the current ThreadID variable. 276 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 277 if (OuterRegionInfo) 278 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 279 llvm_unreachable("No LValue for inlined OpenMP construct"); 280 } 281 282 /// Get the name of the capture helper. 283 StringRef getHelperName() const override { 284 if (auto *OuterRegionInfo = getOldCSI()) 285 return OuterRegionInfo->getHelperName(); 286 llvm_unreachable("No helper name for inlined OpenMP construct"); 287 } 288 289 void emitUntiedSwitch(CodeGenFunction &CGF) override { 290 if (OuterRegionInfo) 291 OuterRegionInfo->emitUntiedSwitch(CGF); 292 } 293 294 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 295 296 static bool classof(const CGCapturedStmtInfo *Info) { 297 return CGOpenMPRegionInfo::classof(Info) && 298 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 299 } 300 301 ~CGOpenMPInlinedRegionInfo() override = default; 302 303 private: 304 /// CodeGen info about outer OpenMP region. 305 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 306 CGOpenMPRegionInfo *OuterRegionInfo; 307 }; 308 309 /// API for captured statement code generation in OpenMP target 310 /// constructs. For this captures, implicit parameters are used instead of the 311 /// captured fields. The name of the target region has to be unique in a given 312 /// application so it is provided by the client, because only the client has 313 /// the information to generate that. 314 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 315 public: 316 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 317 const RegionCodeGenTy &CodeGen, StringRef HelperName) 318 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 319 /*HasCancel=*/false), 320 HelperName(HelperName) {} 321 322 /// This is unused for target regions because each starts executing 323 /// with a single thread. 324 const VarDecl *getThreadIDVariable() const override { return nullptr; } 325 326 /// Get the name of the capture helper. 327 StringRef getHelperName() const override { return HelperName; } 328 329 static bool classof(const CGCapturedStmtInfo *Info) { 330 return CGOpenMPRegionInfo::classof(Info) && 331 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 332 } 333 334 private: 335 StringRef HelperName; 336 }; 337 338 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 339 llvm_unreachable("No codegen for expressions"); 340 } 341 /// API for generation of expressions captured in a innermost OpenMP 342 /// region. 343 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 344 public: 345 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 346 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 347 OMPD_unknown, 348 /*HasCancel=*/false), 349 PrivScope(CGF) { 350 // Make sure the globals captured in the provided statement are local by 351 // using the privatization logic. We assume the same variable is not 352 // captured more than once. 353 for (const auto &C : CS.captures()) { 354 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 355 continue; 356 357 const VarDecl *VD = C.getCapturedVar(); 358 if (VD->isLocalVarDeclOrParm()) 359 continue; 360 361 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 362 /*RefersToEnclosingVariableOrCapture=*/false, 363 VD->getType().getNonReferenceType(), VK_LValue, 364 C.getLocation()); 365 PrivScope.addPrivate( 366 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 367 } 368 (void)PrivScope.Privatize(); 369 } 370 371 /// Lookup the captured field decl for a variable. 372 const FieldDecl *lookup(const VarDecl *VD) const override { 373 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 374 return FD; 375 return nullptr; 376 } 377 378 /// Emit the captured statement body. 379 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 380 llvm_unreachable("No body for expressions"); 381 } 382 383 /// Get a variable or parameter for storing global thread id 384 /// inside OpenMP construct. 385 const VarDecl *getThreadIDVariable() const override { 386 llvm_unreachable("No thread id for expressions"); 387 } 388 389 /// Get the name of the capture helper. 390 StringRef getHelperName() const override { 391 llvm_unreachable("No helper name for expressions"); 392 } 393 394 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 395 396 private: 397 /// Private scope to capture global variables. 398 CodeGenFunction::OMPPrivateScope PrivScope; 399 }; 400 401 /// RAII for emitting code of OpenMP constructs. 402 class InlinedOpenMPRegionRAII { 403 CodeGenFunction &CGF; 404 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 405 FieldDecl *LambdaThisCaptureField = nullptr; 406 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 407 408 public: 409 /// Constructs region for combined constructs. 410 /// \param CodeGen Code generation sequence for combined directives. Includes 411 /// a list of functions used for code generation of implicitly inlined 412 /// regions. 413 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 414 OpenMPDirectiveKind Kind, bool HasCancel) 415 : CGF(CGF) { 416 // Start emission for the construct. 417 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 418 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 419 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 420 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 421 CGF.LambdaThisCaptureField = nullptr; 422 BlockInfo = CGF.BlockInfo; 423 CGF.BlockInfo = nullptr; 424 } 425 426 ~InlinedOpenMPRegionRAII() { 427 // Restore original CapturedStmtInfo only if we're done with code emission. 428 auto *OldCSI = 429 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 430 delete CGF.CapturedStmtInfo; 431 CGF.CapturedStmtInfo = OldCSI; 432 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 433 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 434 CGF.BlockInfo = BlockInfo; 435 } 436 }; 437 438 /// Values for bit flags used in the ident_t to describe the fields. 439 /// All enumeric elements are named and described in accordance with the code 440 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 441 enum OpenMPLocationFlags : unsigned { 442 /// Use trampoline for internal microtask. 443 OMP_IDENT_IMD = 0x01, 444 /// Use c-style ident structure. 445 OMP_IDENT_KMPC = 0x02, 446 /// Atomic reduction option for kmpc_reduce. 447 OMP_ATOMIC_REDUCE = 0x10, 448 /// Explicit 'barrier' directive. 449 OMP_IDENT_BARRIER_EXPL = 0x20, 450 /// Implicit barrier in code. 451 OMP_IDENT_BARRIER_IMPL = 0x40, 452 /// Implicit barrier in 'for' directive. 453 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 454 /// Implicit barrier in 'sections' directive. 455 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 456 /// Implicit barrier in 'single' directive. 457 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 458 /// Call of __kmp_for_static_init for static loop. 459 OMP_IDENT_WORK_LOOP = 0x200, 460 /// Call of __kmp_for_static_init for sections. 461 OMP_IDENT_WORK_SECTIONS = 0x400, 462 /// Call of __kmp_for_static_init for distribute. 463 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 464 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 465 }; 466 467 namespace { 468 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 469 /// Values for bit flags for marking which requires clauses have been used. 470 enum OpenMPOffloadingRequiresDirFlags : int64_t { 471 /// flag undefined. 472 OMP_REQ_UNDEFINED = 0x000, 473 /// no requires clause present. 474 OMP_REQ_NONE = 0x001, 475 /// reverse_offload clause. 476 OMP_REQ_REVERSE_OFFLOAD = 0x002, 477 /// unified_address clause. 478 OMP_REQ_UNIFIED_ADDRESS = 0x004, 479 /// unified_shared_memory clause. 480 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 481 /// dynamic_allocators clause. 482 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 483 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 484 }; 485 486 enum OpenMPOffloadingReservedDeviceIDs { 487 /// Device ID if the device was not defined, runtime should get it 488 /// from environment variables in the spec. 489 OMP_DEVICEID_UNDEF = -1, 490 }; 491 } // anonymous namespace 492 493 /// Describes ident structure that describes a source location. 494 /// All descriptions are taken from 495 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 496 /// Original structure: 497 /// typedef struct ident { 498 /// kmp_int32 reserved_1; /**< might be used in Fortran; 499 /// see above */ 500 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 501 /// KMP_IDENT_KMPC identifies this union 502 /// member */ 503 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 504 /// see above */ 505 ///#if USE_ITT_BUILD 506 /// /* but currently used for storing 507 /// region-specific ITT */ 508 /// /* contextual information. */ 509 ///#endif /* USE_ITT_BUILD */ 510 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 511 /// C++ */ 512 /// char const *psource; /**< String describing the source location. 513 /// The string is composed of semi-colon separated 514 // fields which describe the source file, 515 /// the function and a pair of line numbers that 516 /// delimit the construct. 517 /// */ 518 /// } ident_t; 519 enum IdentFieldIndex { 520 /// might be used in Fortran 521 IdentField_Reserved_1, 522 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 523 IdentField_Flags, 524 /// Not really used in Fortran any more 525 IdentField_Reserved_2, 526 /// Source[4] in Fortran, do not use for C++ 527 IdentField_Reserved_3, 528 /// String describing the source location. The string is composed of 529 /// semi-colon separated fields which describe the source file, the function 530 /// and a pair of line numbers that delimit the construct. 531 IdentField_PSource 532 }; 533 534 /// Schedule types for 'omp for' loops (these enumerators are taken from 535 /// the enum sched_type in kmp.h). 536 enum OpenMPSchedType { 537 /// Lower bound for default (unordered) versions. 538 OMP_sch_lower = 32, 539 OMP_sch_static_chunked = 33, 540 OMP_sch_static = 34, 541 OMP_sch_dynamic_chunked = 35, 542 OMP_sch_guided_chunked = 36, 543 OMP_sch_runtime = 37, 544 OMP_sch_auto = 38, 545 /// static with chunk adjustment (e.g., simd) 546 OMP_sch_static_balanced_chunked = 45, 547 /// Lower bound for 'ordered' versions. 548 OMP_ord_lower = 64, 549 OMP_ord_static_chunked = 65, 550 OMP_ord_static = 66, 551 OMP_ord_dynamic_chunked = 67, 552 OMP_ord_guided_chunked = 68, 553 OMP_ord_runtime = 69, 554 OMP_ord_auto = 70, 555 OMP_sch_default = OMP_sch_static, 556 /// dist_schedule types 557 OMP_dist_sch_static_chunked = 91, 558 OMP_dist_sch_static = 92, 559 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 560 /// Set if the monotonic schedule modifier was present. 561 OMP_sch_modifier_monotonic = (1 << 29), 562 /// Set if the nonmonotonic schedule modifier was present. 563 OMP_sch_modifier_nonmonotonic = (1 << 30), 564 }; 565 566 enum OpenMPRTLFunction { 567 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 568 /// kmpc_micro microtask, ...); 569 OMPRTL__kmpc_fork_call, 570 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 571 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 572 OMPRTL__kmpc_threadprivate_cached, 573 /// Call to void __kmpc_threadprivate_register( ident_t *, 574 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 575 OMPRTL__kmpc_threadprivate_register, 576 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 577 OMPRTL__kmpc_global_thread_num, 578 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 579 // kmp_critical_name *crit); 580 OMPRTL__kmpc_critical, 581 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 582 // global_tid, kmp_critical_name *crit, uintptr_t hint); 583 OMPRTL__kmpc_critical_with_hint, 584 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 585 // kmp_critical_name *crit); 586 OMPRTL__kmpc_end_critical, 587 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 588 // global_tid); 589 OMPRTL__kmpc_cancel_barrier, 590 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 591 OMPRTL__kmpc_barrier, 592 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 593 OMPRTL__kmpc_for_static_fini, 594 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 595 // global_tid); 596 OMPRTL__kmpc_serialized_parallel, 597 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 598 // global_tid); 599 OMPRTL__kmpc_end_serialized_parallel, 600 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 601 // kmp_int32 num_threads); 602 OMPRTL__kmpc_push_num_threads, 603 // Call to void __kmpc_flush(ident_t *loc); 604 OMPRTL__kmpc_flush, 605 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 606 OMPRTL__kmpc_master, 607 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 608 OMPRTL__kmpc_end_master, 609 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 610 // int end_part); 611 OMPRTL__kmpc_omp_taskyield, 612 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 613 OMPRTL__kmpc_single, 614 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 615 OMPRTL__kmpc_end_single, 616 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 617 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 618 // kmp_routine_entry_t *task_entry); 619 OMPRTL__kmpc_omp_task_alloc, 620 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 621 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 622 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 623 // kmp_int64 device_id); 624 OMPRTL__kmpc_omp_target_task_alloc, 625 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 626 // new_task); 627 OMPRTL__kmpc_omp_task, 628 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 629 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 630 // kmp_int32 didit); 631 OMPRTL__kmpc_copyprivate, 632 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 633 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 634 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 635 OMPRTL__kmpc_reduce, 636 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 637 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 638 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 639 // *lck); 640 OMPRTL__kmpc_reduce_nowait, 641 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 642 // kmp_critical_name *lck); 643 OMPRTL__kmpc_end_reduce, 644 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 645 // kmp_critical_name *lck); 646 OMPRTL__kmpc_end_reduce_nowait, 647 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 648 // kmp_task_t * new_task); 649 OMPRTL__kmpc_omp_task_begin_if0, 650 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 651 // kmp_task_t * new_task); 652 OMPRTL__kmpc_omp_task_complete_if0, 653 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 654 OMPRTL__kmpc_ordered, 655 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 656 OMPRTL__kmpc_end_ordered, 657 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 658 // global_tid); 659 OMPRTL__kmpc_omp_taskwait, 660 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 661 OMPRTL__kmpc_taskgroup, 662 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 663 OMPRTL__kmpc_end_taskgroup, 664 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 665 // int proc_bind); 666 OMPRTL__kmpc_push_proc_bind, 667 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 668 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 669 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 670 OMPRTL__kmpc_omp_task_with_deps, 671 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 672 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 673 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 674 OMPRTL__kmpc_omp_wait_deps, 675 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 676 // global_tid, kmp_int32 cncl_kind); 677 OMPRTL__kmpc_cancellationpoint, 678 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 679 // kmp_int32 cncl_kind); 680 OMPRTL__kmpc_cancel, 681 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 682 // kmp_int32 num_teams, kmp_int32 thread_limit); 683 OMPRTL__kmpc_push_num_teams, 684 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 685 // microtask, ...); 686 OMPRTL__kmpc_fork_teams, 687 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 688 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 689 // sched, kmp_uint64 grainsize, void *task_dup); 690 OMPRTL__kmpc_taskloop, 691 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 692 // num_dims, struct kmp_dim *dims); 693 OMPRTL__kmpc_doacross_init, 694 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 695 OMPRTL__kmpc_doacross_fini, 696 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 697 // *vec); 698 OMPRTL__kmpc_doacross_post, 699 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 700 // *vec); 701 OMPRTL__kmpc_doacross_wait, 702 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 703 // *data); 704 OMPRTL__kmpc_task_reduction_init, 705 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 706 // *d); 707 OMPRTL__kmpc_task_reduction_get_th_data, 708 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 709 OMPRTL__kmpc_alloc, 710 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 711 OMPRTL__kmpc_free, 712 713 // 714 // Offloading related calls 715 // 716 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 717 // size); 718 OMPRTL__kmpc_push_target_tripcount, 719 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 720 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 721 // *arg_types); 722 OMPRTL__tgt_target, 723 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 724 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 725 // *arg_types); 726 OMPRTL__tgt_target_nowait, 727 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 728 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 729 // *arg_types, int32_t num_teams, int32_t thread_limit); 730 OMPRTL__tgt_target_teams, 731 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 732 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 733 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 734 OMPRTL__tgt_target_teams_nowait, 735 // Call to void __tgt_register_requires(int64_t flags); 736 OMPRTL__tgt_register_requires, 737 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 738 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 739 OMPRTL__tgt_target_data_begin, 740 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 741 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 742 // *arg_types); 743 OMPRTL__tgt_target_data_begin_nowait, 744 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 745 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 746 OMPRTL__tgt_target_data_end, 747 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 748 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 749 // *arg_types); 750 OMPRTL__tgt_target_data_end_nowait, 751 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 752 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 753 OMPRTL__tgt_target_data_update, 754 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 755 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 756 // *arg_types); 757 OMPRTL__tgt_target_data_update_nowait, 758 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 759 OMPRTL__tgt_mapper_num_components, 760 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 761 // *base, void *begin, int64_t size, int64_t type); 762 OMPRTL__tgt_push_mapper_component, 763 }; 764 765 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 766 /// region. 767 class CleanupTy final : public EHScopeStack::Cleanup { 768 PrePostActionTy *Action; 769 770 public: 771 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 772 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 773 if (!CGF.HaveInsertPoint()) 774 return; 775 Action->Exit(CGF); 776 } 777 }; 778 779 } // anonymous namespace 780 781 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 782 CodeGenFunction::RunCleanupsScope Scope(CGF); 783 if (PrePostAction) { 784 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 785 Callback(CodeGen, CGF, *PrePostAction); 786 } else { 787 PrePostActionTy Action; 788 Callback(CodeGen, CGF, Action); 789 } 790 } 791 792 /// Check if the combiner is a call to UDR combiner and if it is so return the 793 /// UDR decl used for reduction. 794 static const OMPDeclareReductionDecl * 795 getReductionInit(const Expr *ReductionOp) { 796 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 797 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 798 if (const auto *DRE = 799 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 800 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 801 return DRD; 802 return nullptr; 803 } 804 805 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 806 const OMPDeclareReductionDecl *DRD, 807 const Expr *InitOp, 808 Address Private, Address Original, 809 QualType Ty) { 810 if (DRD->getInitializer()) { 811 std::pair<llvm::Function *, llvm::Function *> Reduction = 812 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 813 const auto *CE = cast<CallExpr>(InitOp); 814 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 815 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 816 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 817 const auto *LHSDRE = 818 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 819 const auto *RHSDRE = 820 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 821 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 822 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 823 [=]() { return Private; }); 824 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 825 [=]() { return Original; }); 826 (void)PrivateScope.Privatize(); 827 RValue Func = RValue::get(Reduction.second); 828 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 829 CGF.EmitIgnoredExpr(InitOp); 830 } else { 831 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 832 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 833 auto *GV = new llvm::GlobalVariable( 834 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 835 llvm::GlobalValue::PrivateLinkage, Init, Name); 836 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 837 RValue InitRVal; 838 switch (CGF.getEvaluationKind(Ty)) { 839 case TEK_Scalar: 840 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 841 break; 842 case TEK_Complex: 843 InitRVal = 844 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 845 break; 846 case TEK_Aggregate: 847 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 848 break; 849 } 850 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 851 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 852 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 853 /*IsInitializer=*/false); 854 } 855 } 856 857 /// Emit initialization of arrays of complex types. 858 /// \param DestAddr Address of the array. 859 /// \param Type Type of array. 860 /// \param Init Initial expression of array. 861 /// \param SrcAddr Address of the original array. 862 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 863 QualType Type, bool EmitDeclareReductionInit, 864 const Expr *Init, 865 const OMPDeclareReductionDecl *DRD, 866 Address SrcAddr = Address::invalid()) { 867 // Perform element-by-element initialization. 868 QualType ElementTy; 869 870 // Drill down to the base element type on both arrays. 871 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 872 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 873 DestAddr = 874 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 875 if (DRD) 876 SrcAddr = 877 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 878 879 llvm::Value *SrcBegin = nullptr; 880 if (DRD) 881 SrcBegin = SrcAddr.getPointer(); 882 llvm::Value *DestBegin = DestAddr.getPointer(); 883 // Cast from pointer to array type to pointer to single element. 884 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 885 // The basic structure here is a while-do loop. 886 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 887 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 888 llvm::Value *IsEmpty = 889 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 890 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 891 892 // Enter the loop body, making that address the current address. 893 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 894 CGF.EmitBlock(BodyBB); 895 896 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 897 898 llvm::PHINode *SrcElementPHI = nullptr; 899 Address SrcElementCurrent = Address::invalid(); 900 if (DRD) { 901 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 902 "omp.arraycpy.srcElementPast"); 903 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 904 SrcElementCurrent = 905 Address(SrcElementPHI, 906 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 907 } 908 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 909 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 910 DestElementPHI->addIncoming(DestBegin, EntryBB); 911 Address DestElementCurrent = 912 Address(DestElementPHI, 913 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 914 915 // Emit copy. 916 { 917 CodeGenFunction::RunCleanupsScope InitScope(CGF); 918 if (EmitDeclareReductionInit) { 919 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 920 SrcElementCurrent, ElementTy); 921 } else 922 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 923 /*IsInitializer=*/false); 924 } 925 926 if (DRD) { 927 // Shift the address forward by one element. 928 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 929 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 930 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 931 } 932 933 // Shift the address forward by one element. 934 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 935 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 936 // Check whether we've reached the end. 937 llvm::Value *Done = 938 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 939 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 940 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 941 942 // Done. 943 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 944 } 945 946 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 947 return CGF.EmitOMPSharedLValue(E); 948 } 949 950 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 951 const Expr *E) { 952 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 953 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 954 return LValue(); 955 } 956 957 void ReductionCodeGen::emitAggregateInitialization( 958 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 959 const OMPDeclareReductionDecl *DRD) { 960 // Emit VarDecl with copy init for arrays. 961 // Get the address of the original variable captured in current 962 // captured region. 963 const auto *PrivateVD = 964 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 965 bool EmitDeclareReductionInit = 966 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 967 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 968 EmitDeclareReductionInit, 969 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 970 : PrivateVD->getInit(), 971 DRD, SharedLVal.getAddress(CGF)); 972 } 973 974 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 975 ArrayRef<const Expr *> Privates, 976 ArrayRef<const Expr *> ReductionOps) { 977 ClausesData.reserve(Shareds.size()); 978 SharedAddresses.reserve(Shareds.size()); 979 Sizes.reserve(Shareds.size()); 980 BaseDecls.reserve(Shareds.size()); 981 auto IPriv = Privates.begin(); 982 auto IRed = ReductionOps.begin(); 983 for (const Expr *Ref : Shareds) { 984 ClausesData.emplace_back(Ref, *IPriv, *IRed); 985 std::advance(IPriv, 1); 986 std::advance(IRed, 1); 987 } 988 } 989 990 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 991 assert(SharedAddresses.size() == N && 992 "Number of generated lvalues must be exactly N."); 993 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 994 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 995 SharedAddresses.emplace_back(First, Second); 996 } 997 998 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 999 const auto *PrivateVD = 1000 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1001 QualType PrivateType = PrivateVD->getType(); 1002 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1003 if (!PrivateType->isVariablyModifiedType()) { 1004 Sizes.emplace_back( 1005 CGF.getTypeSize( 1006 SharedAddresses[N].first.getType().getNonReferenceType()), 1007 nullptr); 1008 return; 1009 } 1010 llvm::Value *Size; 1011 llvm::Value *SizeInChars; 1012 auto *ElemType = cast<llvm::PointerType>( 1013 SharedAddresses[N].first.getPointer(CGF)->getType()) 1014 ->getElementType(); 1015 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1016 if (AsArraySection) { 1017 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF), 1018 SharedAddresses[N].first.getPointer(CGF)); 1019 Size = CGF.Builder.CreateNUWAdd( 1020 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1021 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1022 } else { 1023 SizeInChars = CGF.getTypeSize( 1024 SharedAddresses[N].first.getType().getNonReferenceType()); 1025 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1026 } 1027 Sizes.emplace_back(SizeInChars, Size); 1028 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1029 CGF, 1030 cast<OpaqueValueExpr>( 1031 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1032 RValue::get(Size)); 1033 CGF.EmitVariablyModifiedType(PrivateType); 1034 } 1035 1036 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1037 llvm::Value *Size) { 1038 const auto *PrivateVD = 1039 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1040 QualType PrivateType = PrivateVD->getType(); 1041 if (!PrivateType->isVariablyModifiedType()) { 1042 assert(!Size && !Sizes[N].second && 1043 "Size should be nullptr for non-variably modified reduction " 1044 "items."); 1045 return; 1046 } 1047 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1048 CGF, 1049 cast<OpaqueValueExpr>( 1050 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1051 RValue::get(Size)); 1052 CGF.EmitVariablyModifiedType(PrivateType); 1053 } 1054 1055 void ReductionCodeGen::emitInitialization( 1056 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1057 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1058 assert(SharedAddresses.size() > N && "No variable was generated"); 1059 const auto *PrivateVD = 1060 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1061 const OMPDeclareReductionDecl *DRD = 1062 getReductionInit(ClausesData[N].ReductionOp); 1063 QualType PrivateType = PrivateVD->getType(); 1064 PrivateAddr = CGF.Builder.CreateElementBitCast( 1065 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1066 QualType SharedType = SharedAddresses[N].first.getType(); 1067 SharedLVal = CGF.MakeAddrLValue( 1068 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 1069 CGF.ConvertTypeForMem(SharedType)), 1070 SharedType, SharedAddresses[N].first.getBaseInfo(), 1071 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1072 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1073 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1074 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1075 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1076 PrivateAddr, SharedLVal.getAddress(CGF), 1077 SharedLVal.getType()); 1078 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1079 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1080 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1081 PrivateVD->getType().getQualifiers(), 1082 /*IsInitializer=*/false); 1083 } 1084 } 1085 1086 bool ReductionCodeGen::needCleanups(unsigned N) { 1087 const auto *PrivateVD = 1088 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1089 QualType PrivateType = PrivateVD->getType(); 1090 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1091 return DTorKind != QualType::DK_none; 1092 } 1093 1094 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1095 Address PrivateAddr) { 1096 const auto *PrivateVD = 1097 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1098 QualType PrivateType = PrivateVD->getType(); 1099 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1100 if (needCleanups(N)) { 1101 PrivateAddr = CGF.Builder.CreateElementBitCast( 1102 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1103 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1104 } 1105 } 1106 1107 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1108 LValue BaseLV) { 1109 BaseTy = BaseTy.getNonReferenceType(); 1110 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1111 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1112 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1113 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 1114 } else { 1115 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 1116 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1117 } 1118 BaseTy = BaseTy->getPointeeType(); 1119 } 1120 return CGF.MakeAddrLValue( 1121 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 1122 CGF.ConvertTypeForMem(ElTy)), 1123 BaseLV.getType(), BaseLV.getBaseInfo(), 1124 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1125 } 1126 1127 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1128 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1129 llvm::Value *Addr) { 1130 Address Tmp = Address::invalid(); 1131 Address TopTmp = Address::invalid(); 1132 Address MostTopTmp = Address::invalid(); 1133 BaseTy = BaseTy.getNonReferenceType(); 1134 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1135 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1136 Tmp = CGF.CreateMemTemp(BaseTy); 1137 if (TopTmp.isValid()) 1138 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1139 else 1140 MostTopTmp = Tmp; 1141 TopTmp = Tmp; 1142 BaseTy = BaseTy->getPointeeType(); 1143 } 1144 llvm::Type *Ty = BaseLVType; 1145 if (Tmp.isValid()) 1146 Ty = Tmp.getElementType(); 1147 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1148 if (Tmp.isValid()) { 1149 CGF.Builder.CreateStore(Addr, Tmp); 1150 return MostTopTmp; 1151 } 1152 return Address(Addr, BaseLVAlignment); 1153 } 1154 1155 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1156 const VarDecl *OrigVD = nullptr; 1157 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1158 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1159 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1160 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1161 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1162 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1163 DE = cast<DeclRefExpr>(Base); 1164 OrigVD = cast<VarDecl>(DE->getDecl()); 1165 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1166 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1167 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1168 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1169 DE = cast<DeclRefExpr>(Base); 1170 OrigVD = cast<VarDecl>(DE->getDecl()); 1171 } 1172 return OrigVD; 1173 } 1174 1175 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1176 Address PrivateAddr) { 1177 const DeclRefExpr *DE; 1178 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1179 BaseDecls.emplace_back(OrigVD); 1180 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1181 LValue BaseLValue = 1182 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1183 OriginalBaseLValue); 1184 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1185 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1186 llvm::Value *PrivatePointer = 1187 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1188 PrivateAddr.getPointer(), 1189 SharedAddresses[N].first.getAddress(CGF).getType()); 1190 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1191 return castToBase(CGF, OrigVD->getType(), 1192 SharedAddresses[N].first.getType(), 1193 OriginalBaseLValue.getAddress(CGF).getType(), 1194 OriginalBaseLValue.getAlignment(), Ptr); 1195 } 1196 BaseDecls.emplace_back( 1197 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1198 return PrivateAddr; 1199 } 1200 1201 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1202 const OMPDeclareReductionDecl *DRD = 1203 getReductionInit(ClausesData[N].ReductionOp); 1204 return DRD && DRD->getInitializer(); 1205 } 1206 1207 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1208 return CGF.EmitLoadOfPointerLValue( 1209 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1210 getThreadIDVariable()->getType()->castAs<PointerType>()); 1211 } 1212 1213 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1214 if (!CGF.HaveInsertPoint()) 1215 return; 1216 // 1.2.2 OpenMP Language Terminology 1217 // Structured block - An executable statement with a single entry at the 1218 // top and a single exit at the bottom. 1219 // The point of exit cannot be a branch out of the structured block. 1220 // longjmp() and throw() must not violate the entry/exit criteria. 1221 CGF.EHStack.pushTerminate(); 1222 CodeGen(CGF); 1223 CGF.EHStack.popTerminate(); 1224 } 1225 1226 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1227 CodeGenFunction &CGF) { 1228 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1229 getThreadIDVariable()->getType(), 1230 AlignmentSource::Decl); 1231 } 1232 1233 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1234 QualType FieldTy) { 1235 auto *Field = FieldDecl::Create( 1236 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1237 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1238 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1239 Field->setAccess(AS_public); 1240 DC->addDecl(Field); 1241 return Field; 1242 } 1243 1244 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1245 StringRef Separator) 1246 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1247 OffloadEntriesInfoManager(CGM) { 1248 ASTContext &C = CGM.getContext(); 1249 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1250 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1251 RD->startDefinition(); 1252 // reserved_1 1253 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1254 // flags 1255 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1256 // reserved_2 1257 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1258 // reserved_3 1259 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1260 // psource 1261 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1262 RD->completeDefinition(); 1263 IdentQTy = C.getRecordType(RD); 1264 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1265 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1266 1267 loadOffloadInfoMetadata(); 1268 } 1269 1270 bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD, 1271 const GlobalDecl &OldGD, 1272 llvm::GlobalValue *OrigAddr, 1273 bool IsForDefinition) { 1274 // Emit at least a definition for the aliasee if the the address of the 1275 // original function is requested. 1276 if (IsForDefinition || OrigAddr) 1277 (void)CGM.GetAddrOfGlobal(NewGD); 1278 StringRef NewMangledName = CGM.getMangledName(NewGD); 1279 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1280 if (Addr && !Addr->isDeclaration()) { 1281 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1282 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(NewGD); 1283 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1284 1285 // Create a reference to the named value. This ensures that it is emitted 1286 // if a deferred decl. 1287 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1288 1289 // Create the new alias itself, but don't set a name yet. 1290 auto *GA = 1291 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1292 1293 if (OrigAddr) { 1294 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1295 1296 GA->takeName(OrigAddr); 1297 OrigAddr->replaceAllUsesWith( 1298 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1299 OrigAddr->eraseFromParent(); 1300 } else { 1301 GA->setName(CGM.getMangledName(OldGD)); 1302 } 1303 1304 // Set attributes which are particular to an alias; this is a 1305 // specialization of the attributes which may be set on a global function. 1306 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1307 D->isWeakImported()) 1308 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1309 1310 CGM.SetCommonAttributes(OldGD, GA); 1311 return true; 1312 } 1313 return false; 1314 } 1315 1316 void CGOpenMPRuntime::clear() { 1317 InternalVars.clear(); 1318 // Clean non-target variable declarations possibly used only in debug info. 1319 for (const auto &Data : EmittedNonTargetVariables) { 1320 if (!Data.getValue().pointsToAliveValue()) 1321 continue; 1322 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1323 if (!GV) 1324 continue; 1325 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1326 continue; 1327 GV->eraseFromParent(); 1328 } 1329 // Emit aliases for the deferred aliasees. 1330 for (const auto &Pair : DeferredVariantFunction) { 1331 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1332 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1333 // If not able to emit alias, just emit original declaration. 1334 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr, 1335 /*IsForDefinition=*/false); 1336 } 1337 } 1338 1339 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1340 SmallString<128> Buffer; 1341 llvm::raw_svector_ostream OS(Buffer); 1342 StringRef Sep = FirstSeparator; 1343 for (StringRef Part : Parts) { 1344 OS << Sep << Part; 1345 Sep = Separator; 1346 } 1347 return std::string(OS.str()); 1348 } 1349 1350 static llvm::Function * 1351 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1352 const Expr *CombinerInitializer, const VarDecl *In, 1353 const VarDecl *Out, bool IsCombiner) { 1354 // void .omp_combiner.(Ty *in, Ty *out); 1355 ASTContext &C = CGM.getContext(); 1356 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1357 FunctionArgList Args; 1358 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1359 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1360 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1361 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1362 Args.push_back(&OmpOutParm); 1363 Args.push_back(&OmpInParm); 1364 const CGFunctionInfo &FnInfo = 1365 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1366 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1367 std::string Name = CGM.getOpenMPRuntime().getName( 1368 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1369 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1370 Name, &CGM.getModule()); 1371 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1372 if (CGM.getLangOpts().Optimize) { 1373 Fn->removeFnAttr(llvm::Attribute::NoInline); 1374 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1375 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1376 } 1377 CodeGenFunction CGF(CGM); 1378 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1379 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1380 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1381 Out->getLocation()); 1382 CodeGenFunction::OMPPrivateScope Scope(CGF); 1383 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1384 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1385 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1386 .getAddress(CGF); 1387 }); 1388 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1389 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1390 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1391 .getAddress(CGF); 1392 }); 1393 (void)Scope.Privatize(); 1394 if (!IsCombiner && Out->hasInit() && 1395 !CGF.isTrivialInitializer(Out->getInit())) { 1396 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1397 Out->getType().getQualifiers(), 1398 /*IsInitializer=*/true); 1399 } 1400 if (CombinerInitializer) 1401 CGF.EmitIgnoredExpr(CombinerInitializer); 1402 Scope.ForceCleanup(); 1403 CGF.FinishFunction(); 1404 return Fn; 1405 } 1406 1407 void CGOpenMPRuntime::emitUserDefinedReduction( 1408 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1409 if (UDRMap.count(D) > 0) 1410 return; 1411 llvm::Function *Combiner = emitCombinerOrInitializer( 1412 CGM, D->getType(), D->getCombiner(), 1413 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1414 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1415 /*IsCombiner=*/true); 1416 llvm::Function *Initializer = nullptr; 1417 if (const Expr *Init = D->getInitializer()) { 1418 Initializer = emitCombinerOrInitializer( 1419 CGM, D->getType(), 1420 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1421 : nullptr, 1422 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1423 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1424 /*IsCombiner=*/false); 1425 } 1426 UDRMap.try_emplace(D, Combiner, Initializer); 1427 if (CGF) { 1428 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1429 Decls.second.push_back(D); 1430 } 1431 } 1432 1433 std::pair<llvm::Function *, llvm::Function *> 1434 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1435 auto I = UDRMap.find(D); 1436 if (I != UDRMap.end()) 1437 return I->second; 1438 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1439 return UDRMap.lookup(D); 1440 } 1441 1442 namespace { 1443 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1444 // Builder if one is present. 1445 struct PushAndPopStackRAII { 1446 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1447 bool HasCancel) 1448 : OMPBuilder(OMPBuilder) { 1449 if (!OMPBuilder) 1450 return; 1451 1452 // The following callback is the crucial part of clangs cleanup process. 1453 // 1454 // NOTE: 1455 // Once the OpenMPIRBuilder is used to create parallel regions (and 1456 // similar), the cancellation destination (Dest below) is determined via 1457 // IP. That means if we have variables to finalize we split the block at IP, 1458 // use the new block (=BB) as destination to build a JumpDest (via 1459 // getJumpDestInCurrentScope(BB)) which then is fed to 1460 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1461 // to push & pop an FinalizationInfo object. 1462 // The FiniCB will still be needed but at the point where the 1463 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1464 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1465 assert(IP.getBlock()->end() == IP.getPoint() && 1466 "Clang CG should cause non-terminated block!"); 1467 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1468 CGF.Builder.restoreIP(IP); 1469 CodeGenFunction::JumpDest Dest = 1470 CGF.getOMPCancelDestination(OMPD_parallel); 1471 CGF.EmitBranchThroughCleanup(Dest); 1472 }; 1473 1474 // TODO: Remove this once we emit parallel regions through the 1475 // OpenMPIRBuilder as it can do this setup internally. 1476 llvm::OpenMPIRBuilder::FinalizationInfo FI( 1477 {FiniCB, OMPD_parallel, HasCancel}); 1478 OMPBuilder->pushFinalizationCB(std::move(FI)); 1479 } 1480 ~PushAndPopStackRAII() { 1481 if (OMPBuilder) 1482 OMPBuilder->popFinalizationCB(); 1483 } 1484 llvm::OpenMPIRBuilder *OMPBuilder; 1485 }; 1486 } // namespace 1487 1488 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1489 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1490 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1491 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1492 assert(ThreadIDVar->getType()->isPointerType() && 1493 "thread id variable must be of type kmp_int32 *"); 1494 CodeGenFunction CGF(CGM, true); 1495 bool HasCancel = false; 1496 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1497 HasCancel = OPD->hasCancel(); 1498 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1499 HasCancel = OPSD->hasCancel(); 1500 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1501 HasCancel = OPFD->hasCancel(); 1502 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1503 HasCancel = OPFD->hasCancel(); 1504 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1505 HasCancel = OPFD->hasCancel(); 1506 else if (const auto *OPFD = 1507 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1508 HasCancel = OPFD->hasCancel(); 1509 else if (const auto *OPFD = 1510 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1511 HasCancel = OPFD->hasCancel(); 1512 1513 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1514 // parallel region to make cancellation barriers work properly. 1515 llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder(); 1516 PushAndPopStackRAII PSR(OMPBuilder, CGF, HasCancel); 1517 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1518 HasCancel, OutlinedHelperName); 1519 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1520 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1521 } 1522 1523 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1524 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1525 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1526 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1527 return emitParallelOrTeamsOutlinedFunction( 1528 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1529 } 1530 1531 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1532 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1533 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1534 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1535 return emitParallelOrTeamsOutlinedFunction( 1536 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1537 } 1538 1539 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1540 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1541 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1542 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1543 bool Tied, unsigned &NumberOfParts) { 1544 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1545 PrePostActionTy &) { 1546 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1547 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1548 llvm::Value *TaskArgs[] = { 1549 UpLoc, ThreadID, 1550 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1551 TaskTVar->getType()->castAs<PointerType>()) 1552 .getPointer(CGF)}; 1553 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1554 }; 1555 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1556 UntiedCodeGen); 1557 CodeGen.setAction(Action); 1558 assert(!ThreadIDVar->getType()->isPointerType() && 1559 "thread id variable must be of type kmp_int32 for tasks"); 1560 const OpenMPDirectiveKind Region = 1561 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1562 : OMPD_task; 1563 const CapturedStmt *CS = D.getCapturedStmt(Region); 1564 const auto *TD = dyn_cast<OMPTaskDirective>(&D); 1565 CodeGenFunction CGF(CGM, true); 1566 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1567 InnermostKind, 1568 TD ? TD->hasCancel() : false, Action); 1569 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1570 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1571 if (!Tied) 1572 NumberOfParts = Action.getNumberOfParts(); 1573 return Res; 1574 } 1575 1576 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1577 const RecordDecl *RD, const CGRecordLayout &RL, 1578 ArrayRef<llvm::Constant *> Data) { 1579 llvm::StructType *StructTy = RL.getLLVMType(); 1580 unsigned PrevIdx = 0; 1581 ConstantInitBuilder CIBuilder(CGM); 1582 auto DI = Data.begin(); 1583 for (const FieldDecl *FD : RD->fields()) { 1584 unsigned Idx = RL.getLLVMFieldNo(FD); 1585 // Fill the alignment. 1586 for (unsigned I = PrevIdx; I < Idx; ++I) 1587 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1588 PrevIdx = Idx + 1; 1589 Fields.add(*DI); 1590 ++DI; 1591 } 1592 } 1593 1594 template <class... As> 1595 static llvm::GlobalVariable * 1596 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1597 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1598 As &&... Args) { 1599 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1600 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1601 ConstantInitBuilder CIBuilder(CGM); 1602 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1603 buildStructValue(Fields, CGM, RD, RL, Data); 1604 return Fields.finishAndCreateGlobal( 1605 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1606 std::forward<As>(Args)...); 1607 } 1608 1609 template <typename T> 1610 static void 1611 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1612 ArrayRef<llvm::Constant *> Data, 1613 T &Parent) { 1614 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1615 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1616 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1617 buildStructValue(Fields, CGM, RD, RL, Data); 1618 Fields.finishAndAddTo(Parent); 1619 } 1620 1621 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1622 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1623 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1624 FlagsTy FlagsKey(Flags, Reserved2Flags); 1625 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1626 if (!Entry) { 1627 if (!DefaultOpenMPPSource) { 1628 // Initialize default location for psource field of ident_t structure of 1629 // all ident_t objects. Format is ";file;function;line;column;;". 1630 // Taken from 1631 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1632 DefaultOpenMPPSource = 1633 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1634 DefaultOpenMPPSource = 1635 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1636 } 1637 1638 llvm::Constant *Data[] = { 1639 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1640 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1641 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1642 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1643 llvm::GlobalValue *DefaultOpenMPLocation = 1644 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1645 llvm::GlobalValue::PrivateLinkage); 1646 DefaultOpenMPLocation->setUnnamedAddr( 1647 llvm::GlobalValue::UnnamedAddr::Global); 1648 1649 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1650 } 1651 return Address(Entry, Align); 1652 } 1653 1654 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1655 bool AtCurrentPoint) { 1656 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1657 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1658 1659 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1660 if (AtCurrentPoint) { 1661 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1662 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1663 } else { 1664 Elem.second.ServiceInsertPt = 1665 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1666 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1667 } 1668 } 1669 1670 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1671 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1672 if (Elem.second.ServiceInsertPt) { 1673 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1674 Elem.second.ServiceInsertPt = nullptr; 1675 Ptr->eraseFromParent(); 1676 } 1677 } 1678 1679 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1680 SourceLocation Loc, 1681 unsigned Flags) { 1682 Flags |= OMP_IDENT_KMPC; 1683 // If no debug info is generated - return global default location. 1684 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1685 Loc.isInvalid()) 1686 return getOrCreateDefaultLocation(Flags).getPointer(); 1687 1688 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1689 1690 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1691 Address LocValue = Address::invalid(); 1692 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1693 if (I != OpenMPLocThreadIDMap.end()) 1694 LocValue = Address(I->second.DebugLoc, Align); 1695 1696 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1697 // GetOpenMPThreadID was called before this routine. 1698 if (!LocValue.isValid()) { 1699 // Generate "ident_t .kmpc_loc.addr;" 1700 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1701 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1702 Elem.second.DebugLoc = AI.getPointer(); 1703 LocValue = AI; 1704 1705 if (!Elem.second.ServiceInsertPt) 1706 setLocThreadIdInsertPt(CGF); 1707 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1708 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1709 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1710 CGF.getTypeSize(IdentQTy)); 1711 } 1712 1713 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1714 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1715 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1716 LValue PSource = 1717 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1718 1719 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1720 if (OMPDebugLoc == nullptr) { 1721 SmallString<128> Buffer2; 1722 llvm::raw_svector_ostream OS2(Buffer2); 1723 // Build debug location 1724 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1725 OS2 << ";" << PLoc.getFilename() << ";"; 1726 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1727 OS2 << FD->getQualifiedNameAsString(); 1728 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1729 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1730 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1731 } 1732 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1733 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1734 1735 // Our callers always pass this to a runtime function, so for 1736 // convenience, go ahead and return a naked pointer. 1737 return LocValue.getPointer(); 1738 } 1739 1740 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1741 SourceLocation Loc) { 1742 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1743 1744 llvm::Value *ThreadID = nullptr; 1745 // Check whether we've already cached a load of the thread id in this 1746 // function. 1747 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1748 if (I != OpenMPLocThreadIDMap.end()) { 1749 ThreadID = I->second.ThreadID; 1750 if (ThreadID != nullptr) 1751 return ThreadID; 1752 } 1753 // If exceptions are enabled, do not use parameter to avoid possible crash. 1754 if (auto *OMPRegionInfo = 1755 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1756 if (OMPRegionInfo->getThreadIDVariable()) { 1757 // Check if this an outlined function with thread id passed as argument. 1758 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1759 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1760 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1761 !CGF.getLangOpts().CXXExceptions || 1762 CGF.Builder.GetInsertBlock() == TopBlock || 1763 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1764 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1765 TopBlock || 1766 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1767 CGF.Builder.GetInsertBlock()) { 1768 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1769 // If value loaded in entry block, cache it and use it everywhere in 1770 // function. 1771 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1772 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1773 Elem.second.ThreadID = ThreadID; 1774 } 1775 return ThreadID; 1776 } 1777 } 1778 } 1779 1780 // This is not an outlined function region - need to call __kmpc_int32 1781 // kmpc_global_thread_num(ident_t *loc). 1782 // Generate thread id value and cache this value for use across the 1783 // function. 1784 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1785 if (!Elem.second.ServiceInsertPt) 1786 setLocThreadIdInsertPt(CGF); 1787 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1788 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1789 llvm::CallInst *Call = CGF.Builder.CreateCall( 1790 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1791 emitUpdateLocation(CGF, Loc)); 1792 Call->setCallingConv(CGF.getRuntimeCC()); 1793 Elem.second.ThreadID = Call; 1794 return Call; 1795 } 1796 1797 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1798 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1799 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1800 clearLocThreadIdInsertPt(CGF); 1801 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1802 } 1803 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1804 for(const auto *D : FunctionUDRMap[CGF.CurFn]) 1805 UDRMap.erase(D); 1806 FunctionUDRMap.erase(CGF.CurFn); 1807 } 1808 auto I = FunctionUDMMap.find(CGF.CurFn); 1809 if (I != FunctionUDMMap.end()) { 1810 for(const auto *D : I->second) 1811 UDMMap.erase(D); 1812 FunctionUDMMap.erase(I); 1813 } 1814 LastprivateConditionalToTypes.erase(CGF.CurFn); 1815 } 1816 1817 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1818 return IdentTy->getPointerTo(); 1819 } 1820 1821 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1822 if (!Kmpc_MicroTy) { 1823 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1824 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1825 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1826 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1827 } 1828 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1829 } 1830 1831 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1832 llvm::FunctionCallee RTLFn = nullptr; 1833 switch (static_cast<OpenMPRTLFunction>(Function)) { 1834 case OMPRTL__kmpc_fork_call: { 1835 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1836 // microtask, ...); 1837 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1838 getKmpc_MicroPointerTy()}; 1839 auto *FnTy = 1840 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1841 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1842 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1843 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1844 llvm::LLVMContext &Ctx = F->getContext(); 1845 llvm::MDBuilder MDB(Ctx); 1846 // Annotate the callback behavior of the __kmpc_fork_call: 1847 // - The callback callee is argument number 2 (microtask). 1848 // - The first two arguments of the callback callee are unknown (-1). 1849 // - All variadic arguments to the __kmpc_fork_call are passed to the 1850 // callback callee. 1851 F->addMetadata( 1852 llvm::LLVMContext::MD_callback, 1853 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1854 2, {-1, -1}, 1855 /* VarArgsArePassed */ true)})); 1856 } 1857 } 1858 break; 1859 } 1860 case OMPRTL__kmpc_global_thread_num: { 1861 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1862 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1863 auto *FnTy = 1864 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1865 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1866 break; 1867 } 1868 case OMPRTL__kmpc_threadprivate_cached: { 1869 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1870 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1871 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1872 CGM.VoidPtrTy, CGM.SizeTy, 1873 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1874 auto *FnTy = 1875 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1876 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1877 break; 1878 } 1879 case OMPRTL__kmpc_critical: { 1880 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1881 // kmp_critical_name *crit); 1882 llvm::Type *TypeParams[] = { 1883 getIdentTyPointerTy(), CGM.Int32Ty, 1884 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1885 auto *FnTy = 1886 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1887 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1888 break; 1889 } 1890 case OMPRTL__kmpc_critical_with_hint: { 1891 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1892 // kmp_critical_name *crit, uintptr_t hint); 1893 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1894 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1895 CGM.IntPtrTy}; 1896 auto *FnTy = 1897 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1898 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1899 break; 1900 } 1901 case OMPRTL__kmpc_threadprivate_register: { 1902 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1903 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1904 // typedef void *(*kmpc_ctor)(void *); 1905 auto *KmpcCtorTy = 1906 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1907 /*isVarArg*/ false)->getPointerTo(); 1908 // typedef void *(*kmpc_cctor)(void *, void *); 1909 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1910 auto *KmpcCopyCtorTy = 1911 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1912 /*isVarArg*/ false) 1913 ->getPointerTo(); 1914 // typedef void (*kmpc_dtor)(void *); 1915 auto *KmpcDtorTy = 1916 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1917 ->getPointerTo(); 1918 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1919 KmpcCopyCtorTy, KmpcDtorTy}; 1920 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1921 /*isVarArg*/ false); 1922 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1923 break; 1924 } 1925 case OMPRTL__kmpc_end_critical: { 1926 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1927 // kmp_critical_name *crit); 1928 llvm::Type *TypeParams[] = { 1929 getIdentTyPointerTy(), CGM.Int32Ty, 1930 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1931 auto *FnTy = 1932 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1933 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1934 break; 1935 } 1936 case OMPRTL__kmpc_cancel_barrier: { 1937 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1938 // global_tid); 1939 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1940 auto *FnTy = 1941 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1942 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1943 break; 1944 } 1945 case OMPRTL__kmpc_barrier: { 1946 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1947 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1948 auto *FnTy = 1949 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1950 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1951 break; 1952 } 1953 case OMPRTL__kmpc_for_static_fini: { 1954 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1955 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1956 auto *FnTy = 1957 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1958 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1959 break; 1960 } 1961 case OMPRTL__kmpc_push_num_threads: { 1962 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1963 // kmp_int32 num_threads) 1964 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1965 CGM.Int32Ty}; 1966 auto *FnTy = 1967 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1968 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1969 break; 1970 } 1971 case OMPRTL__kmpc_serialized_parallel: { 1972 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1973 // global_tid); 1974 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1975 auto *FnTy = 1976 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1977 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1978 break; 1979 } 1980 case OMPRTL__kmpc_end_serialized_parallel: { 1981 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1982 // global_tid); 1983 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1984 auto *FnTy = 1985 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1986 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1987 break; 1988 } 1989 case OMPRTL__kmpc_flush: { 1990 // Build void __kmpc_flush(ident_t *loc); 1991 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1992 auto *FnTy = 1993 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1994 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1995 break; 1996 } 1997 case OMPRTL__kmpc_master: { 1998 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1999 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2000 auto *FnTy = 2001 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2002 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 2003 break; 2004 } 2005 case OMPRTL__kmpc_end_master: { 2006 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 2007 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2008 auto *FnTy = 2009 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2010 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 2011 break; 2012 } 2013 case OMPRTL__kmpc_omp_taskyield: { 2014 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 2015 // int end_part); 2016 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2017 auto *FnTy = 2018 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2019 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 2020 break; 2021 } 2022 case OMPRTL__kmpc_single: { 2023 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 2024 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2025 auto *FnTy = 2026 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2027 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 2028 break; 2029 } 2030 case OMPRTL__kmpc_end_single: { 2031 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 2032 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2033 auto *FnTy = 2034 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2035 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 2036 break; 2037 } 2038 case OMPRTL__kmpc_omp_task_alloc: { 2039 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 2040 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2041 // kmp_routine_entry_t *task_entry); 2042 assert(KmpRoutineEntryPtrTy != nullptr && 2043 "Type kmp_routine_entry_t must be created."); 2044 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2045 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 2046 // Return void * and then cast to particular kmp_task_t type. 2047 auto *FnTy = 2048 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2049 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 2050 break; 2051 } 2052 case OMPRTL__kmpc_omp_target_task_alloc: { 2053 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 2054 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2055 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 2056 assert(KmpRoutineEntryPtrTy != nullptr && 2057 "Type kmp_routine_entry_t must be created."); 2058 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2059 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 2060 CGM.Int64Ty}; 2061 // Return void * and then cast to particular kmp_task_t type. 2062 auto *FnTy = 2063 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2064 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2065 break; 2066 } 2067 case OMPRTL__kmpc_omp_task: { 2068 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2069 // *new_task); 2070 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2071 CGM.VoidPtrTy}; 2072 auto *FnTy = 2073 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2074 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2075 break; 2076 } 2077 case OMPRTL__kmpc_copyprivate: { 2078 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2079 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2080 // kmp_int32 didit); 2081 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2082 auto *CpyFnTy = 2083 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2084 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2085 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2086 CGM.Int32Ty}; 2087 auto *FnTy = 2088 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2089 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2090 break; 2091 } 2092 case OMPRTL__kmpc_reduce: { 2093 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2094 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2095 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2096 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2097 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2098 /*isVarArg=*/false); 2099 llvm::Type *TypeParams[] = { 2100 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2101 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2102 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2103 auto *FnTy = 2104 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2105 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2106 break; 2107 } 2108 case OMPRTL__kmpc_reduce_nowait: { 2109 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2110 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2111 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2112 // *lck); 2113 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2114 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2115 /*isVarArg=*/false); 2116 llvm::Type *TypeParams[] = { 2117 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2118 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2119 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2120 auto *FnTy = 2121 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2122 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2123 break; 2124 } 2125 case OMPRTL__kmpc_end_reduce: { 2126 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2127 // kmp_critical_name *lck); 2128 llvm::Type *TypeParams[] = { 2129 getIdentTyPointerTy(), CGM.Int32Ty, 2130 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2131 auto *FnTy = 2132 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2133 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2134 break; 2135 } 2136 case OMPRTL__kmpc_end_reduce_nowait: { 2137 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2138 // kmp_critical_name *lck); 2139 llvm::Type *TypeParams[] = { 2140 getIdentTyPointerTy(), CGM.Int32Ty, 2141 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2142 auto *FnTy = 2143 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2144 RTLFn = 2145 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2146 break; 2147 } 2148 case OMPRTL__kmpc_omp_task_begin_if0: { 2149 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2150 // *new_task); 2151 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2152 CGM.VoidPtrTy}; 2153 auto *FnTy = 2154 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2155 RTLFn = 2156 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2157 break; 2158 } 2159 case OMPRTL__kmpc_omp_task_complete_if0: { 2160 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2161 // *new_task); 2162 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2163 CGM.VoidPtrTy}; 2164 auto *FnTy = 2165 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2166 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2167 /*Name=*/"__kmpc_omp_task_complete_if0"); 2168 break; 2169 } 2170 case OMPRTL__kmpc_ordered: { 2171 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2172 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2173 auto *FnTy = 2174 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2175 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2176 break; 2177 } 2178 case OMPRTL__kmpc_end_ordered: { 2179 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2180 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2181 auto *FnTy = 2182 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2183 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2184 break; 2185 } 2186 case OMPRTL__kmpc_omp_taskwait: { 2187 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2188 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2189 auto *FnTy = 2190 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2191 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2192 break; 2193 } 2194 case OMPRTL__kmpc_taskgroup: { 2195 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2196 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2197 auto *FnTy = 2198 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2199 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2200 break; 2201 } 2202 case OMPRTL__kmpc_end_taskgroup: { 2203 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2204 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2205 auto *FnTy = 2206 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2207 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2208 break; 2209 } 2210 case OMPRTL__kmpc_push_proc_bind: { 2211 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2212 // int proc_bind) 2213 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2214 auto *FnTy = 2215 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2216 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2217 break; 2218 } 2219 case OMPRTL__kmpc_omp_task_with_deps: { 2220 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2221 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2222 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2223 llvm::Type *TypeParams[] = { 2224 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2225 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2226 auto *FnTy = 2227 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2228 RTLFn = 2229 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2230 break; 2231 } 2232 case OMPRTL__kmpc_omp_wait_deps: { 2233 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2234 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2235 // kmp_depend_info_t *noalias_dep_list); 2236 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2237 CGM.Int32Ty, CGM.VoidPtrTy, 2238 CGM.Int32Ty, CGM.VoidPtrTy}; 2239 auto *FnTy = 2240 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2241 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2242 break; 2243 } 2244 case OMPRTL__kmpc_cancellationpoint: { 2245 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2246 // global_tid, kmp_int32 cncl_kind) 2247 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2248 auto *FnTy = 2249 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2250 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2251 break; 2252 } 2253 case OMPRTL__kmpc_cancel: { 2254 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2255 // kmp_int32 cncl_kind) 2256 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2257 auto *FnTy = 2258 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2259 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2260 break; 2261 } 2262 case OMPRTL__kmpc_push_num_teams: { 2263 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2264 // kmp_int32 num_teams, kmp_int32 num_threads) 2265 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2266 CGM.Int32Ty}; 2267 auto *FnTy = 2268 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2269 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2270 break; 2271 } 2272 case OMPRTL__kmpc_fork_teams: { 2273 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2274 // microtask, ...); 2275 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2276 getKmpc_MicroPointerTy()}; 2277 auto *FnTy = 2278 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2279 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2280 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2281 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2282 llvm::LLVMContext &Ctx = F->getContext(); 2283 llvm::MDBuilder MDB(Ctx); 2284 // Annotate the callback behavior of the __kmpc_fork_teams: 2285 // - The callback callee is argument number 2 (microtask). 2286 // - The first two arguments of the callback callee are unknown (-1). 2287 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2288 // callback callee. 2289 F->addMetadata( 2290 llvm::LLVMContext::MD_callback, 2291 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2292 2, {-1, -1}, 2293 /* VarArgsArePassed */ true)})); 2294 } 2295 } 2296 break; 2297 } 2298 case OMPRTL__kmpc_taskloop: { 2299 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2300 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2301 // sched, kmp_uint64 grainsize, void *task_dup); 2302 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2303 CGM.IntTy, 2304 CGM.VoidPtrTy, 2305 CGM.IntTy, 2306 CGM.Int64Ty->getPointerTo(), 2307 CGM.Int64Ty->getPointerTo(), 2308 CGM.Int64Ty, 2309 CGM.IntTy, 2310 CGM.IntTy, 2311 CGM.Int64Ty, 2312 CGM.VoidPtrTy}; 2313 auto *FnTy = 2314 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2315 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2316 break; 2317 } 2318 case OMPRTL__kmpc_doacross_init: { 2319 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2320 // num_dims, struct kmp_dim *dims); 2321 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2322 CGM.Int32Ty, 2323 CGM.Int32Ty, 2324 CGM.VoidPtrTy}; 2325 auto *FnTy = 2326 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2327 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2328 break; 2329 } 2330 case OMPRTL__kmpc_doacross_fini: { 2331 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2332 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2333 auto *FnTy = 2334 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2335 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2336 break; 2337 } 2338 case OMPRTL__kmpc_doacross_post: { 2339 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2340 // *vec); 2341 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2342 CGM.Int64Ty->getPointerTo()}; 2343 auto *FnTy = 2344 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2345 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2346 break; 2347 } 2348 case OMPRTL__kmpc_doacross_wait: { 2349 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2350 // *vec); 2351 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2352 CGM.Int64Ty->getPointerTo()}; 2353 auto *FnTy = 2354 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2355 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2356 break; 2357 } 2358 case OMPRTL__kmpc_task_reduction_init: { 2359 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2360 // *data); 2361 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2362 auto *FnTy = 2363 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2364 RTLFn = 2365 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2366 break; 2367 } 2368 case OMPRTL__kmpc_task_reduction_get_th_data: { 2369 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2370 // *d); 2371 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2372 auto *FnTy = 2373 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2374 RTLFn = CGM.CreateRuntimeFunction( 2375 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2376 break; 2377 } 2378 case OMPRTL__kmpc_alloc: { 2379 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2380 // al); omp_allocator_handle_t type is void *. 2381 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2382 auto *FnTy = 2383 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2384 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2385 break; 2386 } 2387 case OMPRTL__kmpc_free: { 2388 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2389 // al); omp_allocator_handle_t type is void *. 2390 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2391 auto *FnTy = 2392 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2393 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2394 break; 2395 } 2396 case OMPRTL__kmpc_push_target_tripcount: { 2397 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2398 // size); 2399 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2400 llvm::FunctionType *FnTy = 2401 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2402 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2403 break; 2404 } 2405 case OMPRTL__tgt_target: { 2406 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2407 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2408 // *arg_types); 2409 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2410 CGM.VoidPtrTy, 2411 CGM.Int32Ty, 2412 CGM.VoidPtrPtrTy, 2413 CGM.VoidPtrPtrTy, 2414 CGM.Int64Ty->getPointerTo(), 2415 CGM.Int64Ty->getPointerTo()}; 2416 auto *FnTy = 2417 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2418 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2419 break; 2420 } 2421 case OMPRTL__tgt_target_nowait: { 2422 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2423 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2424 // int64_t *arg_types); 2425 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2426 CGM.VoidPtrTy, 2427 CGM.Int32Ty, 2428 CGM.VoidPtrPtrTy, 2429 CGM.VoidPtrPtrTy, 2430 CGM.Int64Ty->getPointerTo(), 2431 CGM.Int64Ty->getPointerTo()}; 2432 auto *FnTy = 2433 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2434 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2435 break; 2436 } 2437 case OMPRTL__tgt_target_teams: { 2438 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2439 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2440 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2441 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2442 CGM.VoidPtrTy, 2443 CGM.Int32Ty, 2444 CGM.VoidPtrPtrTy, 2445 CGM.VoidPtrPtrTy, 2446 CGM.Int64Ty->getPointerTo(), 2447 CGM.Int64Ty->getPointerTo(), 2448 CGM.Int32Ty, 2449 CGM.Int32Ty}; 2450 auto *FnTy = 2451 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2452 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2453 break; 2454 } 2455 case OMPRTL__tgt_target_teams_nowait: { 2456 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2457 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2458 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2459 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2460 CGM.VoidPtrTy, 2461 CGM.Int32Ty, 2462 CGM.VoidPtrPtrTy, 2463 CGM.VoidPtrPtrTy, 2464 CGM.Int64Ty->getPointerTo(), 2465 CGM.Int64Ty->getPointerTo(), 2466 CGM.Int32Ty, 2467 CGM.Int32Ty}; 2468 auto *FnTy = 2469 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2470 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2471 break; 2472 } 2473 case OMPRTL__tgt_register_requires: { 2474 // Build void __tgt_register_requires(int64_t flags); 2475 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2476 auto *FnTy = 2477 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2478 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2479 break; 2480 } 2481 case OMPRTL__tgt_target_data_begin: { 2482 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2483 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2484 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2485 CGM.Int32Ty, 2486 CGM.VoidPtrPtrTy, 2487 CGM.VoidPtrPtrTy, 2488 CGM.Int64Ty->getPointerTo(), 2489 CGM.Int64Ty->getPointerTo()}; 2490 auto *FnTy = 2491 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2492 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2493 break; 2494 } 2495 case OMPRTL__tgt_target_data_begin_nowait: { 2496 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2497 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2498 // *arg_types); 2499 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2500 CGM.Int32Ty, 2501 CGM.VoidPtrPtrTy, 2502 CGM.VoidPtrPtrTy, 2503 CGM.Int64Ty->getPointerTo(), 2504 CGM.Int64Ty->getPointerTo()}; 2505 auto *FnTy = 2506 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2507 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2508 break; 2509 } 2510 case OMPRTL__tgt_target_data_end: { 2511 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2512 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2513 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2514 CGM.Int32Ty, 2515 CGM.VoidPtrPtrTy, 2516 CGM.VoidPtrPtrTy, 2517 CGM.Int64Ty->getPointerTo(), 2518 CGM.Int64Ty->getPointerTo()}; 2519 auto *FnTy = 2520 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2521 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2522 break; 2523 } 2524 case OMPRTL__tgt_target_data_end_nowait: { 2525 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2526 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2527 // *arg_types); 2528 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2529 CGM.Int32Ty, 2530 CGM.VoidPtrPtrTy, 2531 CGM.VoidPtrPtrTy, 2532 CGM.Int64Ty->getPointerTo(), 2533 CGM.Int64Ty->getPointerTo()}; 2534 auto *FnTy = 2535 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2536 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2537 break; 2538 } 2539 case OMPRTL__tgt_target_data_update: { 2540 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2541 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2542 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2543 CGM.Int32Ty, 2544 CGM.VoidPtrPtrTy, 2545 CGM.VoidPtrPtrTy, 2546 CGM.Int64Ty->getPointerTo(), 2547 CGM.Int64Ty->getPointerTo()}; 2548 auto *FnTy = 2549 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2550 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2551 break; 2552 } 2553 case OMPRTL__tgt_target_data_update_nowait: { 2554 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2555 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2556 // *arg_types); 2557 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2558 CGM.Int32Ty, 2559 CGM.VoidPtrPtrTy, 2560 CGM.VoidPtrPtrTy, 2561 CGM.Int64Ty->getPointerTo(), 2562 CGM.Int64Ty->getPointerTo()}; 2563 auto *FnTy = 2564 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2565 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2566 break; 2567 } 2568 case OMPRTL__tgt_mapper_num_components: { 2569 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2570 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2571 auto *FnTy = 2572 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2573 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2574 break; 2575 } 2576 case OMPRTL__tgt_push_mapper_component: { 2577 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2578 // *base, void *begin, int64_t size, int64_t type); 2579 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2580 CGM.Int64Ty, CGM.Int64Ty}; 2581 auto *FnTy = 2582 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2583 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2584 break; 2585 } 2586 } 2587 assert(RTLFn && "Unable to find OpenMP runtime function"); 2588 return RTLFn; 2589 } 2590 2591 llvm::FunctionCallee 2592 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2593 assert((IVSize == 32 || IVSize == 64) && 2594 "IV size is not compatible with the omp runtime"); 2595 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2596 : "__kmpc_for_static_init_4u") 2597 : (IVSigned ? "__kmpc_for_static_init_8" 2598 : "__kmpc_for_static_init_8u"); 2599 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2600 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2601 llvm::Type *TypeParams[] = { 2602 getIdentTyPointerTy(), // loc 2603 CGM.Int32Ty, // tid 2604 CGM.Int32Ty, // schedtype 2605 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2606 PtrTy, // p_lower 2607 PtrTy, // p_upper 2608 PtrTy, // p_stride 2609 ITy, // incr 2610 ITy // chunk 2611 }; 2612 auto *FnTy = 2613 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2614 return CGM.CreateRuntimeFunction(FnTy, Name); 2615 } 2616 2617 llvm::FunctionCallee 2618 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2619 assert((IVSize == 32 || IVSize == 64) && 2620 "IV size is not compatible with the omp runtime"); 2621 StringRef Name = 2622 IVSize == 32 2623 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2624 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2625 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2626 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2627 CGM.Int32Ty, // tid 2628 CGM.Int32Ty, // schedtype 2629 ITy, // lower 2630 ITy, // upper 2631 ITy, // stride 2632 ITy // chunk 2633 }; 2634 auto *FnTy = 2635 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2636 return CGM.CreateRuntimeFunction(FnTy, Name); 2637 } 2638 2639 llvm::FunctionCallee 2640 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2641 assert((IVSize == 32 || IVSize == 64) && 2642 "IV size is not compatible with the omp runtime"); 2643 StringRef Name = 2644 IVSize == 32 2645 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2646 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2647 llvm::Type *TypeParams[] = { 2648 getIdentTyPointerTy(), // loc 2649 CGM.Int32Ty, // tid 2650 }; 2651 auto *FnTy = 2652 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2653 return CGM.CreateRuntimeFunction(FnTy, Name); 2654 } 2655 2656 llvm::FunctionCallee 2657 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2658 assert((IVSize == 32 || IVSize == 64) && 2659 "IV size is not compatible with the omp runtime"); 2660 StringRef Name = 2661 IVSize == 32 2662 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2663 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2664 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2665 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2666 llvm::Type *TypeParams[] = { 2667 getIdentTyPointerTy(), // loc 2668 CGM.Int32Ty, // tid 2669 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2670 PtrTy, // p_lower 2671 PtrTy, // p_upper 2672 PtrTy // p_stride 2673 }; 2674 auto *FnTy = 2675 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2676 return CGM.CreateRuntimeFunction(FnTy, Name); 2677 } 2678 2679 /// Obtain information that uniquely identifies a target entry. This 2680 /// consists of the file and device IDs as well as line number associated with 2681 /// the relevant entry source location. 2682 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2683 unsigned &DeviceID, unsigned &FileID, 2684 unsigned &LineNum) { 2685 SourceManager &SM = C.getSourceManager(); 2686 2687 // The loc should be always valid and have a file ID (the user cannot use 2688 // #pragma directives in macros) 2689 2690 assert(Loc.isValid() && "Source location is expected to be always valid."); 2691 2692 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2693 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2694 2695 llvm::sys::fs::UniqueID ID; 2696 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2697 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2698 << PLoc.getFilename() << EC.message(); 2699 2700 DeviceID = ID.getDevice(); 2701 FileID = ID.getFile(); 2702 LineNum = PLoc.getLine(); 2703 } 2704 2705 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2706 if (CGM.getLangOpts().OpenMPSimd) 2707 return Address::invalid(); 2708 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2709 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2710 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2711 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2712 HasRequiresUnifiedSharedMemory))) { 2713 SmallString<64> PtrName; 2714 { 2715 llvm::raw_svector_ostream OS(PtrName); 2716 OS << CGM.getMangledName(GlobalDecl(VD)); 2717 if (!VD->isExternallyVisible()) { 2718 unsigned DeviceID, FileID, Line; 2719 getTargetEntryUniqueInfo(CGM.getContext(), 2720 VD->getCanonicalDecl()->getBeginLoc(), 2721 DeviceID, FileID, Line); 2722 OS << llvm::format("_%x", FileID); 2723 } 2724 OS << "_decl_tgt_ref_ptr"; 2725 } 2726 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2727 if (!Ptr) { 2728 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2729 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2730 PtrName); 2731 2732 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2733 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2734 2735 if (!CGM.getLangOpts().OpenMPIsDevice) 2736 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2737 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2738 } 2739 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2740 } 2741 return Address::invalid(); 2742 } 2743 2744 llvm::Constant * 2745 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2746 assert(!CGM.getLangOpts().OpenMPUseTLS || 2747 !CGM.getContext().getTargetInfo().isTLSSupported()); 2748 // Lookup the entry, lazily creating it if necessary. 2749 std::string Suffix = getName({"cache", ""}); 2750 return getOrCreateInternalVariable( 2751 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2752 } 2753 2754 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2755 const VarDecl *VD, 2756 Address VDAddr, 2757 SourceLocation Loc) { 2758 if (CGM.getLangOpts().OpenMPUseTLS && 2759 CGM.getContext().getTargetInfo().isTLSSupported()) 2760 return VDAddr; 2761 2762 llvm::Type *VarTy = VDAddr.getElementType(); 2763 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2764 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2765 CGM.Int8PtrTy), 2766 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2767 getOrCreateThreadPrivateCache(VD)}; 2768 return Address(CGF.EmitRuntimeCall( 2769 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2770 VDAddr.getAlignment()); 2771 } 2772 2773 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2774 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2775 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2776 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2777 // library. 2778 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2779 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2780 OMPLoc); 2781 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2782 // to register constructor/destructor for variable. 2783 llvm::Value *Args[] = { 2784 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2785 Ctor, CopyCtor, Dtor}; 2786 CGF.EmitRuntimeCall( 2787 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2788 } 2789 2790 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2791 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2792 bool PerformInit, CodeGenFunction *CGF) { 2793 if (CGM.getLangOpts().OpenMPUseTLS && 2794 CGM.getContext().getTargetInfo().isTLSSupported()) 2795 return nullptr; 2796 2797 VD = VD->getDefinition(CGM.getContext()); 2798 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2799 QualType ASTTy = VD->getType(); 2800 2801 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2802 const Expr *Init = VD->getAnyInitializer(); 2803 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2804 // Generate function that re-emits the declaration's initializer into the 2805 // threadprivate copy of the variable VD 2806 CodeGenFunction CtorCGF(CGM); 2807 FunctionArgList Args; 2808 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2809 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2810 ImplicitParamDecl::Other); 2811 Args.push_back(&Dst); 2812 2813 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2814 CGM.getContext().VoidPtrTy, Args); 2815 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2816 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2817 llvm::Function *Fn = 2818 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2819 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2820 Args, Loc, Loc); 2821 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2822 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2823 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2824 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2825 Arg = CtorCGF.Builder.CreateElementBitCast( 2826 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2827 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2828 /*IsInitializer=*/true); 2829 ArgVal = CtorCGF.EmitLoadOfScalar( 2830 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2831 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2832 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2833 CtorCGF.FinishFunction(); 2834 Ctor = Fn; 2835 } 2836 if (VD->getType().isDestructedType() != QualType::DK_none) { 2837 // Generate function that emits destructor call for the threadprivate copy 2838 // of the variable VD 2839 CodeGenFunction DtorCGF(CGM); 2840 FunctionArgList Args; 2841 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2842 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2843 ImplicitParamDecl::Other); 2844 Args.push_back(&Dst); 2845 2846 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2847 CGM.getContext().VoidTy, Args); 2848 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2849 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2850 llvm::Function *Fn = 2851 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2852 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2853 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2854 Loc, Loc); 2855 // Create a scope with an artificial location for the body of this function. 2856 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2857 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2858 DtorCGF.GetAddrOfLocalVar(&Dst), 2859 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2860 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2861 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2862 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2863 DtorCGF.FinishFunction(); 2864 Dtor = Fn; 2865 } 2866 // Do not emit init function if it is not required. 2867 if (!Ctor && !Dtor) 2868 return nullptr; 2869 2870 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2871 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2872 /*isVarArg=*/false) 2873 ->getPointerTo(); 2874 // Copying constructor for the threadprivate variable. 2875 // Must be NULL - reserved by runtime, but currently it requires that this 2876 // parameter is always NULL. Otherwise it fires assertion. 2877 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2878 if (Ctor == nullptr) { 2879 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2880 /*isVarArg=*/false) 2881 ->getPointerTo(); 2882 Ctor = llvm::Constant::getNullValue(CtorTy); 2883 } 2884 if (Dtor == nullptr) { 2885 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2886 /*isVarArg=*/false) 2887 ->getPointerTo(); 2888 Dtor = llvm::Constant::getNullValue(DtorTy); 2889 } 2890 if (!CGF) { 2891 auto *InitFunctionTy = 2892 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2893 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2894 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2895 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2896 CodeGenFunction InitCGF(CGM); 2897 FunctionArgList ArgList; 2898 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2899 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2900 Loc, Loc); 2901 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2902 InitCGF.FinishFunction(); 2903 return InitFunction; 2904 } 2905 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2906 } 2907 return nullptr; 2908 } 2909 2910 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2911 llvm::GlobalVariable *Addr, 2912 bool PerformInit) { 2913 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2914 !CGM.getLangOpts().OpenMPIsDevice) 2915 return false; 2916 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2917 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2918 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2919 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2920 HasRequiresUnifiedSharedMemory)) 2921 return CGM.getLangOpts().OpenMPIsDevice; 2922 VD = VD->getDefinition(CGM.getContext()); 2923 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2924 return CGM.getLangOpts().OpenMPIsDevice; 2925 2926 QualType ASTTy = VD->getType(); 2927 2928 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2929 // Produce the unique prefix to identify the new target regions. We use 2930 // the source location of the variable declaration which we know to not 2931 // conflict with any target region. 2932 unsigned DeviceID; 2933 unsigned FileID; 2934 unsigned Line; 2935 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2936 SmallString<128> Buffer, Out; 2937 { 2938 llvm::raw_svector_ostream OS(Buffer); 2939 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2940 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2941 } 2942 2943 const Expr *Init = VD->getAnyInitializer(); 2944 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2945 llvm::Constant *Ctor; 2946 llvm::Constant *ID; 2947 if (CGM.getLangOpts().OpenMPIsDevice) { 2948 // Generate function that re-emits the declaration's initializer into 2949 // the threadprivate copy of the variable VD 2950 CodeGenFunction CtorCGF(CGM); 2951 2952 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2953 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2954 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2955 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2956 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2957 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2958 FunctionArgList(), Loc, Loc); 2959 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2960 CtorCGF.EmitAnyExprToMem(Init, 2961 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2962 Init->getType().getQualifiers(), 2963 /*IsInitializer=*/true); 2964 CtorCGF.FinishFunction(); 2965 Ctor = Fn; 2966 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2967 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2968 } else { 2969 Ctor = new llvm::GlobalVariable( 2970 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2971 llvm::GlobalValue::PrivateLinkage, 2972 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2973 ID = Ctor; 2974 } 2975 2976 // Register the information for the entry associated with the constructor. 2977 Out.clear(); 2978 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2979 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2980 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2981 } 2982 if (VD->getType().isDestructedType() != QualType::DK_none) { 2983 llvm::Constant *Dtor; 2984 llvm::Constant *ID; 2985 if (CGM.getLangOpts().OpenMPIsDevice) { 2986 // Generate function that emits destructor call for the threadprivate 2987 // copy of the variable VD 2988 CodeGenFunction DtorCGF(CGM); 2989 2990 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2991 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2992 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2993 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2994 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2995 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2996 FunctionArgList(), Loc, Loc); 2997 // Create a scope with an artificial location for the body of this 2998 // function. 2999 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 3000 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 3001 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 3002 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 3003 DtorCGF.FinishFunction(); 3004 Dtor = Fn; 3005 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 3006 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 3007 } else { 3008 Dtor = new llvm::GlobalVariable( 3009 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 3010 llvm::GlobalValue::PrivateLinkage, 3011 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 3012 ID = Dtor; 3013 } 3014 // Register the information for the entry associated with the destructor. 3015 Out.clear(); 3016 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 3017 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 3018 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 3019 } 3020 return CGM.getLangOpts().OpenMPIsDevice; 3021 } 3022 3023 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 3024 QualType VarType, 3025 StringRef Name) { 3026 std::string Suffix = getName({"artificial", ""}); 3027 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 3028 llvm::Value *GAddr = 3029 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 3030 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 3031 CGM.getTarget().isTLSSupported()) { 3032 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 3033 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 3034 } 3035 std::string CacheSuffix = getName({"cache", ""}); 3036 llvm::Value *Args[] = { 3037 emitUpdateLocation(CGF, SourceLocation()), 3038 getThreadID(CGF, SourceLocation()), 3039 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 3040 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 3041 /*isSigned=*/false), 3042 getOrCreateInternalVariable( 3043 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 3044 return Address( 3045 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3046 CGF.EmitRuntimeCall( 3047 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3048 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3049 CGM.getContext().getTypeAlignInChars(VarType)); 3050 } 3051 3052 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 3053 const RegionCodeGenTy &ThenGen, 3054 const RegionCodeGenTy &ElseGen) { 3055 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3056 3057 // If the condition constant folds and can be elided, try to avoid emitting 3058 // the condition and the dead arm of the if/else. 3059 bool CondConstant; 3060 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3061 if (CondConstant) 3062 ThenGen(CGF); 3063 else 3064 ElseGen(CGF); 3065 return; 3066 } 3067 3068 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3069 // emit the conditional branch. 3070 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3071 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3072 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3073 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3074 3075 // Emit the 'then' code. 3076 CGF.EmitBlock(ThenBlock); 3077 ThenGen(CGF); 3078 CGF.EmitBranch(ContBlock); 3079 // Emit the 'else' code if present. 3080 // There is no need to emit line number for unconditional branch. 3081 (void)ApplyDebugLocation::CreateEmpty(CGF); 3082 CGF.EmitBlock(ElseBlock); 3083 ElseGen(CGF); 3084 // There is no need to emit line number for unconditional branch. 3085 (void)ApplyDebugLocation::CreateEmpty(CGF); 3086 CGF.EmitBranch(ContBlock); 3087 // Emit the continuation block for code after the if. 3088 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3089 } 3090 3091 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3092 llvm::Function *OutlinedFn, 3093 ArrayRef<llvm::Value *> CapturedVars, 3094 const Expr *IfCond) { 3095 if (!CGF.HaveInsertPoint()) 3096 return; 3097 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3098 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3099 PrePostActionTy &) { 3100 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3101 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3102 llvm::Value *Args[] = { 3103 RTLoc, 3104 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3105 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3106 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3107 RealArgs.append(std::begin(Args), std::end(Args)); 3108 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3109 3110 llvm::FunctionCallee RTLFn = 3111 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3112 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3113 }; 3114 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3115 PrePostActionTy &) { 3116 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3117 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3118 // Build calls: 3119 // __kmpc_serialized_parallel(&Loc, GTid); 3120 llvm::Value *Args[] = {RTLoc, ThreadID}; 3121 CGF.EmitRuntimeCall( 3122 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3123 3124 // OutlinedFn(>id, &zero_bound, CapturedStruct); 3125 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 3126 Address ZeroAddrBound = 3127 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3128 /*Name=*/".bound.zero.addr"); 3129 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 3130 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3131 // ThreadId for serialized parallels is 0. 3132 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 3133 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 3134 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3135 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3136 3137 // __kmpc_end_serialized_parallel(&Loc, GTid); 3138 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3139 CGF.EmitRuntimeCall( 3140 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3141 EndArgs); 3142 }; 3143 if (IfCond) { 3144 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 3145 } else { 3146 RegionCodeGenTy ThenRCG(ThenGen); 3147 ThenRCG(CGF); 3148 } 3149 } 3150 3151 // If we're inside an (outlined) parallel region, use the region info's 3152 // thread-ID variable (it is passed in a first argument of the outlined function 3153 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3154 // regular serial code region, get thread ID by calling kmp_int32 3155 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3156 // return the address of that temp. 3157 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3158 SourceLocation Loc) { 3159 if (auto *OMPRegionInfo = 3160 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3161 if (OMPRegionInfo->getThreadIDVariable()) 3162 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 3163 3164 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3165 QualType Int32Ty = 3166 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3167 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3168 CGF.EmitStoreOfScalar(ThreadID, 3169 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3170 3171 return ThreadIDTemp; 3172 } 3173 3174 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3175 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3176 SmallString<256> Buffer; 3177 llvm::raw_svector_ostream Out(Buffer); 3178 Out << Name; 3179 StringRef RuntimeName = Out.str(); 3180 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3181 if (Elem.second) { 3182 assert(Elem.second->getType()->getPointerElementType() == Ty && 3183 "OMP internal variable has different type than requested"); 3184 return &*Elem.second; 3185 } 3186 3187 return Elem.second = new llvm::GlobalVariable( 3188 CGM.getModule(), Ty, /*IsConstant*/ false, 3189 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3190 Elem.first(), /*InsertBefore=*/nullptr, 3191 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3192 } 3193 3194 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3195 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3196 std::string Name = getName({Prefix, "var"}); 3197 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3198 } 3199 3200 namespace { 3201 /// Common pre(post)-action for different OpenMP constructs. 3202 class CommonActionTy final : public PrePostActionTy { 3203 llvm::FunctionCallee EnterCallee; 3204 ArrayRef<llvm::Value *> EnterArgs; 3205 llvm::FunctionCallee ExitCallee; 3206 ArrayRef<llvm::Value *> ExitArgs; 3207 bool Conditional; 3208 llvm::BasicBlock *ContBlock = nullptr; 3209 3210 public: 3211 CommonActionTy(llvm::FunctionCallee EnterCallee, 3212 ArrayRef<llvm::Value *> EnterArgs, 3213 llvm::FunctionCallee ExitCallee, 3214 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3215 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3216 ExitArgs(ExitArgs), Conditional(Conditional) {} 3217 void Enter(CodeGenFunction &CGF) override { 3218 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3219 if (Conditional) { 3220 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3221 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3222 ContBlock = CGF.createBasicBlock("omp_if.end"); 3223 // Generate the branch (If-stmt) 3224 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3225 CGF.EmitBlock(ThenBlock); 3226 } 3227 } 3228 void Done(CodeGenFunction &CGF) { 3229 // Emit the rest of blocks/branches 3230 CGF.EmitBranch(ContBlock); 3231 CGF.EmitBlock(ContBlock, true); 3232 } 3233 void Exit(CodeGenFunction &CGF) override { 3234 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3235 } 3236 }; 3237 } // anonymous namespace 3238 3239 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3240 StringRef CriticalName, 3241 const RegionCodeGenTy &CriticalOpGen, 3242 SourceLocation Loc, const Expr *Hint) { 3243 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3244 // CriticalOpGen(); 3245 // __kmpc_end_critical(ident_t *, gtid, Lock); 3246 // Prepare arguments and build a call to __kmpc_critical 3247 if (!CGF.HaveInsertPoint()) 3248 return; 3249 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3250 getCriticalRegionLock(CriticalName)}; 3251 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3252 std::end(Args)); 3253 if (Hint) { 3254 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3255 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3256 } 3257 CommonActionTy Action( 3258 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3259 : OMPRTL__kmpc_critical), 3260 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3261 CriticalOpGen.setAction(Action); 3262 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3263 } 3264 3265 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3266 const RegionCodeGenTy &MasterOpGen, 3267 SourceLocation Loc) { 3268 if (!CGF.HaveInsertPoint()) 3269 return; 3270 // if(__kmpc_master(ident_t *, gtid)) { 3271 // MasterOpGen(); 3272 // __kmpc_end_master(ident_t *, gtid); 3273 // } 3274 // Prepare arguments and build a call to __kmpc_master 3275 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3276 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3277 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3278 /*Conditional=*/true); 3279 MasterOpGen.setAction(Action); 3280 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3281 Action.Done(CGF); 3282 } 3283 3284 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3285 SourceLocation Loc) { 3286 if (!CGF.HaveInsertPoint()) 3287 return; 3288 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3289 llvm::Value *Args[] = { 3290 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3291 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3292 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3293 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3294 Region->emitUntiedSwitch(CGF); 3295 } 3296 3297 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3298 const RegionCodeGenTy &TaskgroupOpGen, 3299 SourceLocation Loc) { 3300 if (!CGF.HaveInsertPoint()) 3301 return; 3302 // __kmpc_taskgroup(ident_t *, gtid); 3303 // TaskgroupOpGen(); 3304 // __kmpc_end_taskgroup(ident_t *, gtid); 3305 // Prepare arguments and build a call to __kmpc_taskgroup 3306 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3307 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3308 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3309 Args); 3310 TaskgroupOpGen.setAction(Action); 3311 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3312 } 3313 3314 /// Given an array of pointers to variables, project the address of a 3315 /// given variable. 3316 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3317 unsigned Index, const VarDecl *Var) { 3318 // Pull out the pointer to the variable. 3319 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3320 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3321 3322 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3323 Addr = CGF.Builder.CreateElementBitCast( 3324 Addr, CGF.ConvertTypeForMem(Var->getType())); 3325 return Addr; 3326 } 3327 3328 static llvm::Value *emitCopyprivateCopyFunction( 3329 CodeGenModule &CGM, llvm::Type *ArgsType, 3330 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3331 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3332 SourceLocation Loc) { 3333 ASTContext &C = CGM.getContext(); 3334 // void copy_func(void *LHSArg, void *RHSArg); 3335 FunctionArgList Args; 3336 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3337 ImplicitParamDecl::Other); 3338 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3339 ImplicitParamDecl::Other); 3340 Args.push_back(&LHSArg); 3341 Args.push_back(&RHSArg); 3342 const auto &CGFI = 3343 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3344 std::string Name = 3345 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3346 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3347 llvm::GlobalValue::InternalLinkage, Name, 3348 &CGM.getModule()); 3349 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3350 Fn->setDoesNotRecurse(); 3351 CodeGenFunction CGF(CGM); 3352 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3353 // Dest = (void*[n])(LHSArg); 3354 // Src = (void*[n])(RHSArg); 3355 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3356 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3357 ArgsType), CGF.getPointerAlign()); 3358 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3359 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3360 ArgsType), CGF.getPointerAlign()); 3361 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3362 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3363 // ... 3364 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3365 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3366 const auto *DestVar = 3367 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3368 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3369 3370 const auto *SrcVar = 3371 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3372 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3373 3374 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3375 QualType Type = VD->getType(); 3376 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3377 } 3378 CGF.FinishFunction(); 3379 return Fn; 3380 } 3381 3382 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3383 const RegionCodeGenTy &SingleOpGen, 3384 SourceLocation Loc, 3385 ArrayRef<const Expr *> CopyprivateVars, 3386 ArrayRef<const Expr *> SrcExprs, 3387 ArrayRef<const Expr *> DstExprs, 3388 ArrayRef<const Expr *> AssignmentOps) { 3389 if (!CGF.HaveInsertPoint()) 3390 return; 3391 assert(CopyprivateVars.size() == SrcExprs.size() && 3392 CopyprivateVars.size() == DstExprs.size() && 3393 CopyprivateVars.size() == AssignmentOps.size()); 3394 ASTContext &C = CGM.getContext(); 3395 // int32 did_it = 0; 3396 // if(__kmpc_single(ident_t *, gtid)) { 3397 // SingleOpGen(); 3398 // __kmpc_end_single(ident_t *, gtid); 3399 // did_it = 1; 3400 // } 3401 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3402 // <copy_func>, did_it); 3403 3404 Address DidIt = Address::invalid(); 3405 if (!CopyprivateVars.empty()) { 3406 // int32 did_it = 0; 3407 QualType KmpInt32Ty = 3408 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3409 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3410 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3411 } 3412 // Prepare arguments and build a call to __kmpc_single 3413 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3414 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3415 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3416 /*Conditional=*/true); 3417 SingleOpGen.setAction(Action); 3418 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3419 if (DidIt.isValid()) { 3420 // did_it = 1; 3421 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3422 } 3423 Action.Done(CGF); 3424 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3425 // <copy_func>, did_it); 3426 if (DidIt.isValid()) { 3427 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3428 QualType CopyprivateArrayTy = C.getConstantArrayType( 3429 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3430 /*IndexTypeQuals=*/0); 3431 // Create a list of all private variables for copyprivate. 3432 Address CopyprivateList = 3433 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3434 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3435 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3436 CGF.Builder.CreateStore( 3437 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3438 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 3439 CGF.VoidPtrTy), 3440 Elem); 3441 } 3442 // Build function that copies private values from single region to all other 3443 // threads in the corresponding parallel region. 3444 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3445 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3446 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3447 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3448 Address CL = 3449 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3450 CGF.VoidPtrTy); 3451 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3452 llvm::Value *Args[] = { 3453 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3454 getThreadID(CGF, Loc), // i32 <gtid> 3455 BufSize, // size_t <buf_size> 3456 CL.getPointer(), // void *<copyprivate list> 3457 CpyFn, // void (*) (void *, void *) <copy_func> 3458 DidItVal // i32 did_it 3459 }; 3460 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3461 } 3462 } 3463 3464 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3465 const RegionCodeGenTy &OrderedOpGen, 3466 SourceLocation Loc, bool IsThreads) { 3467 if (!CGF.HaveInsertPoint()) 3468 return; 3469 // __kmpc_ordered(ident_t *, gtid); 3470 // OrderedOpGen(); 3471 // __kmpc_end_ordered(ident_t *, gtid); 3472 // Prepare arguments and build a call to __kmpc_ordered 3473 if (IsThreads) { 3474 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3475 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3476 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3477 Args); 3478 OrderedOpGen.setAction(Action); 3479 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3480 return; 3481 } 3482 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3483 } 3484 3485 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3486 unsigned Flags; 3487 if (Kind == OMPD_for) 3488 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3489 else if (Kind == OMPD_sections) 3490 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3491 else if (Kind == OMPD_single) 3492 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3493 else if (Kind == OMPD_barrier) 3494 Flags = OMP_IDENT_BARRIER_EXPL; 3495 else 3496 Flags = OMP_IDENT_BARRIER_IMPL; 3497 return Flags; 3498 } 3499 3500 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3501 CodeGenFunction &CGF, const OMPLoopDirective &S, 3502 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3503 // Check if the loop directive is actually a doacross loop directive. In this 3504 // case choose static, 1 schedule. 3505 if (llvm::any_of( 3506 S.getClausesOfKind<OMPOrderedClause>(), 3507 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3508 ScheduleKind = OMPC_SCHEDULE_static; 3509 // Chunk size is 1 in this case. 3510 llvm::APInt ChunkSize(32, 1); 3511 ChunkExpr = IntegerLiteral::Create( 3512 CGF.getContext(), ChunkSize, 3513 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3514 SourceLocation()); 3515 } 3516 } 3517 3518 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3519 OpenMPDirectiveKind Kind, bool EmitChecks, 3520 bool ForceSimpleCall) { 3521 // Check if we should use the OMPBuilder 3522 auto *OMPRegionInfo = 3523 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 3524 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3525 if (OMPBuilder) { 3526 CGF.Builder.restoreIP(OMPBuilder->CreateBarrier( 3527 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 3528 return; 3529 } 3530 3531 if (!CGF.HaveInsertPoint()) 3532 return; 3533 // Build call __kmpc_cancel_barrier(loc, thread_id); 3534 // Build call __kmpc_barrier(loc, thread_id); 3535 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3536 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3537 // thread_id); 3538 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3539 getThreadID(CGF, Loc)}; 3540 if (OMPRegionInfo) { 3541 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3542 llvm::Value *Result = CGF.EmitRuntimeCall( 3543 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3544 if (EmitChecks) { 3545 // if (__kmpc_cancel_barrier()) { 3546 // exit from construct; 3547 // } 3548 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3549 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3550 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3551 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3552 CGF.EmitBlock(ExitBB); 3553 // exit from construct; 3554 CodeGenFunction::JumpDest CancelDestination = 3555 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3556 CGF.EmitBranchThroughCleanup(CancelDestination); 3557 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3558 } 3559 return; 3560 } 3561 } 3562 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3563 } 3564 3565 /// Map the OpenMP loop schedule to the runtime enumeration. 3566 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3567 bool Chunked, bool Ordered) { 3568 switch (ScheduleKind) { 3569 case OMPC_SCHEDULE_static: 3570 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3571 : (Ordered ? OMP_ord_static : OMP_sch_static); 3572 case OMPC_SCHEDULE_dynamic: 3573 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3574 case OMPC_SCHEDULE_guided: 3575 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3576 case OMPC_SCHEDULE_runtime: 3577 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3578 case OMPC_SCHEDULE_auto: 3579 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3580 case OMPC_SCHEDULE_unknown: 3581 assert(!Chunked && "chunk was specified but schedule kind not known"); 3582 return Ordered ? OMP_ord_static : OMP_sch_static; 3583 } 3584 llvm_unreachable("Unexpected runtime schedule"); 3585 } 3586 3587 /// Map the OpenMP distribute schedule to the runtime enumeration. 3588 static OpenMPSchedType 3589 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3590 // only static is allowed for dist_schedule 3591 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3592 } 3593 3594 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3595 bool Chunked) const { 3596 OpenMPSchedType Schedule = 3597 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3598 return Schedule == OMP_sch_static; 3599 } 3600 3601 bool CGOpenMPRuntime::isStaticNonchunked( 3602 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3603 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3604 return Schedule == OMP_dist_sch_static; 3605 } 3606 3607 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3608 bool Chunked) const { 3609 OpenMPSchedType Schedule = 3610 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3611 return Schedule == OMP_sch_static_chunked; 3612 } 3613 3614 bool CGOpenMPRuntime::isStaticChunked( 3615 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3616 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3617 return Schedule == OMP_dist_sch_static_chunked; 3618 } 3619 3620 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3621 OpenMPSchedType Schedule = 3622 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3623 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3624 return Schedule != OMP_sch_static; 3625 } 3626 3627 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3628 OpenMPScheduleClauseModifier M1, 3629 OpenMPScheduleClauseModifier M2) { 3630 int Modifier = 0; 3631 switch (M1) { 3632 case OMPC_SCHEDULE_MODIFIER_monotonic: 3633 Modifier = OMP_sch_modifier_monotonic; 3634 break; 3635 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3636 Modifier = OMP_sch_modifier_nonmonotonic; 3637 break; 3638 case OMPC_SCHEDULE_MODIFIER_simd: 3639 if (Schedule == OMP_sch_static_chunked) 3640 Schedule = OMP_sch_static_balanced_chunked; 3641 break; 3642 case OMPC_SCHEDULE_MODIFIER_last: 3643 case OMPC_SCHEDULE_MODIFIER_unknown: 3644 break; 3645 } 3646 switch (M2) { 3647 case OMPC_SCHEDULE_MODIFIER_monotonic: 3648 Modifier = OMP_sch_modifier_monotonic; 3649 break; 3650 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3651 Modifier = OMP_sch_modifier_nonmonotonic; 3652 break; 3653 case OMPC_SCHEDULE_MODIFIER_simd: 3654 if (Schedule == OMP_sch_static_chunked) 3655 Schedule = OMP_sch_static_balanced_chunked; 3656 break; 3657 case OMPC_SCHEDULE_MODIFIER_last: 3658 case OMPC_SCHEDULE_MODIFIER_unknown: 3659 break; 3660 } 3661 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3662 // If the static schedule kind is specified or if the ordered clause is 3663 // specified, and if the nonmonotonic modifier is not specified, the effect is 3664 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3665 // modifier is specified, the effect is as if the nonmonotonic modifier is 3666 // specified. 3667 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3668 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3669 Schedule == OMP_sch_static_balanced_chunked || 3670 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 3671 Schedule == OMP_dist_sch_static_chunked || 3672 Schedule == OMP_dist_sch_static)) 3673 Modifier = OMP_sch_modifier_nonmonotonic; 3674 } 3675 return Schedule | Modifier; 3676 } 3677 3678 void CGOpenMPRuntime::emitForDispatchInit( 3679 CodeGenFunction &CGF, SourceLocation Loc, 3680 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3681 bool Ordered, const DispatchRTInput &DispatchValues) { 3682 if (!CGF.HaveInsertPoint()) 3683 return; 3684 OpenMPSchedType Schedule = getRuntimeSchedule( 3685 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3686 assert(Ordered || 3687 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3688 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3689 Schedule != OMP_sch_static_balanced_chunked)); 3690 // Call __kmpc_dispatch_init( 3691 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3692 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3693 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3694 3695 // If the Chunk was not specified in the clause - use default value 1. 3696 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3697 : CGF.Builder.getIntN(IVSize, 1); 3698 llvm::Value *Args[] = { 3699 emitUpdateLocation(CGF, Loc), 3700 getThreadID(CGF, Loc), 3701 CGF.Builder.getInt32(addMonoNonMonoModifier( 3702 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3703 DispatchValues.LB, // Lower 3704 DispatchValues.UB, // Upper 3705 CGF.Builder.getIntN(IVSize, 1), // Stride 3706 Chunk // Chunk 3707 }; 3708 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3709 } 3710 3711 static void emitForStaticInitCall( 3712 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3713 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3714 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3715 const CGOpenMPRuntime::StaticRTInput &Values) { 3716 if (!CGF.HaveInsertPoint()) 3717 return; 3718 3719 assert(!Values.Ordered); 3720 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3721 Schedule == OMP_sch_static_balanced_chunked || 3722 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3723 Schedule == OMP_dist_sch_static || 3724 Schedule == OMP_dist_sch_static_chunked); 3725 3726 // Call __kmpc_for_static_init( 3727 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3728 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3729 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3730 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3731 llvm::Value *Chunk = Values.Chunk; 3732 if (Chunk == nullptr) { 3733 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3734 Schedule == OMP_dist_sch_static) && 3735 "expected static non-chunked schedule"); 3736 // If the Chunk was not specified in the clause - use default value 1. 3737 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3738 } else { 3739 assert((Schedule == OMP_sch_static_chunked || 3740 Schedule == OMP_sch_static_balanced_chunked || 3741 Schedule == OMP_ord_static_chunked || 3742 Schedule == OMP_dist_sch_static_chunked) && 3743 "expected static chunked schedule"); 3744 } 3745 llvm::Value *Args[] = { 3746 UpdateLocation, 3747 ThreadId, 3748 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3749 M2)), // Schedule type 3750 Values.IL.getPointer(), // &isLastIter 3751 Values.LB.getPointer(), // &LB 3752 Values.UB.getPointer(), // &UB 3753 Values.ST.getPointer(), // &Stride 3754 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3755 Chunk // Chunk 3756 }; 3757 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3758 } 3759 3760 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3761 SourceLocation Loc, 3762 OpenMPDirectiveKind DKind, 3763 const OpenMPScheduleTy &ScheduleKind, 3764 const StaticRTInput &Values) { 3765 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3766 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3767 assert(isOpenMPWorksharingDirective(DKind) && 3768 "Expected loop-based or sections-based directive."); 3769 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3770 isOpenMPLoopDirective(DKind) 3771 ? OMP_IDENT_WORK_LOOP 3772 : OMP_IDENT_WORK_SECTIONS); 3773 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3774 llvm::FunctionCallee StaticInitFunction = 3775 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3776 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3777 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3778 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3779 } 3780 3781 void CGOpenMPRuntime::emitDistributeStaticInit( 3782 CodeGenFunction &CGF, SourceLocation Loc, 3783 OpenMPDistScheduleClauseKind SchedKind, 3784 const CGOpenMPRuntime::StaticRTInput &Values) { 3785 OpenMPSchedType ScheduleNum = 3786 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3787 llvm::Value *UpdatedLocation = 3788 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3789 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3790 llvm::FunctionCallee StaticInitFunction = 3791 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3792 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3793 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3794 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3795 } 3796 3797 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3798 SourceLocation Loc, 3799 OpenMPDirectiveKind DKind) { 3800 if (!CGF.HaveInsertPoint()) 3801 return; 3802 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3803 llvm::Value *Args[] = { 3804 emitUpdateLocation(CGF, Loc, 3805 isOpenMPDistributeDirective(DKind) 3806 ? OMP_IDENT_WORK_DISTRIBUTE 3807 : isOpenMPLoopDirective(DKind) 3808 ? OMP_IDENT_WORK_LOOP 3809 : OMP_IDENT_WORK_SECTIONS), 3810 getThreadID(CGF, Loc)}; 3811 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3812 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3813 Args); 3814 } 3815 3816 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3817 SourceLocation Loc, 3818 unsigned IVSize, 3819 bool IVSigned) { 3820 if (!CGF.HaveInsertPoint()) 3821 return; 3822 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3823 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3824 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3825 } 3826 3827 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3828 SourceLocation Loc, unsigned IVSize, 3829 bool IVSigned, Address IL, 3830 Address LB, Address UB, 3831 Address ST) { 3832 // Call __kmpc_dispatch_next( 3833 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3834 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3835 // kmp_int[32|64] *p_stride); 3836 llvm::Value *Args[] = { 3837 emitUpdateLocation(CGF, Loc), 3838 getThreadID(CGF, Loc), 3839 IL.getPointer(), // &isLastIter 3840 LB.getPointer(), // &Lower 3841 UB.getPointer(), // &Upper 3842 ST.getPointer() // &Stride 3843 }; 3844 llvm::Value *Call = 3845 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3846 return CGF.EmitScalarConversion( 3847 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3848 CGF.getContext().BoolTy, Loc); 3849 } 3850 3851 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3852 llvm::Value *NumThreads, 3853 SourceLocation Loc) { 3854 if (!CGF.HaveInsertPoint()) 3855 return; 3856 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3857 llvm::Value *Args[] = { 3858 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3859 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3860 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3861 Args); 3862 } 3863 3864 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3865 ProcBindKind ProcBind, 3866 SourceLocation Loc) { 3867 if (!CGF.HaveInsertPoint()) 3868 return; 3869 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 3870 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3871 llvm::Value *Args[] = { 3872 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3873 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 3874 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3875 } 3876 3877 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3878 SourceLocation Loc) { 3879 if (!CGF.HaveInsertPoint()) 3880 return; 3881 // Build call void __kmpc_flush(ident_t *loc) 3882 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3883 emitUpdateLocation(CGF, Loc)); 3884 } 3885 3886 namespace { 3887 /// Indexes of fields for type kmp_task_t. 3888 enum KmpTaskTFields { 3889 /// List of shared variables. 3890 KmpTaskTShareds, 3891 /// Task routine. 3892 KmpTaskTRoutine, 3893 /// Partition id for the untied tasks. 3894 KmpTaskTPartId, 3895 /// Function with call of destructors for private variables. 3896 Data1, 3897 /// Task priority. 3898 Data2, 3899 /// (Taskloops only) Lower bound. 3900 KmpTaskTLowerBound, 3901 /// (Taskloops only) Upper bound. 3902 KmpTaskTUpperBound, 3903 /// (Taskloops only) Stride. 3904 KmpTaskTStride, 3905 /// (Taskloops only) Is last iteration flag. 3906 KmpTaskTLastIter, 3907 /// (Taskloops only) Reduction data. 3908 KmpTaskTReductions, 3909 }; 3910 } // anonymous namespace 3911 3912 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3913 return OffloadEntriesTargetRegion.empty() && 3914 OffloadEntriesDeviceGlobalVar.empty(); 3915 } 3916 3917 /// Initialize target region entry. 3918 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3919 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3920 StringRef ParentName, unsigned LineNum, 3921 unsigned Order) { 3922 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3923 "only required for the device " 3924 "code generation."); 3925 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3926 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3927 OMPTargetRegionEntryTargetRegion); 3928 ++OffloadingEntriesNum; 3929 } 3930 3931 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3932 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3933 StringRef ParentName, unsigned LineNum, 3934 llvm::Constant *Addr, llvm::Constant *ID, 3935 OMPTargetRegionEntryKind Flags) { 3936 // If we are emitting code for a target, the entry is already initialized, 3937 // only has to be registered. 3938 if (CGM.getLangOpts().OpenMPIsDevice) { 3939 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3940 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3941 DiagnosticsEngine::Error, 3942 "Unable to find target region on line '%0' in the device code."); 3943 CGM.getDiags().Report(DiagID) << LineNum; 3944 return; 3945 } 3946 auto &Entry = 3947 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3948 assert(Entry.isValid() && "Entry not initialized!"); 3949 Entry.setAddress(Addr); 3950 Entry.setID(ID); 3951 Entry.setFlags(Flags); 3952 } else { 3953 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3954 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3955 ++OffloadingEntriesNum; 3956 } 3957 } 3958 3959 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3960 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3961 unsigned LineNum) const { 3962 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3963 if (PerDevice == OffloadEntriesTargetRegion.end()) 3964 return false; 3965 auto PerFile = PerDevice->second.find(FileID); 3966 if (PerFile == PerDevice->second.end()) 3967 return false; 3968 auto PerParentName = PerFile->second.find(ParentName); 3969 if (PerParentName == PerFile->second.end()) 3970 return false; 3971 auto PerLine = PerParentName->second.find(LineNum); 3972 if (PerLine == PerParentName->second.end()) 3973 return false; 3974 // Fail if this entry is already registered. 3975 if (PerLine->second.getAddress() || PerLine->second.getID()) 3976 return false; 3977 return true; 3978 } 3979 3980 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3981 const OffloadTargetRegionEntryInfoActTy &Action) { 3982 // Scan all target region entries and perform the provided action. 3983 for (const auto &D : OffloadEntriesTargetRegion) 3984 for (const auto &F : D.second) 3985 for (const auto &P : F.second) 3986 for (const auto &L : P.second) 3987 Action(D.first, F.first, P.first(), L.first, L.second); 3988 } 3989 3990 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3991 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3992 OMPTargetGlobalVarEntryKind Flags, 3993 unsigned Order) { 3994 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3995 "only required for the device " 3996 "code generation."); 3997 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3998 ++OffloadingEntriesNum; 3999 } 4000 4001 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4002 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 4003 CharUnits VarSize, 4004 OMPTargetGlobalVarEntryKind Flags, 4005 llvm::GlobalValue::LinkageTypes Linkage) { 4006 if (CGM.getLangOpts().OpenMPIsDevice) { 4007 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4008 assert(Entry.isValid() && Entry.getFlags() == Flags && 4009 "Entry not initialized!"); 4010 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4011 "Resetting with the new address."); 4012 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 4013 if (Entry.getVarSize().isZero()) { 4014 Entry.setVarSize(VarSize); 4015 Entry.setLinkage(Linkage); 4016 } 4017 return; 4018 } 4019 Entry.setVarSize(VarSize); 4020 Entry.setLinkage(Linkage); 4021 Entry.setAddress(Addr); 4022 } else { 4023 if (hasDeviceGlobalVarEntryInfo(VarName)) { 4024 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4025 assert(Entry.isValid() && Entry.getFlags() == Flags && 4026 "Entry not initialized!"); 4027 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4028 "Resetting with the new address."); 4029 if (Entry.getVarSize().isZero()) { 4030 Entry.setVarSize(VarSize); 4031 Entry.setLinkage(Linkage); 4032 } 4033 return; 4034 } 4035 OffloadEntriesDeviceGlobalVar.try_emplace( 4036 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 4037 ++OffloadingEntriesNum; 4038 } 4039 } 4040 4041 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4042 actOnDeviceGlobalVarEntriesInfo( 4043 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4044 // Scan all target region entries and perform the provided action. 4045 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4046 Action(E.getKey(), E.getValue()); 4047 } 4048 4049 void CGOpenMPRuntime::createOffloadEntry( 4050 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4051 llvm::GlobalValue::LinkageTypes Linkage) { 4052 StringRef Name = Addr->getName(); 4053 llvm::Module &M = CGM.getModule(); 4054 llvm::LLVMContext &C = M.getContext(); 4055 4056 // Create constant string with the name. 4057 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4058 4059 std::string StringName = getName({"omp_offloading", "entry_name"}); 4060 auto *Str = new llvm::GlobalVariable( 4061 M, StrPtrInit->getType(), /*isConstant=*/true, 4062 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4063 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4064 4065 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4066 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4067 llvm::ConstantInt::get(CGM.SizeTy, Size), 4068 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4069 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4070 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4071 llvm::GlobalVariable *Entry = createGlobalStruct( 4072 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4073 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4074 4075 // The entry has to be created in the section the linker expects it to be. 4076 Entry->setSection("omp_offloading_entries"); 4077 } 4078 4079 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4080 // Emit the offloading entries and metadata so that the device codegen side 4081 // can easily figure out what to emit. The produced metadata looks like 4082 // this: 4083 // 4084 // !omp_offload.info = !{!1, ...} 4085 // 4086 // Right now we only generate metadata for function that contain target 4087 // regions. 4088 4089 // If we are in simd mode or there are no entries, we don't need to do 4090 // anything. 4091 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4092 return; 4093 4094 llvm::Module &M = CGM.getModule(); 4095 llvm::LLVMContext &C = M.getContext(); 4096 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4097 SourceLocation, StringRef>, 4098 16> 4099 OrderedEntries(OffloadEntriesInfoManager.size()); 4100 llvm::SmallVector<StringRef, 16> ParentFunctions( 4101 OffloadEntriesInfoManager.size()); 4102 4103 // Auxiliary methods to create metadata values and strings. 4104 auto &&GetMDInt = [this](unsigned V) { 4105 return llvm::ConstantAsMetadata::get( 4106 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4107 }; 4108 4109 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4110 4111 // Create the offloading info metadata node. 4112 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4113 4114 // Create function that emits metadata for each target region entry; 4115 auto &&TargetRegionMetadataEmitter = 4116 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4117 &GetMDString]( 4118 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4119 unsigned Line, 4120 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4121 // Generate metadata for target regions. Each entry of this metadata 4122 // contains: 4123 // - Entry 0 -> Kind of this type of metadata (0). 4124 // - Entry 1 -> Device ID of the file where the entry was identified. 4125 // - Entry 2 -> File ID of the file where the entry was identified. 4126 // - Entry 3 -> Mangled name of the function where the entry was 4127 // identified. 4128 // - Entry 4 -> Line in the file where the entry was identified. 4129 // - Entry 5 -> Order the entry was created. 4130 // The first element of the metadata node is the kind. 4131 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4132 GetMDInt(FileID), GetMDString(ParentName), 4133 GetMDInt(Line), GetMDInt(E.getOrder())}; 4134 4135 SourceLocation Loc; 4136 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4137 E = CGM.getContext().getSourceManager().fileinfo_end(); 4138 I != E; ++I) { 4139 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4140 I->getFirst()->getUniqueID().getFile() == FileID) { 4141 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4142 I->getFirst(), Line, 1); 4143 break; 4144 } 4145 } 4146 // Save this entry in the right position of the ordered entries array. 4147 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4148 ParentFunctions[E.getOrder()] = ParentName; 4149 4150 // Add metadata to the named metadata node. 4151 MD->addOperand(llvm::MDNode::get(C, Ops)); 4152 }; 4153 4154 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4155 TargetRegionMetadataEmitter); 4156 4157 // Create function that emits metadata for each device global variable entry; 4158 auto &&DeviceGlobalVarMetadataEmitter = 4159 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4160 MD](StringRef MangledName, 4161 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4162 &E) { 4163 // Generate metadata for global variables. Each entry of this metadata 4164 // contains: 4165 // - Entry 0 -> Kind of this type of metadata (1). 4166 // - Entry 1 -> Mangled name of the variable. 4167 // - Entry 2 -> Declare target kind. 4168 // - Entry 3 -> Order the entry was created. 4169 // The first element of the metadata node is the kind. 4170 llvm::Metadata *Ops[] = { 4171 GetMDInt(E.getKind()), GetMDString(MangledName), 4172 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4173 4174 // Save this entry in the right position of the ordered entries array. 4175 OrderedEntries[E.getOrder()] = 4176 std::make_tuple(&E, SourceLocation(), MangledName); 4177 4178 // Add metadata to the named metadata node. 4179 MD->addOperand(llvm::MDNode::get(C, Ops)); 4180 }; 4181 4182 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4183 DeviceGlobalVarMetadataEmitter); 4184 4185 for (const auto &E : OrderedEntries) { 4186 assert(std::get<0>(E) && "All ordered entries must exist!"); 4187 if (const auto *CE = 4188 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4189 std::get<0>(E))) { 4190 if (!CE->getID() || !CE->getAddress()) { 4191 // Do not blame the entry if the parent funtion is not emitted. 4192 StringRef FnName = ParentFunctions[CE->getOrder()]; 4193 if (!CGM.GetGlobalValue(FnName)) 4194 continue; 4195 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4196 DiagnosticsEngine::Error, 4197 "Offloading entry for target region in %0 is incorrect: either the " 4198 "address or the ID is invalid."); 4199 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4200 continue; 4201 } 4202 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4203 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4204 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4205 OffloadEntryInfoDeviceGlobalVar>( 4206 std::get<0>(E))) { 4207 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4208 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4209 CE->getFlags()); 4210 switch (Flags) { 4211 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4212 if (CGM.getLangOpts().OpenMPIsDevice && 4213 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4214 continue; 4215 if (!CE->getAddress()) { 4216 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4217 DiagnosticsEngine::Error, "Offloading entry for declare target " 4218 "variable %0 is incorrect: the " 4219 "address is invalid."); 4220 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4221 continue; 4222 } 4223 // The vaiable has no definition - no need to add the entry. 4224 if (CE->getVarSize().isZero()) 4225 continue; 4226 break; 4227 } 4228 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4229 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4230 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4231 "Declaret target link address is set."); 4232 if (CGM.getLangOpts().OpenMPIsDevice) 4233 continue; 4234 if (!CE->getAddress()) { 4235 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4236 DiagnosticsEngine::Error, 4237 "Offloading entry for declare target variable is incorrect: the " 4238 "address is invalid."); 4239 CGM.getDiags().Report(DiagID); 4240 continue; 4241 } 4242 break; 4243 } 4244 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4245 CE->getVarSize().getQuantity(), Flags, 4246 CE->getLinkage()); 4247 } else { 4248 llvm_unreachable("Unsupported entry kind."); 4249 } 4250 } 4251 } 4252 4253 /// Loads all the offload entries information from the host IR 4254 /// metadata. 4255 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4256 // If we are in target mode, load the metadata from the host IR. This code has 4257 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4258 4259 if (!CGM.getLangOpts().OpenMPIsDevice) 4260 return; 4261 4262 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4263 return; 4264 4265 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4266 if (auto EC = Buf.getError()) { 4267 CGM.getDiags().Report(diag::err_cannot_open_file) 4268 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4269 return; 4270 } 4271 4272 llvm::LLVMContext C; 4273 auto ME = expectedToErrorOrAndEmitErrors( 4274 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4275 4276 if (auto EC = ME.getError()) { 4277 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4278 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4279 CGM.getDiags().Report(DiagID) 4280 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4281 return; 4282 } 4283 4284 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4285 if (!MD) 4286 return; 4287 4288 for (llvm::MDNode *MN : MD->operands()) { 4289 auto &&GetMDInt = [MN](unsigned Idx) { 4290 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4291 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4292 }; 4293 4294 auto &&GetMDString = [MN](unsigned Idx) { 4295 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4296 return V->getString(); 4297 }; 4298 4299 switch (GetMDInt(0)) { 4300 default: 4301 llvm_unreachable("Unexpected metadata!"); 4302 break; 4303 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4304 OffloadingEntryInfoTargetRegion: 4305 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4306 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4307 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4308 /*Order=*/GetMDInt(5)); 4309 break; 4310 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4311 OffloadingEntryInfoDeviceGlobalVar: 4312 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4313 /*MangledName=*/GetMDString(1), 4314 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4315 /*Flags=*/GetMDInt(2)), 4316 /*Order=*/GetMDInt(3)); 4317 break; 4318 } 4319 } 4320 } 4321 4322 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4323 if (!KmpRoutineEntryPtrTy) { 4324 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4325 ASTContext &C = CGM.getContext(); 4326 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4327 FunctionProtoType::ExtProtoInfo EPI; 4328 KmpRoutineEntryPtrQTy = C.getPointerType( 4329 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4330 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4331 } 4332 } 4333 4334 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4335 // Make sure the type of the entry is already created. This is the type we 4336 // have to create: 4337 // struct __tgt_offload_entry{ 4338 // void *addr; // Pointer to the offload entry info. 4339 // // (function or global) 4340 // char *name; // Name of the function or global. 4341 // size_t size; // Size of the entry info (0 if it a function). 4342 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4343 // int32_t reserved; // Reserved, to use by the runtime library. 4344 // }; 4345 if (TgtOffloadEntryQTy.isNull()) { 4346 ASTContext &C = CGM.getContext(); 4347 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4348 RD->startDefinition(); 4349 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4350 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4351 addFieldToRecordDecl(C, RD, C.getSizeType()); 4352 addFieldToRecordDecl( 4353 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4354 addFieldToRecordDecl( 4355 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4356 RD->completeDefinition(); 4357 RD->addAttr(PackedAttr::CreateImplicit(C)); 4358 TgtOffloadEntryQTy = C.getRecordType(RD); 4359 } 4360 return TgtOffloadEntryQTy; 4361 } 4362 4363 namespace { 4364 struct PrivateHelpersTy { 4365 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4366 const VarDecl *PrivateElemInit) 4367 : Original(Original), PrivateCopy(PrivateCopy), 4368 PrivateElemInit(PrivateElemInit) {} 4369 const VarDecl *Original; 4370 const VarDecl *PrivateCopy; 4371 const VarDecl *PrivateElemInit; 4372 }; 4373 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4374 } // anonymous namespace 4375 4376 static RecordDecl * 4377 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4378 if (!Privates.empty()) { 4379 ASTContext &C = CGM.getContext(); 4380 // Build struct .kmp_privates_t. { 4381 // /* private vars */ 4382 // }; 4383 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4384 RD->startDefinition(); 4385 for (const auto &Pair : Privates) { 4386 const VarDecl *VD = Pair.second.Original; 4387 QualType Type = VD->getType().getNonReferenceType(); 4388 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4389 if (VD->hasAttrs()) { 4390 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4391 E(VD->getAttrs().end()); 4392 I != E; ++I) 4393 FD->addAttr(*I); 4394 } 4395 } 4396 RD->completeDefinition(); 4397 return RD; 4398 } 4399 return nullptr; 4400 } 4401 4402 static RecordDecl * 4403 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4404 QualType KmpInt32Ty, 4405 QualType KmpRoutineEntryPointerQTy) { 4406 ASTContext &C = CGM.getContext(); 4407 // Build struct kmp_task_t { 4408 // void * shareds; 4409 // kmp_routine_entry_t routine; 4410 // kmp_int32 part_id; 4411 // kmp_cmplrdata_t data1; 4412 // kmp_cmplrdata_t data2; 4413 // For taskloops additional fields: 4414 // kmp_uint64 lb; 4415 // kmp_uint64 ub; 4416 // kmp_int64 st; 4417 // kmp_int32 liter; 4418 // void * reductions; 4419 // }; 4420 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4421 UD->startDefinition(); 4422 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4423 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4424 UD->completeDefinition(); 4425 QualType KmpCmplrdataTy = C.getRecordType(UD); 4426 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4427 RD->startDefinition(); 4428 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4429 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4430 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4431 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4432 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4433 if (isOpenMPTaskLoopDirective(Kind)) { 4434 QualType KmpUInt64Ty = 4435 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4436 QualType KmpInt64Ty = 4437 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4438 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4439 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4440 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4441 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4442 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4443 } 4444 RD->completeDefinition(); 4445 return RD; 4446 } 4447 4448 static RecordDecl * 4449 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4450 ArrayRef<PrivateDataTy> Privates) { 4451 ASTContext &C = CGM.getContext(); 4452 // Build struct kmp_task_t_with_privates { 4453 // kmp_task_t task_data; 4454 // .kmp_privates_t. privates; 4455 // }; 4456 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4457 RD->startDefinition(); 4458 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4459 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4460 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4461 RD->completeDefinition(); 4462 return RD; 4463 } 4464 4465 /// Emit a proxy function which accepts kmp_task_t as the second 4466 /// argument. 4467 /// \code 4468 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4469 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4470 /// For taskloops: 4471 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4472 /// tt->reductions, tt->shareds); 4473 /// return 0; 4474 /// } 4475 /// \endcode 4476 static llvm::Function * 4477 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4478 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4479 QualType KmpTaskTWithPrivatesPtrQTy, 4480 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4481 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4482 llvm::Value *TaskPrivatesMap) { 4483 ASTContext &C = CGM.getContext(); 4484 FunctionArgList Args; 4485 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4486 ImplicitParamDecl::Other); 4487 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4488 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4489 ImplicitParamDecl::Other); 4490 Args.push_back(&GtidArg); 4491 Args.push_back(&TaskTypeArg); 4492 const auto &TaskEntryFnInfo = 4493 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4494 llvm::FunctionType *TaskEntryTy = 4495 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4496 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4497 auto *TaskEntry = llvm::Function::Create( 4498 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4499 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4500 TaskEntry->setDoesNotRecurse(); 4501 CodeGenFunction CGF(CGM); 4502 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4503 Loc, Loc); 4504 4505 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4506 // tt, 4507 // For taskloops: 4508 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4509 // tt->task_data.shareds); 4510 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4511 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4512 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4513 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4514 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4515 const auto *KmpTaskTWithPrivatesQTyRD = 4516 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4517 LValue Base = 4518 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4519 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4520 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4521 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4522 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 4523 4524 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4525 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4526 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4527 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4528 CGF.ConvertTypeForMem(SharedsPtrTy)); 4529 4530 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4531 llvm::Value *PrivatesParam; 4532 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4533 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4534 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4535 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 4536 } else { 4537 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4538 } 4539 4540 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4541 TaskPrivatesMap, 4542 CGF.Builder 4543 .CreatePointerBitCastOrAddrSpaceCast( 4544 TDBase.getAddress(CGF), CGF.VoidPtrTy) 4545 .getPointer()}; 4546 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4547 std::end(CommonArgs)); 4548 if (isOpenMPTaskLoopDirective(Kind)) { 4549 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4550 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4551 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4552 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4553 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4554 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4555 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4556 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4557 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4558 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4559 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4560 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4561 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4562 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4563 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4564 CallArgs.push_back(LBParam); 4565 CallArgs.push_back(UBParam); 4566 CallArgs.push_back(StParam); 4567 CallArgs.push_back(LIParam); 4568 CallArgs.push_back(RParam); 4569 } 4570 CallArgs.push_back(SharedsParam); 4571 4572 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4573 CallArgs); 4574 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4575 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4576 CGF.FinishFunction(); 4577 return TaskEntry; 4578 } 4579 4580 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4581 SourceLocation Loc, 4582 QualType KmpInt32Ty, 4583 QualType KmpTaskTWithPrivatesPtrQTy, 4584 QualType KmpTaskTWithPrivatesQTy) { 4585 ASTContext &C = CGM.getContext(); 4586 FunctionArgList Args; 4587 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4588 ImplicitParamDecl::Other); 4589 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4590 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4591 ImplicitParamDecl::Other); 4592 Args.push_back(&GtidArg); 4593 Args.push_back(&TaskTypeArg); 4594 const auto &DestructorFnInfo = 4595 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4596 llvm::FunctionType *DestructorFnTy = 4597 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4598 std::string Name = 4599 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4600 auto *DestructorFn = 4601 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4602 Name, &CGM.getModule()); 4603 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4604 DestructorFnInfo); 4605 DestructorFn->setDoesNotRecurse(); 4606 CodeGenFunction CGF(CGM); 4607 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4608 Args, Loc, Loc); 4609 4610 LValue Base = CGF.EmitLoadOfPointerLValue( 4611 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4612 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4613 const auto *KmpTaskTWithPrivatesQTyRD = 4614 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4615 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4616 Base = CGF.EmitLValueForField(Base, *FI); 4617 for (const auto *Field : 4618 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4619 if (QualType::DestructionKind DtorKind = 4620 Field->getType().isDestructedType()) { 4621 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4622 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 4623 } 4624 } 4625 CGF.FinishFunction(); 4626 return DestructorFn; 4627 } 4628 4629 /// Emit a privates mapping function for correct handling of private and 4630 /// firstprivate variables. 4631 /// \code 4632 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4633 /// **noalias priv1,..., <tyn> **noalias privn) { 4634 /// *priv1 = &.privates.priv1; 4635 /// ...; 4636 /// *privn = &.privates.privn; 4637 /// } 4638 /// \endcode 4639 static llvm::Value * 4640 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4641 ArrayRef<const Expr *> PrivateVars, 4642 ArrayRef<const Expr *> FirstprivateVars, 4643 ArrayRef<const Expr *> LastprivateVars, 4644 QualType PrivatesQTy, 4645 ArrayRef<PrivateDataTy> Privates) { 4646 ASTContext &C = CGM.getContext(); 4647 FunctionArgList Args; 4648 ImplicitParamDecl TaskPrivatesArg( 4649 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4650 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4651 ImplicitParamDecl::Other); 4652 Args.push_back(&TaskPrivatesArg); 4653 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4654 unsigned Counter = 1; 4655 for (const Expr *E : PrivateVars) { 4656 Args.push_back(ImplicitParamDecl::Create( 4657 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4658 C.getPointerType(C.getPointerType(E->getType())) 4659 .withConst() 4660 .withRestrict(), 4661 ImplicitParamDecl::Other)); 4662 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4663 PrivateVarsPos[VD] = Counter; 4664 ++Counter; 4665 } 4666 for (const Expr *E : FirstprivateVars) { 4667 Args.push_back(ImplicitParamDecl::Create( 4668 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4669 C.getPointerType(C.getPointerType(E->getType())) 4670 .withConst() 4671 .withRestrict(), 4672 ImplicitParamDecl::Other)); 4673 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4674 PrivateVarsPos[VD] = Counter; 4675 ++Counter; 4676 } 4677 for (const Expr *E : LastprivateVars) { 4678 Args.push_back(ImplicitParamDecl::Create( 4679 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4680 C.getPointerType(C.getPointerType(E->getType())) 4681 .withConst() 4682 .withRestrict(), 4683 ImplicitParamDecl::Other)); 4684 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4685 PrivateVarsPos[VD] = Counter; 4686 ++Counter; 4687 } 4688 const auto &TaskPrivatesMapFnInfo = 4689 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4690 llvm::FunctionType *TaskPrivatesMapTy = 4691 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4692 std::string Name = 4693 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4694 auto *TaskPrivatesMap = llvm::Function::Create( 4695 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4696 &CGM.getModule()); 4697 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4698 TaskPrivatesMapFnInfo); 4699 if (CGM.getLangOpts().Optimize) { 4700 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4701 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4702 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4703 } 4704 CodeGenFunction CGF(CGM); 4705 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4706 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4707 4708 // *privi = &.privates.privi; 4709 LValue Base = CGF.EmitLoadOfPointerLValue( 4710 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4711 TaskPrivatesArg.getType()->castAs<PointerType>()); 4712 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4713 Counter = 0; 4714 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4715 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4716 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4717 LValue RefLVal = 4718 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4719 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4720 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 4721 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 4722 ++Counter; 4723 } 4724 CGF.FinishFunction(); 4725 return TaskPrivatesMap; 4726 } 4727 4728 /// Emit initialization for private variables in task-based directives. 4729 static void emitPrivatesInit(CodeGenFunction &CGF, 4730 const OMPExecutableDirective &D, 4731 Address KmpTaskSharedsPtr, LValue TDBase, 4732 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4733 QualType SharedsTy, QualType SharedsPtrTy, 4734 const OMPTaskDataTy &Data, 4735 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4736 ASTContext &C = CGF.getContext(); 4737 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4738 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4739 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4740 ? OMPD_taskloop 4741 : OMPD_task; 4742 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4743 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4744 LValue SrcBase; 4745 bool IsTargetTask = 4746 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4747 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4748 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4749 // PointersArray and SizesArray. The original variables for these arrays are 4750 // not captured and we get their addresses explicitly. 4751 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4752 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4753 SrcBase = CGF.MakeAddrLValue( 4754 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4755 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4756 SharedsTy); 4757 } 4758 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4759 for (const PrivateDataTy &Pair : Privates) { 4760 const VarDecl *VD = Pair.second.PrivateCopy; 4761 const Expr *Init = VD->getAnyInitializer(); 4762 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4763 !CGF.isTrivialInitializer(Init)))) { 4764 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4765 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4766 const VarDecl *OriginalVD = Pair.second.Original; 4767 // Check if the variable is the target-based BasePointersArray, 4768 // PointersArray or SizesArray. 4769 LValue SharedRefLValue; 4770 QualType Type = PrivateLValue.getType(); 4771 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4772 if (IsTargetTask && !SharedField) { 4773 assert(isa<ImplicitParamDecl>(OriginalVD) && 4774 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4775 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4776 ->getNumParams() == 0 && 4777 isa<TranslationUnitDecl>( 4778 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4779 ->getDeclContext()) && 4780 "Expected artificial target data variable."); 4781 SharedRefLValue = 4782 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4783 } else { 4784 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4785 SharedRefLValue = CGF.MakeAddrLValue( 4786 Address(SharedRefLValue.getPointer(CGF), 4787 C.getDeclAlign(OriginalVD)), 4788 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4789 SharedRefLValue.getTBAAInfo()); 4790 } 4791 if (Type->isArrayType()) { 4792 // Initialize firstprivate array. 4793 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4794 // Perform simple memcpy. 4795 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4796 } else { 4797 // Initialize firstprivate array using element-by-element 4798 // initialization. 4799 CGF.EmitOMPAggregateAssign( 4800 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 4801 Type, 4802 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4803 Address SrcElement) { 4804 // Clean up any temporaries needed by the initialization. 4805 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4806 InitScope.addPrivate( 4807 Elem, [SrcElement]() -> Address { return SrcElement; }); 4808 (void)InitScope.Privatize(); 4809 // Emit initialization for single element. 4810 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4811 CGF, &CapturesInfo); 4812 CGF.EmitAnyExprToMem(Init, DestElement, 4813 Init->getType().getQualifiers(), 4814 /*IsInitializer=*/false); 4815 }); 4816 } 4817 } else { 4818 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4819 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 4820 return SharedRefLValue.getAddress(CGF); 4821 }); 4822 (void)InitScope.Privatize(); 4823 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4824 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4825 /*capturedByInit=*/false); 4826 } 4827 } else { 4828 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4829 } 4830 } 4831 ++FI; 4832 } 4833 } 4834 4835 /// Check if duplication function is required for taskloops. 4836 static bool checkInitIsRequired(CodeGenFunction &CGF, 4837 ArrayRef<PrivateDataTy> Privates) { 4838 bool InitRequired = false; 4839 for (const PrivateDataTy &Pair : Privates) { 4840 const VarDecl *VD = Pair.second.PrivateCopy; 4841 const Expr *Init = VD->getAnyInitializer(); 4842 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4843 !CGF.isTrivialInitializer(Init)); 4844 if (InitRequired) 4845 break; 4846 } 4847 return InitRequired; 4848 } 4849 4850 4851 /// Emit task_dup function (for initialization of 4852 /// private/firstprivate/lastprivate vars and last_iter flag) 4853 /// \code 4854 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4855 /// lastpriv) { 4856 /// // setup lastprivate flag 4857 /// task_dst->last = lastpriv; 4858 /// // could be constructor calls here... 4859 /// } 4860 /// \endcode 4861 static llvm::Value * 4862 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4863 const OMPExecutableDirective &D, 4864 QualType KmpTaskTWithPrivatesPtrQTy, 4865 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4866 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4867 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4868 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4869 ASTContext &C = CGM.getContext(); 4870 FunctionArgList Args; 4871 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4872 KmpTaskTWithPrivatesPtrQTy, 4873 ImplicitParamDecl::Other); 4874 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4875 KmpTaskTWithPrivatesPtrQTy, 4876 ImplicitParamDecl::Other); 4877 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4878 ImplicitParamDecl::Other); 4879 Args.push_back(&DstArg); 4880 Args.push_back(&SrcArg); 4881 Args.push_back(&LastprivArg); 4882 const auto &TaskDupFnInfo = 4883 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4884 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4885 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4886 auto *TaskDup = llvm::Function::Create( 4887 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4888 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4889 TaskDup->setDoesNotRecurse(); 4890 CodeGenFunction CGF(CGM); 4891 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4892 Loc); 4893 4894 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4895 CGF.GetAddrOfLocalVar(&DstArg), 4896 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4897 // task_dst->liter = lastpriv; 4898 if (WithLastIter) { 4899 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4900 LValue Base = CGF.EmitLValueForField( 4901 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4902 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4903 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4904 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4905 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4906 } 4907 4908 // Emit initial values for private copies (if any). 4909 assert(!Privates.empty()); 4910 Address KmpTaskSharedsPtr = Address::invalid(); 4911 if (!Data.FirstprivateVars.empty()) { 4912 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4913 CGF.GetAddrOfLocalVar(&SrcArg), 4914 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4915 LValue Base = CGF.EmitLValueForField( 4916 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4917 KmpTaskSharedsPtr = Address( 4918 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4919 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4920 KmpTaskTShareds)), 4921 Loc), 4922 CGF.getNaturalTypeAlignment(SharedsTy)); 4923 } 4924 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4925 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4926 CGF.FinishFunction(); 4927 return TaskDup; 4928 } 4929 4930 /// Checks if destructor function is required to be generated. 4931 /// \return true if cleanups are required, false otherwise. 4932 static bool 4933 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4934 bool NeedsCleanup = false; 4935 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4936 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4937 for (const FieldDecl *FD : PrivateRD->fields()) { 4938 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4939 if (NeedsCleanup) 4940 break; 4941 } 4942 return NeedsCleanup; 4943 } 4944 4945 CGOpenMPRuntime::TaskResultTy 4946 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4947 const OMPExecutableDirective &D, 4948 llvm::Function *TaskFunction, QualType SharedsTy, 4949 Address Shareds, const OMPTaskDataTy &Data) { 4950 ASTContext &C = CGM.getContext(); 4951 llvm::SmallVector<PrivateDataTy, 4> Privates; 4952 // Aggregate privates and sort them by the alignment. 4953 auto I = Data.PrivateCopies.begin(); 4954 for (const Expr *E : Data.PrivateVars) { 4955 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4956 Privates.emplace_back( 4957 C.getDeclAlign(VD), 4958 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4959 /*PrivateElemInit=*/nullptr)); 4960 ++I; 4961 } 4962 I = Data.FirstprivateCopies.begin(); 4963 auto IElemInitRef = Data.FirstprivateInits.begin(); 4964 for (const Expr *E : Data.FirstprivateVars) { 4965 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4966 Privates.emplace_back( 4967 C.getDeclAlign(VD), 4968 PrivateHelpersTy( 4969 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4970 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4971 ++I; 4972 ++IElemInitRef; 4973 } 4974 I = Data.LastprivateCopies.begin(); 4975 for (const Expr *E : Data.LastprivateVars) { 4976 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4977 Privates.emplace_back( 4978 C.getDeclAlign(VD), 4979 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4980 /*PrivateElemInit=*/nullptr)); 4981 ++I; 4982 } 4983 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 4984 return L.first > R.first; 4985 }); 4986 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4987 // Build type kmp_routine_entry_t (if not built yet). 4988 emitKmpRoutineEntryT(KmpInt32Ty); 4989 // Build type kmp_task_t (if not built yet). 4990 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 4991 if (SavedKmpTaskloopTQTy.isNull()) { 4992 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4993 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4994 } 4995 KmpTaskTQTy = SavedKmpTaskloopTQTy; 4996 } else { 4997 assert((D.getDirectiveKind() == OMPD_task || 4998 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 4999 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5000 "Expected taskloop, task or target directive"); 5001 if (SavedKmpTaskTQTy.isNull()) { 5002 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5003 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5004 } 5005 KmpTaskTQTy = SavedKmpTaskTQTy; 5006 } 5007 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5008 // Build particular struct kmp_task_t for the given task. 5009 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5010 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5011 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5012 QualType KmpTaskTWithPrivatesPtrQTy = 5013 C.getPointerType(KmpTaskTWithPrivatesQTy); 5014 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5015 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5016 KmpTaskTWithPrivatesTy->getPointerTo(); 5017 llvm::Value *KmpTaskTWithPrivatesTySize = 5018 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5019 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5020 5021 // Emit initial values for private copies (if any). 5022 llvm::Value *TaskPrivatesMap = nullptr; 5023 llvm::Type *TaskPrivatesMapTy = 5024 std::next(TaskFunction->arg_begin(), 3)->getType(); 5025 if (!Privates.empty()) { 5026 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5027 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5028 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5029 FI->getType(), Privates); 5030 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5031 TaskPrivatesMap, TaskPrivatesMapTy); 5032 } else { 5033 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5034 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5035 } 5036 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5037 // kmp_task_t *tt); 5038 llvm::Function *TaskEntry = emitProxyTaskFunction( 5039 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5040 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5041 TaskPrivatesMap); 5042 5043 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5044 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5045 // kmp_routine_entry_t *task_entry); 5046 // Task flags. Format is taken from 5047 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5048 // description of kmp_tasking_flags struct. 5049 enum { 5050 TiedFlag = 0x1, 5051 FinalFlag = 0x2, 5052 DestructorsFlag = 0x8, 5053 PriorityFlag = 0x20 5054 }; 5055 unsigned Flags = Data.Tied ? TiedFlag : 0; 5056 bool NeedsCleanup = false; 5057 if (!Privates.empty()) { 5058 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5059 if (NeedsCleanup) 5060 Flags = Flags | DestructorsFlag; 5061 } 5062 if (Data.Priority.getInt()) 5063 Flags = Flags | PriorityFlag; 5064 llvm::Value *TaskFlags = 5065 Data.Final.getPointer() 5066 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5067 CGF.Builder.getInt32(FinalFlag), 5068 CGF.Builder.getInt32(/*C=*/0)) 5069 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5070 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5071 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5072 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5073 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5074 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5075 TaskEntry, KmpRoutineEntryPtrTy)}; 5076 llvm::Value *NewTask; 5077 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5078 // Check if we have any device clause associated with the directive. 5079 const Expr *Device = nullptr; 5080 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5081 Device = C->getDevice(); 5082 // Emit device ID if any otherwise use default value. 5083 llvm::Value *DeviceID; 5084 if (Device) 5085 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5086 CGF.Int64Ty, /*isSigned=*/true); 5087 else 5088 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5089 AllocArgs.push_back(DeviceID); 5090 NewTask = CGF.EmitRuntimeCall( 5091 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5092 } else { 5093 NewTask = CGF.EmitRuntimeCall( 5094 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5095 } 5096 llvm::Value *NewTaskNewTaskTTy = 5097 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5098 NewTask, KmpTaskTWithPrivatesPtrTy); 5099 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5100 KmpTaskTWithPrivatesQTy); 5101 LValue TDBase = 5102 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5103 // Fill the data in the resulting kmp_task_t record. 5104 // Copy shareds if there are any. 5105 Address KmpTaskSharedsPtr = Address::invalid(); 5106 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5107 KmpTaskSharedsPtr = 5108 Address(CGF.EmitLoadOfScalar( 5109 CGF.EmitLValueForField( 5110 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5111 KmpTaskTShareds)), 5112 Loc), 5113 CGF.getNaturalTypeAlignment(SharedsTy)); 5114 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5115 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5116 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5117 } 5118 // Emit initial values for private copies (if any). 5119 TaskResultTy Result; 5120 if (!Privates.empty()) { 5121 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5122 SharedsTy, SharedsPtrTy, Data, Privates, 5123 /*ForDup=*/false); 5124 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5125 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5126 Result.TaskDupFn = emitTaskDupFunction( 5127 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5128 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5129 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5130 } 5131 } 5132 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5133 enum { Priority = 0, Destructors = 1 }; 5134 // Provide pointer to function with destructors for privates. 5135 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5136 const RecordDecl *KmpCmplrdataUD = 5137 (*FI)->getType()->getAsUnionType()->getDecl(); 5138 if (NeedsCleanup) { 5139 llvm::Value *DestructorFn = emitDestructorsFunction( 5140 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5141 KmpTaskTWithPrivatesQTy); 5142 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5143 LValue DestructorsLV = CGF.EmitLValueForField( 5144 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5145 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5146 DestructorFn, KmpRoutineEntryPtrTy), 5147 DestructorsLV); 5148 } 5149 // Set priority. 5150 if (Data.Priority.getInt()) { 5151 LValue Data2LV = CGF.EmitLValueForField( 5152 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5153 LValue PriorityLV = CGF.EmitLValueForField( 5154 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5155 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5156 } 5157 Result.NewTask = NewTask; 5158 Result.TaskEntry = TaskEntry; 5159 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5160 Result.TDBase = TDBase; 5161 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5162 return Result; 5163 } 5164 5165 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5166 const OMPExecutableDirective &D, 5167 llvm::Function *TaskFunction, 5168 QualType SharedsTy, Address Shareds, 5169 const Expr *IfCond, 5170 const OMPTaskDataTy &Data) { 5171 if (!CGF.HaveInsertPoint()) 5172 return; 5173 5174 TaskResultTy Result = 5175 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5176 llvm::Value *NewTask = Result.NewTask; 5177 llvm::Function *TaskEntry = Result.TaskEntry; 5178 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5179 LValue TDBase = Result.TDBase; 5180 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5181 ASTContext &C = CGM.getContext(); 5182 // Process list of dependences. 5183 Address DependenciesArray = Address::invalid(); 5184 unsigned NumDependencies = Data.Dependences.size(); 5185 if (NumDependencies) { 5186 // Dependence kind for RTL. 5187 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5188 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5189 RecordDecl *KmpDependInfoRD; 5190 QualType FlagsTy = 5191 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5192 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5193 if (KmpDependInfoTy.isNull()) { 5194 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5195 KmpDependInfoRD->startDefinition(); 5196 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5197 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5198 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5199 KmpDependInfoRD->completeDefinition(); 5200 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5201 } else { 5202 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5203 } 5204 // Define type kmp_depend_info[<Dependences.size()>]; 5205 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5206 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5207 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5208 // kmp_depend_info[<Dependences.size()>] deps; 5209 DependenciesArray = 5210 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5211 for (unsigned I = 0; I < NumDependencies; ++I) { 5212 const Expr *E = Data.Dependences[I].second; 5213 LValue Addr = CGF.EmitLValue(E); 5214 llvm::Value *Size; 5215 QualType Ty = E->getType(); 5216 if (const auto *ASE = 5217 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5218 LValue UpAddrLVal = 5219 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5220 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 5221 UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 5222 llvm::Value *LowIntPtr = 5223 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy); 5224 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5225 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5226 } else { 5227 Size = CGF.getTypeSize(Ty); 5228 } 5229 LValue Base = CGF.MakeAddrLValue( 5230 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5231 KmpDependInfoTy); 5232 // deps[i].base_addr = &<Dependences[i].second>; 5233 LValue BaseAddrLVal = CGF.EmitLValueForField( 5234 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5235 CGF.EmitStoreOfScalar( 5236 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy), 5237 BaseAddrLVal); 5238 // deps[i].len = sizeof(<Dependences[i].second>); 5239 LValue LenLVal = CGF.EmitLValueForField( 5240 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5241 CGF.EmitStoreOfScalar(Size, LenLVal); 5242 // deps[i].flags = <Dependences[i].first>; 5243 RTLDependenceKindTy DepKind; 5244 switch (Data.Dependences[I].first) { 5245 case OMPC_DEPEND_in: 5246 DepKind = DepIn; 5247 break; 5248 // Out and InOut dependencies must use the same code. 5249 case OMPC_DEPEND_out: 5250 case OMPC_DEPEND_inout: 5251 DepKind = DepInOut; 5252 break; 5253 case OMPC_DEPEND_mutexinoutset: 5254 DepKind = DepMutexInOutSet; 5255 break; 5256 case OMPC_DEPEND_source: 5257 case OMPC_DEPEND_sink: 5258 case OMPC_DEPEND_unknown: 5259 llvm_unreachable("Unknown task dependence type"); 5260 } 5261 LValue FlagsLVal = CGF.EmitLValueForField( 5262 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5263 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5264 FlagsLVal); 5265 } 5266 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5267 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5268 } 5269 5270 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5271 // libcall. 5272 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5273 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5274 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5275 // list is not empty 5276 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5277 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5278 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5279 llvm::Value *DepTaskArgs[7]; 5280 if (NumDependencies) { 5281 DepTaskArgs[0] = UpLoc; 5282 DepTaskArgs[1] = ThreadID; 5283 DepTaskArgs[2] = NewTask; 5284 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5285 DepTaskArgs[4] = DependenciesArray.getPointer(); 5286 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5287 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5288 } 5289 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5290 &TaskArgs, 5291 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5292 if (!Data.Tied) { 5293 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5294 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5295 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5296 } 5297 if (NumDependencies) { 5298 CGF.EmitRuntimeCall( 5299 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5300 } else { 5301 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5302 TaskArgs); 5303 } 5304 // Check if parent region is untied and build return for untied task; 5305 if (auto *Region = 5306 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5307 Region->emitUntiedSwitch(CGF); 5308 }; 5309 5310 llvm::Value *DepWaitTaskArgs[6]; 5311 if (NumDependencies) { 5312 DepWaitTaskArgs[0] = UpLoc; 5313 DepWaitTaskArgs[1] = ThreadID; 5314 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5315 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5316 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5317 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5318 } 5319 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5320 NumDependencies, &DepWaitTaskArgs, 5321 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5322 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5323 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5324 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5325 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5326 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5327 // is specified. 5328 if (NumDependencies) 5329 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5330 DepWaitTaskArgs); 5331 // Call proxy_task_entry(gtid, new_task); 5332 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5333 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5334 Action.Enter(CGF); 5335 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5336 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5337 OutlinedFnArgs); 5338 }; 5339 5340 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5341 // kmp_task_t *new_task); 5342 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5343 // kmp_task_t *new_task); 5344 RegionCodeGenTy RCG(CodeGen); 5345 CommonActionTy Action( 5346 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5347 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5348 RCG.setAction(Action); 5349 RCG(CGF); 5350 }; 5351 5352 if (IfCond) { 5353 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5354 } else { 5355 RegionCodeGenTy ThenRCG(ThenCodeGen); 5356 ThenRCG(CGF); 5357 } 5358 } 5359 5360 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5361 const OMPLoopDirective &D, 5362 llvm::Function *TaskFunction, 5363 QualType SharedsTy, Address Shareds, 5364 const Expr *IfCond, 5365 const OMPTaskDataTy &Data) { 5366 if (!CGF.HaveInsertPoint()) 5367 return; 5368 TaskResultTy Result = 5369 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5370 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5371 // libcall. 5372 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5373 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5374 // sched, kmp_uint64 grainsize, void *task_dup); 5375 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5376 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5377 llvm::Value *IfVal; 5378 if (IfCond) { 5379 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5380 /*isSigned=*/true); 5381 } else { 5382 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5383 } 5384 5385 LValue LBLVal = CGF.EmitLValueForField( 5386 Result.TDBase, 5387 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5388 const auto *LBVar = 5389 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5390 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5391 LBLVal.getQuals(), 5392 /*IsInitializer=*/true); 5393 LValue UBLVal = CGF.EmitLValueForField( 5394 Result.TDBase, 5395 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5396 const auto *UBVar = 5397 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5398 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5399 UBLVal.getQuals(), 5400 /*IsInitializer=*/true); 5401 LValue StLVal = CGF.EmitLValueForField( 5402 Result.TDBase, 5403 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5404 const auto *StVar = 5405 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5406 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5407 StLVal.getQuals(), 5408 /*IsInitializer=*/true); 5409 // Store reductions address. 5410 LValue RedLVal = CGF.EmitLValueForField( 5411 Result.TDBase, 5412 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5413 if (Data.Reductions) { 5414 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5415 } else { 5416 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5417 CGF.getContext().VoidPtrTy); 5418 } 5419 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5420 llvm::Value *TaskArgs[] = { 5421 UpLoc, 5422 ThreadID, 5423 Result.NewTask, 5424 IfVal, 5425 LBLVal.getPointer(CGF), 5426 UBLVal.getPointer(CGF), 5427 CGF.EmitLoadOfScalar(StLVal, Loc), 5428 llvm::ConstantInt::getSigned( 5429 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5430 llvm::ConstantInt::getSigned( 5431 CGF.IntTy, Data.Schedule.getPointer() 5432 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5433 : NoSchedule), 5434 Data.Schedule.getPointer() 5435 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5436 /*isSigned=*/false) 5437 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5438 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5439 Result.TaskDupFn, CGF.VoidPtrTy) 5440 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5441 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5442 } 5443 5444 /// Emit reduction operation for each element of array (required for 5445 /// array sections) LHS op = RHS. 5446 /// \param Type Type of array. 5447 /// \param LHSVar Variable on the left side of the reduction operation 5448 /// (references element of array in original variable). 5449 /// \param RHSVar Variable on the right side of the reduction operation 5450 /// (references element of array in original variable). 5451 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5452 /// RHSVar. 5453 static void EmitOMPAggregateReduction( 5454 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5455 const VarDecl *RHSVar, 5456 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5457 const Expr *, const Expr *)> &RedOpGen, 5458 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5459 const Expr *UpExpr = nullptr) { 5460 // Perform element-by-element initialization. 5461 QualType ElementTy; 5462 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5463 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5464 5465 // Drill down to the base element type on both arrays. 5466 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5467 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5468 5469 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5470 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5471 // Cast from pointer to array type to pointer to single element. 5472 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5473 // The basic structure here is a while-do loop. 5474 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5475 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5476 llvm::Value *IsEmpty = 5477 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5478 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5479 5480 // Enter the loop body, making that address the current address. 5481 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5482 CGF.EmitBlock(BodyBB); 5483 5484 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5485 5486 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5487 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5488 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5489 Address RHSElementCurrent = 5490 Address(RHSElementPHI, 5491 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5492 5493 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5494 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5495 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5496 Address LHSElementCurrent = 5497 Address(LHSElementPHI, 5498 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5499 5500 // Emit copy. 5501 CodeGenFunction::OMPPrivateScope Scope(CGF); 5502 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5503 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5504 Scope.Privatize(); 5505 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5506 Scope.ForceCleanup(); 5507 5508 // Shift the address forward by one element. 5509 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5510 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5511 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5512 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5513 // Check whether we've reached the end. 5514 llvm::Value *Done = 5515 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5516 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5517 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5518 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5519 5520 // Done. 5521 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5522 } 5523 5524 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5525 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5526 /// UDR combiner function. 5527 static void emitReductionCombiner(CodeGenFunction &CGF, 5528 const Expr *ReductionOp) { 5529 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5530 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5531 if (const auto *DRE = 5532 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5533 if (const auto *DRD = 5534 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5535 std::pair<llvm::Function *, llvm::Function *> Reduction = 5536 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5537 RValue Func = RValue::get(Reduction.first); 5538 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5539 CGF.EmitIgnoredExpr(ReductionOp); 5540 return; 5541 } 5542 CGF.EmitIgnoredExpr(ReductionOp); 5543 } 5544 5545 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5546 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5547 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5548 ArrayRef<const Expr *> ReductionOps) { 5549 ASTContext &C = CGM.getContext(); 5550 5551 // void reduction_func(void *LHSArg, void *RHSArg); 5552 FunctionArgList Args; 5553 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5554 ImplicitParamDecl::Other); 5555 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5556 ImplicitParamDecl::Other); 5557 Args.push_back(&LHSArg); 5558 Args.push_back(&RHSArg); 5559 const auto &CGFI = 5560 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5561 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5562 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5563 llvm::GlobalValue::InternalLinkage, Name, 5564 &CGM.getModule()); 5565 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5566 Fn->setDoesNotRecurse(); 5567 CodeGenFunction CGF(CGM); 5568 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5569 5570 // Dst = (void*[n])(LHSArg); 5571 // Src = (void*[n])(RHSArg); 5572 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5573 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5574 ArgsType), CGF.getPointerAlign()); 5575 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5576 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5577 ArgsType), CGF.getPointerAlign()); 5578 5579 // ... 5580 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5581 // ... 5582 CodeGenFunction::OMPPrivateScope Scope(CGF); 5583 auto IPriv = Privates.begin(); 5584 unsigned Idx = 0; 5585 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5586 const auto *RHSVar = 5587 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5588 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5589 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5590 }); 5591 const auto *LHSVar = 5592 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5593 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5594 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5595 }); 5596 QualType PrivTy = (*IPriv)->getType(); 5597 if (PrivTy->isVariablyModifiedType()) { 5598 // Get array size and emit VLA type. 5599 ++Idx; 5600 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5601 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5602 const VariableArrayType *VLA = 5603 CGF.getContext().getAsVariableArrayType(PrivTy); 5604 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5605 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5606 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5607 CGF.EmitVariablyModifiedType(PrivTy); 5608 } 5609 } 5610 Scope.Privatize(); 5611 IPriv = Privates.begin(); 5612 auto ILHS = LHSExprs.begin(); 5613 auto IRHS = RHSExprs.begin(); 5614 for (const Expr *E : ReductionOps) { 5615 if ((*IPriv)->getType()->isArrayType()) { 5616 // Emit reduction for array section. 5617 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5618 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5619 EmitOMPAggregateReduction( 5620 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5621 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5622 emitReductionCombiner(CGF, E); 5623 }); 5624 } else { 5625 // Emit reduction for array subscript or single variable. 5626 emitReductionCombiner(CGF, E); 5627 } 5628 ++IPriv; 5629 ++ILHS; 5630 ++IRHS; 5631 } 5632 Scope.ForceCleanup(); 5633 CGF.FinishFunction(); 5634 return Fn; 5635 } 5636 5637 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5638 const Expr *ReductionOp, 5639 const Expr *PrivateRef, 5640 const DeclRefExpr *LHS, 5641 const DeclRefExpr *RHS) { 5642 if (PrivateRef->getType()->isArrayType()) { 5643 // Emit reduction for array section. 5644 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5645 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5646 EmitOMPAggregateReduction( 5647 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5648 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5649 emitReductionCombiner(CGF, ReductionOp); 5650 }); 5651 } else { 5652 // Emit reduction for array subscript or single variable. 5653 emitReductionCombiner(CGF, ReductionOp); 5654 } 5655 } 5656 5657 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5658 ArrayRef<const Expr *> Privates, 5659 ArrayRef<const Expr *> LHSExprs, 5660 ArrayRef<const Expr *> RHSExprs, 5661 ArrayRef<const Expr *> ReductionOps, 5662 ReductionOptionsTy Options) { 5663 if (!CGF.HaveInsertPoint()) 5664 return; 5665 5666 bool WithNowait = Options.WithNowait; 5667 bool SimpleReduction = Options.SimpleReduction; 5668 5669 // Next code should be emitted for reduction: 5670 // 5671 // static kmp_critical_name lock = { 0 }; 5672 // 5673 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5674 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5675 // ... 5676 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5677 // *(Type<n>-1*)rhs[<n>-1]); 5678 // } 5679 // 5680 // ... 5681 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5682 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5683 // RedList, reduce_func, &<lock>)) { 5684 // case 1: 5685 // ... 5686 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5687 // ... 5688 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5689 // break; 5690 // case 2: 5691 // ... 5692 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5693 // ... 5694 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5695 // break; 5696 // default:; 5697 // } 5698 // 5699 // if SimpleReduction is true, only the next code is generated: 5700 // ... 5701 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5702 // ... 5703 5704 ASTContext &C = CGM.getContext(); 5705 5706 if (SimpleReduction) { 5707 CodeGenFunction::RunCleanupsScope Scope(CGF); 5708 auto IPriv = Privates.begin(); 5709 auto ILHS = LHSExprs.begin(); 5710 auto IRHS = RHSExprs.begin(); 5711 for (const Expr *E : ReductionOps) { 5712 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5713 cast<DeclRefExpr>(*IRHS)); 5714 ++IPriv; 5715 ++ILHS; 5716 ++IRHS; 5717 } 5718 return; 5719 } 5720 5721 // 1. Build a list of reduction variables. 5722 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5723 auto Size = RHSExprs.size(); 5724 for (const Expr *E : Privates) { 5725 if (E->getType()->isVariablyModifiedType()) 5726 // Reserve place for array size. 5727 ++Size; 5728 } 5729 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5730 QualType ReductionArrayTy = 5731 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5732 /*IndexTypeQuals=*/0); 5733 Address ReductionList = 5734 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5735 auto IPriv = Privates.begin(); 5736 unsigned Idx = 0; 5737 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5738 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5739 CGF.Builder.CreateStore( 5740 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5741 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5742 Elem); 5743 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5744 // Store array size. 5745 ++Idx; 5746 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5747 llvm::Value *Size = CGF.Builder.CreateIntCast( 5748 CGF.getVLASize( 5749 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5750 .NumElts, 5751 CGF.SizeTy, /*isSigned=*/false); 5752 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5753 Elem); 5754 } 5755 } 5756 5757 // 2. Emit reduce_func(). 5758 llvm::Function *ReductionFn = emitReductionFunction( 5759 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5760 LHSExprs, RHSExprs, ReductionOps); 5761 5762 // 3. Create static kmp_critical_name lock = { 0 }; 5763 std::string Name = getName({"reduction"}); 5764 llvm::Value *Lock = getCriticalRegionLock(Name); 5765 5766 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5767 // RedList, reduce_func, &<lock>); 5768 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5769 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5770 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5771 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5772 ReductionList.getPointer(), CGF.VoidPtrTy); 5773 llvm::Value *Args[] = { 5774 IdentTLoc, // ident_t *<loc> 5775 ThreadId, // i32 <gtid> 5776 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5777 ReductionArrayTySize, // size_type sizeof(RedList) 5778 RL, // void *RedList 5779 ReductionFn, // void (*) (void *, void *) <reduce_func> 5780 Lock // kmp_critical_name *&<lock> 5781 }; 5782 llvm::Value *Res = CGF.EmitRuntimeCall( 5783 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5784 : OMPRTL__kmpc_reduce), 5785 Args); 5786 5787 // 5. Build switch(res) 5788 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5789 llvm::SwitchInst *SwInst = 5790 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5791 5792 // 6. Build case 1: 5793 // ... 5794 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5795 // ... 5796 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5797 // break; 5798 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5799 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5800 CGF.EmitBlock(Case1BB); 5801 5802 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5803 llvm::Value *EndArgs[] = { 5804 IdentTLoc, // ident_t *<loc> 5805 ThreadId, // i32 <gtid> 5806 Lock // kmp_critical_name *&<lock> 5807 }; 5808 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5809 CodeGenFunction &CGF, PrePostActionTy &Action) { 5810 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5811 auto IPriv = Privates.begin(); 5812 auto ILHS = LHSExprs.begin(); 5813 auto IRHS = RHSExprs.begin(); 5814 for (const Expr *E : ReductionOps) { 5815 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5816 cast<DeclRefExpr>(*IRHS)); 5817 ++IPriv; 5818 ++ILHS; 5819 ++IRHS; 5820 } 5821 }; 5822 RegionCodeGenTy RCG(CodeGen); 5823 CommonActionTy Action( 5824 nullptr, llvm::None, 5825 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5826 : OMPRTL__kmpc_end_reduce), 5827 EndArgs); 5828 RCG.setAction(Action); 5829 RCG(CGF); 5830 5831 CGF.EmitBranch(DefaultBB); 5832 5833 // 7. Build case 2: 5834 // ... 5835 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5836 // ... 5837 // break; 5838 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5839 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5840 CGF.EmitBlock(Case2BB); 5841 5842 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5843 CodeGenFunction &CGF, PrePostActionTy &Action) { 5844 auto ILHS = LHSExprs.begin(); 5845 auto IRHS = RHSExprs.begin(); 5846 auto IPriv = Privates.begin(); 5847 for (const Expr *E : ReductionOps) { 5848 const Expr *XExpr = nullptr; 5849 const Expr *EExpr = nullptr; 5850 const Expr *UpExpr = nullptr; 5851 BinaryOperatorKind BO = BO_Comma; 5852 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5853 if (BO->getOpcode() == BO_Assign) { 5854 XExpr = BO->getLHS(); 5855 UpExpr = BO->getRHS(); 5856 } 5857 } 5858 // Try to emit update expression as a simple atomic. 5859 const Expr *RHSExpr = UpExpr; 5860 if (RHSExpr) { 5861 // Analyze RHS part of the whole expression. 5862 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5863 RHSExpr->IgnoreParenImpCasts())) { 5864 // If this is a conditional operator, analyze its condition for 5865 // min/max reduction operator. 5866 RHSExpr = ACO->getCond(); 5867 } 5868 if (const auto *BORHS = 5869 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5870 EExpr = BORHS->getRHS(); 5871 BO = BORHS->getOpcode(); 5872 } 5873 } 5874 if (XExpr) { 5875 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5876 auto &&AtomicRedGen = [BO, VD, 5877 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5878 const Expr *EExpr, const Expr *UpExpr) { 5879 LValue X = CGF.EmitLValue(XExpr); 5880 RValue E; 5881 if (EExpr) 5882 E = CGF.EmitAnyExpr(EExpr); 5883 CGF.EmitOMPAtomicSimpleUpdateExpr( 5884 X, E, BO, /*IsXLHSInRHSPart=*/true, 5885 llvm::AtomicOrdering::Monotonic, Loc, 5886 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5887 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5888 PrivateScope.addPrivate( 5889 VD, [&CGF, VD, XRValue, Loc]() { 5890 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5891 CGF.emitOMPSimpleStore( 5892 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5893 VD->getType().getNonReferenceType(), Loc); 5894 return LHSTemp; 5895 }); 5896 (void)PrivateScope.Privatize(); 5897 return CGF.EmitAnyExpr(UpExpr); 5898 }); 5899 }; 5900 if ((*IPriv)->getType()->isArrayType()) { 5901 // Emit atomic reduction for array section. 5902 const auto *RHSVar = 5903 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5904 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5905 AtomicRedGen, XExpr, EExpr, UpExpr); 5906 } else { 5907 // Emit atomic reduction for array subscript or single variable. 5908 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5909 } 5910 } else { 5911 // Emit as a critical region. 5912 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5913 const Expr *, const Expr *) { 5914 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5915 std::string Name = RT.getName({"atomic_reduction"}); 5916 RT.emitCriticalRegion( 5917 CGF, Name, 5918 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5919 Action.Enter(CGF); 5920 emitReductionCombiner(CGF, E); 5921 }, 5922 Loc); 5923 }; 5924 if ((*IPriv)->getType()->isArrayType()) { 5925 const auto *LHSVar = 5926 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5927 const auto *RHSVar = 5928 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5929 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5930 CritRedGen); 5931 } else { 5932 CritRedGen(CGF, nullptr, nullptr, nullptr); 5933 } 5934 } 5935 ++ILHS; 5936 ++IRHS; 5937 ++IPriv; 5938 } 5939 }; 5940 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5941 if (!WithNowait) { 5942 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5943 llvm::Value *EndArgs[] = { 5944 IdentTLoc, // ident_t *<loc> 5945 ThreadId, // i32 <gtid> 5946 Lock // kmp_critical_name *&<lock> 5947 }; 5948 CommonActionTy Action(nullptr, llvm::None, 5949 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 5950 EndArgs); 5951 AtomicRCG.setAction(Action); 5952 AtomicRCG(CGF); 5953 } else { 5954 AtomicRCG(CGF); 5955 } 5956 5957 CGF.EmitBranch(DefaultBB); 5958 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5959 } 5960 5961 /// Generates unique name for artificial threadprivate variables. 5962 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5963 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5964 const Expr *Ref) { 5965 SmallString<256> Buffer; 5966 llvm::raw_svector_ostream Out(Buffer); 5967 const clang::DeclRefExpr *DE; 5968 const VarDecl *D = ::getBaseDecl(Ref, DE); 5969 if (!D) 5970 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5971 D = D->getCanonicalDecl(); 5972 std::string Name = CGM.getOpenMPRuntime().getName( 5973 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5974 Out << Prefix << Name << "_" 5975 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5976 return std::string(Out.str()); 5977 } 5978 5979 /// Emits reduction initializer function: 5980 /// \code 5981 /// void @.red_init(void* %arg) { 5982 /// %0 = bitcast void* %arg to <type>* 5983 /// store <type> <init>, <type>* %0 5984 /// ret void 5985 /// } 5986 /// \endcode 5987 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 5988 SourceLocation Loc, 5989 ReductionCodeGen &RCG, unsigned N) { 5990 ASTContext &C = CGM.getContext(); 5991 FunctionArgList Args; 5992 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5993 ImplicitParamDecl::Other); 5994 Args.emplace_back(&Param); 5995 const auto &FnInfo = 5996 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5997 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5998 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 5999 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6000 Name, &CGM.getModule()); 6001 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6002 Fn->setDoesNotRecurse(); 6003 CodeGenFunction CGF(CGM); 6004 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6005 Address PrivateAddr = CGF.EmitLoadOfPointer( 6006 CGF.GetAddrOfLocalVar(&Param), 6007 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6008 llvm::Value *Size = nullptr; 6009 // If the size of the reduction item is non-constant, load it from global 6010 // threadprivate variable. 6011 if (RCG.getSizes(N).second) { 6012 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6013 CGF, CGM.getContext().getSizeType(), 6014 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6015 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6016 CGM.getContext().getSizeType(), Loc); 6017 } 6018 RCG.emitAggregateType(CGF, N, Size); 6019 LValue SharedLVal; 6020 // If initializer uses initializer from declare reduction construct, emit a 6021 // pointer to the address of the original reduction item (reuired by reduction 6022 // initializer) 6023 if (RCG.usesReductionInitializer(N)) { 6024 Address SharedAddr = 6025 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6026 CGF, CGM.getContext().VoidPtrTy, 6027 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6028 SharedAddr = CGF.EmitLoadOfPointer( 6029 SharedAddr, 6030 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6031 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6032 } else { 6033 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6034 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6035 CGM.getContext().VoidPtrTy); 6036 } 6037 // Emit the initializer: 6038 // %0 = bitcast void* %arg to <type>* 6039 // store <type> <init>, <type>* %0 6040 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6041 [](CodeGenFunction &) { return false; }); 6042 CGF.FinishFunction(); 6043 return Fn; 6044 } 6045 6046 /// Emits reduction combiner function: 6047 /// \code 6048 /// void @.red_comb(void* %arg0, void* %arg1) { 6049 /// %lhs = bitcast void* %arg0 to <type>* 6050 /// %rhs = bitcast void* %arg1 to <type>* 6051 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6052 /// store <type> %2, <type>* %lhs 6053 /// ret void 6054 /// } 6055 /// \endcode 6056 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6057 SourceLocation Loc, 6058 ReductionCodeGen &RCG, unsigned N, 6059 const Expr *ReductionOp, 6060 const Expr *LHS, const Expr *RHS, 6061 const Expr *PrivateRef) { 6062 ASTContext &C = CGM.getContext(); 6063 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6064 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6065 FunctionArgList Args; 6066 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6067 C.VoidPtrTy, ImplicitParamDecl::Other); 6068 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6069 ImplicitParamDecl::Other); 6070 Args.emplace_back(&ParamInOut); 6071 Args.emplace_back(&ParamIn); 6072 const auto &FnInfo = 6073 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6074 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6075 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6076 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6077 Name, &CGM.getModule()); 6078 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6079 Fn->setDoesNotRecurse(); 6080 CodeGenFunction CGF(CGM); 6081 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6082 llvm::Value *Size = nullptr; 6083 // If the size of the reduction item is non-constant, load it from global 6084 // threadprivate variable. 6085 if (RCG.getSizes(N).second) { 6086 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6087 CGF, CGM.getContext().getSizeType(), 6088 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6089 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6090 CGM.getContext().getSizeType(), Loc); 6091 } 6092 RCG.emitAggregateType(CGF, N, Size); 6093 // Remap lhs and rhs variables to the addresses of the function arguments. 6094 // %lhs = bitcast void* %arg0 to <type>* 6095 // %rhs = bitcast void* %arg1 to <type>* 6096 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6097 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6098 // Pull out the pointer to the variable. 6099 Address PtrAddr = CGF.EmitLoadOfPointer( 6100 CGF.GetAddrOfLocalVar(&ParamInOut), 6101 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6102 return CGF.Builder.CreateElementBitCast( 6103 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6104 }); 6105 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6106 // Pull out the pointer to the variable. 6107 Address PtrAddr = CGF.EmitLoadOfPointer( 6108 CGF.GetAddrOfLocalVar(&ParamIn), 6109 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6110 return CGF.Builder.CreateElementBitCast( 6111 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6112 }); 6113 PrivateScope.Privatize(); 6114 // Emit the combiner body: 6115 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6116 // store <type> %2, <type>* %lhs 6117 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6118 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6119 cast<DeclRefExpr>(RHS)); 6120 CGF.FinishFunction(); 6121 return Fn; 6122 } 6123 6124 /// Emits reduction finalizer function: 6125 /// \code 6126 /// void @.red_fini(void* %arg) { 6127 /// %0 = bitcast void* %arg to <type>* 6128 /// <destroy>(<type>* %0) 6129 /// ret void 6130 /// } 6131 /// \endcode 6132 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6133 SourceLocation Loc, 6134 ReductionCodeGen &RCG, unsigned N) { 6135 if (!RCG.needCleanups(N)) 6136 return nullptr; 6137 ASTContext &C = CGM.getContext(); 6138 FunctionArgList Args; 6139 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6140 ImplicitParamDecl::Other); 6141 Args.emplace_back(&Param); 6142 const auto &FnInfo = 6143 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6144 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6145 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6146 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6147 Name, &CGM.getModule()); 6148 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6149 Fn->setDoesNotRecurse(); 6150 CodeGenFunction CGF(CGM); 6151 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6152 Address PrivateAddr = CGF.EmitLoadOfPointer( 6153 CGF.GetAddrOfLocalVar(&Param), 6154 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6155 llvm::Value *Size = nullptr; 6156 // If the size of the reduction item is non-constant, load it from global 6157 // threadprivate variable. 6158 if (RCG.getSizes(N).second) { 6159 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6160 CGF, CGM.getContext().getSizeType(), 6161 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6162 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6163 CGM.getContext().getSizeType(), Loc); 6164 } 6165 RCG.emitAggregateType(CGF, N, Size); 6166 // Emit the finalizer body: 6167 // <destroy>(<type>* %0) 6168 RCG.emitCleanups(CGF, N, PrivateAddr); 6169 CGF.FinishFunction(Loc); 6170 return Fn; 6171 } 6172 6173 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6174 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6175 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6176 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6177 return nullptr; 6178 6179 // Build typedef struct: 6180 // kmp_task_red_input { 6181 // void *reduce_shar; // shared reduction item 6182 // size_t reduce_size; // size of data item 6183 // void *reduce_init; // data initialization routine 6184 // void *reduce_fini; // data finalization routine 6185 // void *reduce_comb; // data combiner routine 6186 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6187 // } kmp_task_red_input_t; 6188 ASTContext &C = CGM.getContext(); 6189 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6190 RD->startDefinition(); 6191 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6192 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6193 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6194 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6195 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6196 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6197 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6198 RD->completeDefinition(); 6199 QualType RDType = C.getRecordType(RD); 6200 unsigned Size = Data.ReductionVars.size(); 6201 llvm::APInt ArraySize(/*numBits=*/64, Size); 6202 QualType ArrayRDType = C.getConstantArrayType( 6203 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6204 // kmp_task_red_input_t .rd_input.[Size]; 6205 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6206 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6207 Data.ReductionOps); 6208 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6209 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6210 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6211 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6212 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6213 TaskRedInput.getPointer(), Idxs, 6214 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6215 ".rd_input.gep."); 6216 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6217 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6218 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6219 RCG.emitSharedLValue(CGF, Cnt); 6220 llvm::Value *CastedShared = 6221 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6222 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6223 RCG.emitAggregateType(CGF, Cnt); 6224 llvm::Value *SizeValInChars; 6225 llvm::Value *SizeVal; 6226 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6227 // We use delayed creation/initialization for VLAs, array sections and 6228 // custom reduction initializations. It is required because runtime does not 6229 // provide the way to pass the sizes of VLAs/array sections to 6230 // initializer/combiner/finalizer functions and does not pass the pointer to 6231 // original reduction item to the initializer. Instead threadprivate global 6232 // variables are used to store these values and use them in the functions. 6233 bool DelayedCreation = !!SizeVal; 6234 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6235 /*isSigned=*/false); 6236 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6237 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6238 // ElemLVal.reduce_init = init; 6239 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6240 llvm::Value *InitAddr = 6241 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6242 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6243 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6244 // ElemLVal.reduce_fini = fini; 6245 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6246 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6247 llvm::Value *FiniAddr = Fini 6248 ? CGF.EmitCastToVoidPtr(Fini) 6249 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6250 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6251 // ElemLVal.reduce_comb = comb; 6252 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6253 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6254 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6255 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6256 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6257 // ElemLVal.flags = 0; 6258 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6259 if (DelayedCreation) { 6260 CGF.EmitStoreOfScalar( 6261 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6262 FlagsLVal); 6263 } else 6264 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6265 FlagsLVal.getType()); 6266 } 6267 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6268 // *data); 6269 llvm::Value *Args[] = { 6270 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6271 /*isSigned=*/true), 6272 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6273 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6274 CGM.VoidPtrTy)}; 6275 return CGF.EmitRuntimeCall( 6276 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6277 } 6278 6279 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6280 SourceLocation Loc, 6281 ReductionCodeGen &RCG, 6282 unsigned N) { 6283 auto Sizes = RCG.getSizes(N); 6284 // Emit threadprivate global variable if the type is non-constant 6285 // (Sizes.second = nullptr). 6286 if (Sizes.second) { 6287 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6288 /*isSigned=*/false); 6289 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6290 CGF, CGM.getContext().getSizeType(), 6291 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6292 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6293 } 6294 // Store address of the original reduction item if custom initializer is used. 6295 if (RCG.usesReductionInitializer(N)) { 6296 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6297 CGF, CGM.getContext().VoidPtrTy, 6298 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6299 CGF.Builder.CreateStore( 6300 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6301 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy), 6302 SharedAddr, /*IsVolatile=*/false); 6303 } 6304 } 6305 6306 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6307 SourceLocation Loc, 6308 llvm::Value *ReductionsPtr, 6309 LValue SharedLVal) { 6310 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6311 // *d); 6312 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6313 CGM.IntTy, 6314 /*isSigned=*/true), 6315 ReductionsPtr, 6316 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6317 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6318 return Address( 6319 CGF.EmitRuntimeCall( 6320 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6321 SharedLVal.getAlignment()); 6322 } 6323 6324 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6325 SourceLocation Loc) { 6326 if (!CGF.HaveInsertPoint()) 6327 return; 6328 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6329 // global_tid); 6330 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6331 // Ignore return result until untied tasks are supported. 6332 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6333 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6334 Region->emitUntiedSwitch(CGF); 6335 } 6336 6337 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6338 OpenMPDirectiveKind InnerKind, 6339 const RegionCodeGenTy &CodeGen, 6340 bool HasCancel) { 6341 if (!CGF.HaveInsertPoint()) 6342 return; 6343 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6344 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6345 } 6346 6347 namespace { 6348 enum RTCancelKind { 6349 CancelNoreq = 0, 6350 CancelParallel = 1, 6351 CancelLoop = 2, 6352 CancelSections = 3, 6353 CancelTaskgroup = 4 6354 }; 6355 } // anonymous namespace 6356 6357 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6358 RTCancelKind CancelKind = CancelNoreq; 6359 if (CancelRegion == OMPD_parallel) 6360 CancelKind = CancelParallel; 6361 else if (CancelRegion == OMPD_for) 6362 CancelKind = CancelLoop; 6363 else if (CancelRegion == OMPD_sections) 6364 CancelKind = CancelSections; 6365 else { 6366 assert(CancelRegion == OMPD_taskgroup); 6367 CancelKind = CancelTaskgroup; 6368 } 6369 return CancelKind; 6370 } 6371 6372 void CGOpenMPRuntime::emitCancellationPointCall( 6373 CodeGenFunction &CGF, SourceLocation Loc, 6374 OpenMPDirectiveKind CancelRegion) { 6375 if (!CGF.HaveInsertPoint()) 6376 return; 6377 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6378 // global_tid, kmp_int32 cncl_kind); 6379 if (auto *OMPRegionInfo = 6380 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6381 // For 'cancellation point taskgroup', the task region info may not have a 6382 // cancel. This may instead happen in another adjacent task. 6383 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6384 llvm::Value *Args[] = { 6385 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6386 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6387 // Ignore return result until untied tasks are supported. 6388 llvm::Value *Result = CGF.EmitRuntimeCall( 6389 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6390 // if (__kmpc_cancellationpoint()) { 6391 // exit from construct; 6392 // } 6393 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6394 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6395 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6396 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6397 CGF.EmitBlock(ExitBB); 6398 // exit from construct; 6399 CodeGenFunction::JumpDest CancelDest = 6400 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6401 CGF.EmitBranchThroughCleanup(CancelDest); 6402 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6403 } 6404 } 6405 } 6406 6407 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6408 const Expr *IfCond, 6409 OpenMPDirectiveKind CancelRegion) { 6410 if (!CGF.HaveInsertPoint()) 6411 return; 6412 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6413 // kmp_int32 cncl_kind); 6414 if (auto *OMPRegionInfo = 6415 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6416 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6417 PrePostActionTy &) { 6418 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6419 llvm::Value *Args[] = { 6420 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6421 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6422 // Ignore return result until untied tasks are supported. 6423 llvm::Value *Result = CGF.EmitRuntimeCall( 6424 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6425 // if (__kmpc_cancel()) { 6426 // exit from construct; 6427 // } 6428 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6429 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6430 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6431 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6432 CGF.EmitBlock(ExitBB); 6433 // exit from construct; 6434 CodeGenFunction::JumpDest CancelDest = 6435 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6436 CGF.EmitBranchThroughCleanup(CancelDest); 6437 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6438 }; 6439 if (IfCond) { 6440 emitIfClause(CGF, IfCond, ThenGen, 6441 [](CodeGenFunction &, PrePostActionTy &) {}); 6442 } else { 6443 RegionCodeGenTy ThenRCG(ThenGen); 6444 ThenRCG(CGF); 6445 } 6446 } 6447 } 6448 6449 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6450 const OMPExecutableDirective &D, StringRef ParentName, 6451 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6452 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6453 assert(!ParentName.empty() && "Invalid target region parent name!"); 6454 HasEmittedTargetRegion = true; 6455 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6456 IsOffloadEntry, CodeGen); 6457 } 6458 6459 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6460 const OMPExecutableDirective &D, StringRef ParentName, 6461 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6462 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6463 // Create a unique name for the entry function using the source location 6464 // information of the current target region. The name will be something like: 6465 // 6466 // __omp_offloading_DD_FFFF_PP_lBB 6467 // 6468 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6469 // mangled name of the function that encloses the target region and BB is the 6470 // line number of the target region. 6471 6472 unsigned DeviceID; 6473 unsigned FileID; 6474 unsigned Line; 6475 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6476 Line); 6477 SmallString<64> EntryFnName; 6478 { 6479 llvm::raw_svector_ostream OS(EntryFnName); 6480 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6481 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6482 } 6483 6484 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6485 6486 CodeGenFunction CGF(CGM, true); 6487 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6488 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6489 6490 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6491 6492 // If this target outline function is not an offload entry, we don't need to 6493 // register it. 6494 if (!IsOffloadEntry) 6495 return; 6496 6497 // The target region ID is used by the runtime library to identify the current 6498 // target region, so it only has to be unique and not necessarily point to 6499 // anything. It could be the pointer to the outlined function that implements 6500 // the target region, but we aren't using that so that the compiler doesn't 6501 // need to keep that, and could therefore inline the host function if proven 6502 // worthwhile during optimization. In the other hand, if emitting code for the 6503 // device, the ID has to be the function address so that it can retrieved from 6504 // the offloading entry and launched by the runtime library. We also mark the 6505 // outlined function to have external linkage in case we are emitting code for 6506 // the device, because these functions will be entry points to the device. 6507 6508 if (CGM.getLangOpts().OpenMPIsDevice) { 6509 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6510 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6511 OutlinedFn->setDSOLocal(false); 6512 } else { 6513 std::string Name = getName({EntryFnName, "region_id"}); 6514 OutlinedFnID = new llvm::GlobalVariable( 6515 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6516 llvm::GlobalValue::WeakAnyLinkage, 6517 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6518 } 6519 6520 // Register the information for the entry associated with this target region. 6521 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6522 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6523 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6524 } 6525 6526 /// Checks if the expression is constant or does not have non-trivial function 6527 /// calls. 6528 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6529 // We can skip constant expressions. 6530 // We can skip expressions with trivial calls or simple expressions. 6531 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6532 !E->hasNonTrivialCall(Ctx)) && 6533 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6534 } 6535 6536 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6537 const Stmt *Body) { 6538 const Stmt *Child = Body->IgnoreContainers(); 6539 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6540 Child = nullptr; 6541 for (const Stmt *S : C->body()) { 6542 if (const auto *E = dyn_cast<Expr>(S)) { 6543 if (isTrivial(Ctx, E)) 6544 continue; 6545 } 6546 // Some of the statements can be ignored. 6547 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6548 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6549 continue; 6550 // Analyze declarations. 6551 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6552 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6553 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6554 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6555 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6556 isa<UsingDirectiveDecl>(D) || 6557 isa<OMPDeclareReductionDecl>(D) || 6558 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6559 return true; 6560 const auto *VD = dyn_cast<VarDecl>(D); 6561 if (!VD) 6562 return false; 6563 return VD->isConstexpr() || 6564 ((VD->getType().isTrivialType(Ctx) || 6565 VD->getType()->isReferenceType()) && 6566 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6567 })) 6568 continue; 6569 } 6570 // Found multiple children - cannot get the one child only. 6571 if (Child) 6572 return nullptr; 6573 Child = S; 6574 } 6575 if (Child) 6576 Child = Child->IgnoreContainers(); 6577 } 6578 return Child; 6579 } 6580 6581 /// Emit the number of teams for a target directive. Inspect the num_teams 6582 /// clause associated with a teams construct combined or closely nested 6583 /// with the target directive. 6584 /// 6585 /// Emit a team of size one for directives such as 'target parallel' that 6586 /// have no associated teams construct. 6587 /// 6588 /// Otherwise, return nullptr. 6589 static llvm::Value * 6590 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6591 const OMPExecutableDirective &D) { 6592 assert(!CGF.getLangOpts().OpenMPIsDevice && 6593 "Clauses associated with the teams directive expected to be emitted " 6594 "only for the host!"); 6595 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6596 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6597 "Expected target-based executable directive."); 6598 CGBuilderTy &Bld = CGF.Builder; 6599 switch (DirectiveKind) { 6600 case OMPD_target: { 6601 const auto *CS = D.getInnermostCapturedStmt(); 6602 const auto *Body = 6603 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6604 const Stmt *ChildStmt = 6605 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6606 if (const auto *NestedDir = 6607 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6608 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6609 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6610 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6611 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6612 const Expr *NumTeams = 6613 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6614 llvm::Value *NumTeamsVal = 6615 CGF.EmitScalarExpr(NumTeams, 6616 /*IgnoreResultAssign*/ true); 6617 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6618 /*isSigned=*/true); 6619 } 6620 return Bld.getInt32(0); 6621 } 6622 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6623 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6624 return Bld.getInt32(1); 6625 return Bld.getInt32(0); 6626 } 6627 return nullptr; 6628 } 6629 case OMPD_target_teams: 6630 case OMPD_target_teams_distribute: 6631 case OMPD_target_teams_distribute_simd: 6632 case OMPD_target_teams_distribute_parallel_for: 6633 case OMPD_target_teams_distribute_parallel_for_simd: { 6634 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6635 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6636 const Expr *NumTeams = 6637 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6638 llvm::Value *NumTeamsVal = 6639 CGF.EmitScalarExpr(NumTeams, 6640 /*IgnoreResultAssign*/ true); 6641 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6642 /*isSigned=*/true); 6643 } 6644 return Bld.getInt32(0); 6645 } 6646 case OMPD_target_parallel: 6647 case OMPD_target_parallel_for: 6648 case OMPD_target_parallel_for_simd: 6649 case OMPD_target_simd: 6650 return Bld.getInt32(1); 6651 case OMPD_parallel: 6652 case OMPD_for: 6653 case OMPD_parallel_for: 6654 case OMPD_parallel_master: 6655 case OMPD_parallel_sections: 6656 case OMPD_for_simd: 6657 case OMPD_parallel_for_simd: 6658 case OMPD_cancel: 6659 case OMPD_cancellation_point: 6660 case OMPD_ordered: 6661 case OMPD_threadprivate: 6662 case OMPD_allocate: 6663 case OMPD_task: 6664 case OMPD_simd: 6665 case OMPD_sections: 6666 case OMPD_section: 6667 case OMPD_single: 6668 case OMPD_master: 6669 case OMPD_critical: 6670 case OMPD_taskyield: 6671 case OMPD_barrier: 6672 case OMPD_taskwait: 6673 case OMPD_taskgroup: 6674 case OMPD_atomic: 6675 case OMPD_flush: 6676 case OMPD_teams: 6677 case OMPD_target_data: 6678 case OMPD_target_exit_data: 6679 case OMPD_target_enter_data: 6680 case OMPD_distribute: 6681 case OMPD_distribute_simd: 6682 case OMPD_distribute_parallel_for: 6683 case OMPD_distribute_parallel_for_simd: 6684 case OMPD_teams_distribute: 6685 case OMPD_teams_distribute_simd: 6686 case OMPD_teams_distribute_parallel_for: 6687 case OMPD_teams_distribute_parallel_for_simd: 6688 case OMPD_target_update: 6689 case OMPD_declare_simd: 6690 case OMPD_declare_variant: 6691 case OMPD_declare_target: 6692 case OMPD_end_declare_target: 6693 case OMPD_declare_reduction: 6694 case OMPD_declare_mapper: 6695 case OMPD_taskloop: 6696 case OMPD_taskloop_simd: 6697 case OMPD_master_taskloop: 6698 case OMPD_master_taskloop_simd: 6699 case OMPD_parallel_master_taskloop: 6700 case OMPD_parallel_master_taskloop_simd: 6701 case OMPD_requires: 6702 case OMPD_unknown: 6703 break; 6704 } 6705 llvm_unreachable("Unexpected directive kind."); 6706 } 6707 6708 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6709 llvm::Value *DefaultThreadLimitVal) { 6710 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6711 CGF.getContext(), CS->getCapturedStmt()); 6712 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6713 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6714 llvm::Value *NumThreads = nullptr; 6715 llvm::Value *CondVal = nullptr; 6716 // Handle if clause. If if clause present, the number of threads is 6717 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6718 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6719 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6720 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6721 const OMPIfClause *IfClause = nullptr; 6722 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6723 if (C->getNameModifier() == OMPD_unknown || 6724 C->getNameModifier() == OMPD_parallel) { 6725 IfClause = C; 6726 break; 6727 } 6728 } 6729 if (IfClause) { 6730 const Expr *Cond = IfClause->getCondition(); 6731 bool Result; 6732 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6733 if (!Result) 6734 return CGF.Builder.getInt32(1); 6735 } else { 6736 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6737 if (const auto *PreInit = 6738 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6739 for (const auto *I : PreInit->decls()) { 6740 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6741 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6742 } else { 6743 CodeGenFunction::AutoVarEmission Emission = 6744 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6745 CGF.EmitAutoVarCleanups(Emission); 6746 } 6747 } 6748 } 6749 CondVal = CGF.EvaluateExprAsBool(Cond); 6750 } 6751 } 6752 } 6753 // Check the value of num_threads clause iff if clause was not specified 6754 // or is not evaluated to false. 6755 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6756 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6757 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6758 const auto *NumThreadsClause = 6759 Dir->getSingleClause<OMPNumThreadsClause>(); 6760 CodeGenFunction::LexicalScope Scope( 6761 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6762 if (const auto *PreInit = 6763 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6764 for (const auto *I : PreInit->decls()) { 6765 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6766 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6767 } else { 6768 CodeGenFunction::AutoVarEmission Emission = 6769 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6770 CGF.EmitAutoVarCleanups(Emission); 6771 } 6772 } 6773 } 6774 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6775 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6776 /*isSigned=*/false); 6777 if (DefaultThreadLimitVal) 6778 NumThreads = CGF.Builder.CreateSelect( 6779 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6780 DefaultThreadLimitVal, NumThreads); 6781 } else { 6782 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6783 : CGF.Builder.getInt32(0); 6784 } 6785 // Process condition of the if clause. 6786 if (CondVal) { 6787 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6788 CGF.Builder.getInt32(1)); 6789 } 6790 return NumThreads; 6791 } 6792 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6793 return CGF.Builder.getInt32(1); 6794 return DefaultThreadLimitVal; 6795 } 6796 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6797 : CGF.Builder.getInt32(0); 6798 } 6799 6800 /// Emit the number of threads for a target directive. Inspect the 6801 /// thread_limit clause associated with a teams construct combined or closely 6802 /// nested with the target directive. 6803 /// 6804 /// Emit the num_threads clause for directives such as 'target parallel' that 6805 /// have no associated teams construct. 6806 /// 6807 /// Otherwise, return nullptr. 6808 static llvm::Value * 6809 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6810 const OMPExecutableDirective &D) { 6811 assert(!CGF.getLangOpts().OpenMPIsDevice && 6812 "Clauses associated with the teams directive expected to be emitted " 6813 "only for the host!"); 6814 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6815 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6816 "Expected target-based executable directive."); 6817 CGBuilderTy &Bld = CGF.Builder; 6818 llvm::Value *ThreadLimitVal = nullptr; 6819 llvm::Value *NumThreadsVal = nullptr; 6820 switch (DirectiveKind) { 6821 case OMPD_target: { 6822 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6823 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6824 return NumThreads; 6825 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6826 CGF.getContext(), CS->getCapturedStmt()); 6827 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6828 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6829 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6830 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6831 const auto *ThreadLimitClause = 6832 Dir->getSingleClause<OMPThreadLimitClause>(); 6833 CodeGenFunction::LexicalScope Scope( 6834 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6835 if (const auto *PreInit = 6836 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6837 for (const auto *I : PreInit->decls()) { 6838 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6839 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6840 } else { 6841 CodeGenFunction::AutoVarEmission Emission = 6842 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6843 CGF.EmitAutoVarCleanups(Emission); 6844 } 6845 } 6846 } 6847 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6848 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6849 ThreadLimitVal = 6850 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6851 } 6852 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6853 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6854 CS = Dir->getInnermostCapturedStmt(); 6855 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6856 CGF.getContext(), CS->getCapturedStmt()); 6857 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6858 } 6859 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6860 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6861 CS = Dir->getInnermostCapturedStmt(); 6862 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6863 return NumThreads; 6864 } 6865 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6866 return Bld.getInt32(1); 6867 } 6868 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6869 } 6870 case OMPD_target_teams: { 6871 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6872 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6873 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6874 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6875 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6876 ThreadLimitVal = 6877 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6878 } 6879 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6880 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6881 return NumThreads; 6882 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6883 CGF.getContext(), CS->getCapturedStmt()); 6884 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6885 if (Dir->getDirectiveKind() == OMPD_distribute) { 6886 CS = Dir->getInnermostCapturedStmt(); 6887 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6888 return NumThreads; 6889 } 6890 } 6891 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6892 } 6893 case OMPD_target_teams_distribute: 6894 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6895 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6896 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6897 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6898 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6899 ThreadLimitVal = 6900 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6901 } 6902 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6903 case OMPD_target_parallel: 6904 case OMPD_target_parallel_for: 6905 case OMPD_target_parallel_for_simd: 6906 case OMPD_target_teams_distribute_parallel_for: 6907 case OMPD_target_teams_distribute_parallel_for_simd: { 6908 llvm::Value *CondVal = nullptr; 6909 // Handle if clause. If if clause present, the number of threads is 6910 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6911 if (D.hasClausesOfKind<OMPIfClause>()) { 6912 const OMPIfClause *IfClause = nullptr; 6913 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6914 if (C->getNameModifier() == OMPD_unknown || 6915 C->getNameModifier() == OMPD_parallel) { 6916 IfClause = C; 6917 break; 6918 } 6919 } 6920 if (IfClause) { 6921 const Expr *Cond = IfClause->getCondition(); 6922 bool Result; 6923 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6924 if (!Result) 6925 return Bld.getInt32(1); 6926 } else { 6927 CodeGenFunction::RunCleanupsScope Scope(CGF); 6928 CondVal = CGF.EvaluateExprAsBool(Cond); 6929 } 6930 } 6931 } 6932 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6933 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6934 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6935 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6936 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6937 ThreadLimitVal = 6938 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6939 } 6940 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6941 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6942 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6943 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6944 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6945 NumThreadsVal = 6946 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6947 ThreadLimitVal = ThreadLimitVal 6948 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6949 ThreadLimitVal), 6950 NumThreadsVal, ThreadLimitVal) 6951 : NumThreadsVal; 6952 } 6953 if (!ThreadLimitVal) 6954 ThreadLimitVal = Bld.getInt32(0); 6955 if (CondVal) 6956 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6957 return ThreadLimitVal; 6958 } 6959 case OMPD_target_teams_distribute_simd: 6960 case OMPD_target_simd: 6961 return Bld.getInt32(1); 6962 case OMPD_parallel: 6963 case OMPD_for: 6964 case OMPD_parallel_for: 6965 case OMPD_parallel_master: 6966 case OMPD_parallel_sections: 6967 case OMPD_for_simd: 6968 case OMPD_parallel_for_simd: 6969 case OMPD_cancel: 6970 case OMPD_cancellation_point: 6971 case OMPD_ordered: 6972 case OMPD_threadprivate: 6973 case OMPD_allocate: 6974 case OMPD_task: 6975 case OMPD_simd: 6976 case OMPD_sections: 6977 case OMPD_section: 6978 case OMPD_single: 6979 case OMPD_master: 6980 case OMPD_critical: 6981 case OMPD_taskyield: 6982 case OMPD_barrier: 6983 case OMPD_taskwait: 6984 case OMPD_taskgroup: 6985 case OMPD_atomic: 6986 case OMPD_flush: 6987 case OMPD_teams: 6988 case OMPD_target_data: 6989 case OMPD_target_exit_data: 6990 case OMPD_target_enter_data: 6991 case OMPD_distribute: 6992 case OMPD_distribute_simd: 6993 case OMPD_distribute_parallel_for: 6994 case OMPD_distribute_parallel_for_simd: 6995 case OMPD_teams_distribute: 6996 case OMPD_teams_distribute_simd: 6997 case OMPD_teams_distribute_parallel_for: 6998 case OMPD_teams_distribute_parallel_for_simd: 6999 case OMPD_target_update: 7000 case OMPD_declare_simd: 7001 case OMPD_declare_variant: 7002 case OMPD_declare_target: 7003 case OMPD_end_declare_target: 7004 case OMPD_declare_reduction: 7005 case OMPD_declare_mapper: 7006 case OMPD_taskloop: 7007 case OMPD_taskloop_simd: 7008 case OMPD_master_taskloop: 7009 case OMPD_master_taskloop_simd: 7010 case OMPD_parallel_master_taskloop: 7011 case OMPD_parallel_master_taskloop_simd: 7012 case OMPD_requires: 7013 case OMPD_unknown: 7014 break; 7015 } 7016 llvm_unreachable("Unsupported directive kind."); 7017 } 7018 7019 namespace { 7020 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7021 7022 // Utility to handle information from clauses associated with a given 7023 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7024 // It provides a convenient interface to obtain the information and generate 7025 // code for that information. 7026 class MappableExprsHandler { 7027 public: 7028 /// Values for bit flags used to specify the mapping type for 7029 /// offloading. 7030 enum OpenMPOffloadMappingFlags : uint64_t { 7031 /// No flags 7032 OMP_MAP_NONE = 0x0, 7033 /// Allocate memory on the device and move data from host to device. 7034 OMP_MAP_TO = 0x01, 7035 /// Allocate memory on the device and move data from device to host. 7036 OMP_MAP_FROM = 0x02, 7037 /// Always perform the requested mapping action on the element, even 7038 /// if it was already mapped before. 7039 OMP_MAP_ALWAYS = 0x04, 7040 /// Delete the element from the device environment, ignoring the 7041 /// current reference count associated with the element. 7042 OMP_MAP_DELETE = 0x08, 7043 /// The element being mapped is a pointer-pointee pair; both the 7044 /// pointer and the pointee should be mapped. 7045 OMP_MAP_PTR_AND_OBJ = 0x10, 7046 /// This flags signals that the base address of an entry should be 7047 /// passed to the target kernel as an argument. 7048 OMP_MAP_TARGET_PARAM = 0x20, 7049 /// Signal that the runtime library has to return the device pointer 7050 /// in the current position for the data being mapped. Used when we have the 7051 /// use_device_ptr clause. 7052 OMP_MAP_RETURN_PARAM = 0x40, 7053 /// This flag signals that the reference being passed is a pointer to 7054 /// private data. 7055 OMP_MAP_PRIVATE = 0x80, 7056 /// Pass the element to the device by value. 7057 OMP_MAP_LITERAL = 0x100, 7058 /// Implicit map 7059 OMP_MAP_IMPLICIT = 0x200, 7060 /// Close is a hint to the runtime to allocate memory close to 7061 /// the target device. 7062 OMP_MAP_CLOSE = 0x400, 7063 /// The 16 MSBs of the flags indicate whether the entry is member of some 7064 /// struct/class. 7065 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7066 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7067 }; 7068 7069 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7070 static unsigned getFlagMemberOffset() { 7071 unsigned Offset = 0; 7072 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7073 Remain = Remain >> 1) 7074 Offset++; 7075 return Offset; 7076 } 7077 7078 /// Class that associates information with a base pointer to be passed to the 7079 /// runtime library. 7080 class BasePointerInfo { 7081 /// The base pointer. 7082 llvm::Value *Ptr = nullptr; 7083 /// The base declaration that refers to this device pointer, or null if 7084 /// there is none. 7085 const ValueDecl *DevPtrDecl = nullptr; 7086 7087 public: 7088 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7089 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7090 llvm::Value *operator*() const { return Ptr; } 7091 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7092 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7093 }; 7094 7095 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7096 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7097 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7098 7099 /// Map between a struct and the its lowest & highest elements which have been 7100 /// mapped. 7101 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7102 /// HE(FieldIndex, Pointer)} 7103 struct StructRangeInfoTy { 7104 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7105 0, Address::invalid()}; 7106 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7107 0, Address::invalid()}; 7108 Address Base = Address::invalid(); 7109 }; 7110 7111 private: 7112 /// Kind that defines how a device pointer has to be returned. 7113 struct MapInfo { 7114 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7115 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7116 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7117 bool ReturnDevicePointer = false; 7118 bool IsImplicit = false; 7119 7120 MapInfo() = default; 7121 MapInfo( 7122 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7123 OpenMPMapClauseKind MapType, 7124 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7125 bool ReturnDevicePointer, bool IsImplicit) 7126 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7127 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7128 }; 7129 7130 /// If use_device_ptr is used on a pointer which is a struct member and there 7131 /// is no map information about it, then emission of that entry is deferred 7132 /// until the whole struct has been processed. 7133 struct DeferredDevicePtrEntryTy { 7134 const Expr *IE = nullptr; 7135 const ValueDecl *VD = nullptr; 7136 7137 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7138 : IE(IE), VD(VD) {} 7139 }; 7140 7141 /// The target directive from where the mappable clauses were extracted. It 7142 /// is either a executable directive or a user-defined mapper directive. 7143 llvm::PointerUnion<const OMPExecutableDirective *, 7144 const OMPDeclareMapperDecl *> 7145 CurDir; 7146 7147 /// Function the directive is being generated for. 7148 CodeGenFunction &CGF; 7149 7150 /// Set of all first private variables in the current directive. 7151 /// bool data is set to true if the variable is implicitly marked as 7152 /// firstprivate, false otherwise. 7153 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7154 7155 /// Map between device pointer declarations and their expression components. 7156 /// The key value for declarations in 'this' is null. 7157 llvm::DenseMap< 7158 const ValueDecl *, 7159 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7160 DevPointersMap; 7161 7162 llvm::Value *getExprTypeSize(const Expr *E) const { 7163 QualType ExprTy = E->getType().getCanonicalType(); 7164 7165 // Reference types are ignored for mapping purposes. 7166 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7167 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7168 7169 // Given that an array section is considered a built-in type, we need to 7170 // do the calculation based on the length of the section instead of relying 7171 // on CGF.getTypeSize(E->getType()). 7172 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7173 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7174 OAE->getBase()->IgnoreParenImpCasts()) 7175 .getCanonicalType(); 7176 7177 // If there is no length associated with the expression and lower bound is 7178 // not specified too, that means we are using the whole length of the 7179 // base. 7180 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7181 !OAE->getLowerBound()) 7182 return CGF.getTypeSize(BaseTy); 7183 7184 llvm::Value *ElemSize; 7185 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7186 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7187 } else { 7188 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7189 assert(ATy && "Expecting array type if not a pointer type."); 7190 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7191 } 7192 7193 // If we don't have a length at this point, that is because we have an 7194 // array section with a single element. 7195 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7196 return ElemSize; 7197 7198 if (const Expr *LenExpr = OAE->getLength()) { 7199 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7200 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7201 CGF.getContext().getSizeType(), 7202 LenExpr->getExprLoc()); 7203 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7204 } 7205 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7206 OAE->getLowerBound() && "expected array_section[lb:]."); 7207 // Size = sizetype - lb * elemtype; 7208 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7209 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7210 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7211 CGF.getContext().getSizeType(), 7212 OAE->getLowerBound()->getExprLoc()); 7213 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7214 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7215 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7216 LengthVal = CGF.Builder.CreateSelect( 7217 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7218 return LengthVal; 7219 } 7220 return CGF.getTypeSize(ExprTy); 7221 } 7222 7223 /// Return the corresponding bits for a given map clause modifier. Add 7224 /// a flag marking the map as a pointer if requested. Add a flag marking the 7225 /// map as the first one of a series of maps that relate to the same map 7226 /// expression. 7227 OpenMPOffloadMappingFlags getMapTypeBits( 7228 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7229 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7230 OpenMPOffloadMappingFlags Bits = 7231 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7232 switch (MapType) { 7233 case OMPC_MAP_alloc: 7234 case OMPC_MAP_release: 7235 // alloc and release is the default behavior in the runtime library, i.e. 7236 // if we don't pass any bits alloc/release that is what the runtime is 7237 // going to do. Therefore, we don't need to signal anything for these two 7238 // type modifiers. 7239 break; 7240 case OMPC_MAP_to: 7241 Bits |= OMP_MAP_TO; 7242 break; 7243 case OMPC_MAP_from: 7244 Bits |= OMP_MAP_FROM; 7245 break; 7246 case OMPC_MAP_tofrom: 7247 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7248 break; 7249 case OMPC_MAP_delete: 7250 Bits |= OMP_MAP_DELETE; 7251 break; 7252 case OMPC_MAP_unknown: 7253 llvm_unreachable("Unexpected map type!"); 7254 } 7255 if (AddPtrFlag) 7256 Bits |= OMP_MAP_PTR_AND_OBJ; 7257 if (AddIsTargetParamFlag) 7258 Bits |= OMP_MAP_TARGET_PARAM; 7259 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7260 != MapModifiers.end()) 7261 Bits |= OMP_MAP_ALWAYS; 7262 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7263 != MapModifiers.end()) 7264 Bits |= OMP_MAP_CLOSE; 7265 return Bits; 7266 } 7267 7268 /// Return true if the provided expression is a final array section. A 7269 /// final array section, is one whose length can't be proved to be one. 7270 bool isFinalArraySectionExpression(const Expr *E) const { 7271 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7272 7273 // It is not an array section and therefore not a unity-size one. 7274 if (!OASE) 7275 return false; 7276 7277 // An array section with no colon always refer to a single element. 7278 if (OASE->getColonLoc().isInvalid()) 7279 return false; 7280 7281 const Expr *Length = OASE->getLength(); 7282 7283 // If we don't have a length we have to check if the array has size 1 7284 // for this dimension. Also, we should always expect a length if the 7285 // base type is pointer. 7286 if (!Length) { 7287 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7288 OASE->getBase()->IgnoreParenImpCasts()) 7289 .getCanonicalType(); 7290 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7291 return ATy->getSize().getSExtValue() != 1; 7292 // If we don't have a constant dimension length, we have to consider 7293 // the current section as having any size, so it is not necessarily 7294 // unitary. If it happen to be unity size, that's user fault. 7295 return true; 7296 } 7297 7298 // Check if the length evaluates to 1. 7299 Expr::EvalResult Result; 7300 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7301 return true; // Can have more that size 1. 7302 7303 llvm::APSInt ConstLength = Result.Val.getInt(); 7304 return ConstLength.getSExtValue() != 1; 7305 } 7306 7307 /// Generate the base pointers, section pointers, sizes and map type 7308 /// bits for the provided map type, map modifier, and expression components. 7309 /// \a IsFirstComponent should be set to true if the provided set of 7310 /// components is the first associated with a capture. 7311 void generateInfoForComponentList( 7312 OpenMPMapClauseKind MapType, 7313 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7314 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7315 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7316 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7317 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7318 bool IsImplicit, 7319 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7320 OverlappedElements = llvm::None) const { 7321 // The following summarizes what has to be generated for each map and the 7322 // types below. The generated information is expressed in this order: 7323 // base pointer, section pointer, size, flags 7324 // (to add to the ones that come from the map type and modifier). 7325 // 7326 // double d; 7327 // int i[100]; 7328 // float *p; 7329 // 7330 // struct S1 { 7331 // int i; 7332 // float f[50]; 7333 // } 7334 // struct S2 { 7335 // int i; 7336 // float f[50]; 7337 // S1 s; 7338 // double *p; 7339 // struct S2 *ps; 7340 // } 7341 // S2 s; 7342 // S2 *ps; 7343 // 7344 // map(d) 7345 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7346 // 7347 // map(i) 7348 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7349 // 7350 // map(i[1:23]) 7351 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7352 // 7353 // map(p) 7354 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7355 // 7356 // map(p[1:24]) 7357 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7358 // 7359 // map(s) 7360 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7361 // 7362 // map(s.i) 7363 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7364 // 7365 // map(s.s.f) 7366 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7367 // 7368 // map(s.p) 7369 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7370 // 7371 // map(to: s.p[:22]) 7372 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7373 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7374 // &(s.p), &(s.p[0]), 22*sizeof(double), 7375 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7376 // (*) alloc space for struct members, only this is a target parameter 7377 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7378 // optimizes this entry out, same in the examples below) 7379 // (***) map the pointee (map: to) 7380 // 7381 // map(s.ps) 7382 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7383 // 7384 // map(from: s.ps->s.i) 7385 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7386 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7387 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7388 // 7389 // map(to: s.ps->ps) 7390 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7391 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7392 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7393 // 7394 // map(s.ps->ps->ps) 7395 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7396 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7397 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7398 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7399 // 7400 // map(to: s.ps->ps->s.f[:22]) 7401 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7402 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7403 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7404 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7405 // 7406 // map(ps) 7407 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7408 // 7409 // map(ps->i) 7410 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7411 // 7412 // map(ps->s.f) 7413 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7414 // 7415 // map(from: ps->p) 7416 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7417 // 7418 // map(to: ps->p[:22]) 7419 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7420 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7421 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7422 // 7423 // map(ps->ps) 7424 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7425 // 7426 // map(from: ps->ps->s.i) 7427 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7428 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7429 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7430 // 7431 // map(from: ps->ps->ps) 7432 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7433 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7434 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7435 // 7436 // map(ps->ps->ps->ps) 7437 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7438 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7439 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7440 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7441 // 7442 // map(to: ps->ps->ps->s.f[:22]) 7443 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7444 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7445 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7446 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7447 // 7448 // map(to: s.f[:22]) map(from: s.p[:33]) 7449 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7450 // sizeof(double*) (**), TARGET_PARAM 7451 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7452 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7453 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7454 // (*) allocate contiguous space needed to fit all mapped members even if 7455 // we allocate space for members not mapped (in this example, 7456 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7457 // them as well because they fall between &s.f[0] and &s.p) 7458 // 7459 // map(from: s.f[:22]) map(to: ps->p[:33]) 7460 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7461 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7462 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7463 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7464 // (*) the struct this entry pertains to is the 2nd element in the list of 7465 // arguments, hence MEMBER_OF(2) 7466 // 7467 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7468 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7469 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7470 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7471 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7472 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7473 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7474 // (*) the struct this entry pertains to is the 4th element in the list 7475 // of arguments, hence MEMBER_OF(4) 7476 7477 // Track if the map information being generated is the first for a capture. 7478 bool IsCaptureFirstInfo = IsFirstComponentList; 7479 // When the variable is on a declare target link or in a to clause with 7480 // unified memory, a reference is needed to hold the host/device address 7481 // of the variable. 7482 bool RequiresReference = false; 7483 7484 // Scan the components from the base to the complete expression. 7485 auto CI = Components.rbegin(); 7486 auto CE = Components.rend(); 7487 auto I = CI; 7488 7489 // Track if the map information being generated is the first for a list of 7490 // components. 7491 bool IsExpressionFirstInfo = true; 7492 Address BP = Address::invalid(); 7493 const Expr *AssocExpr = I->getAssociatedExpression(); 7494 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7495 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7496 7497 if (isa<MemberExpr>(AssocExpr)) { 7498 // The base is the 'this' pointer. The content of the pointer is going 7499 // to be the base of the field being mapped. 7500 BP = CGF.LoadCXXThisAddress(); 7501 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7502 (OASE && 7503 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7504 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7505 } else { 7506 // The base is the reference to the variable. 7507 // BP = &Var. 7508 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7509 if (const auto *VD = 7510 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7511 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7512 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7513 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7514 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7515 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7516 RequiresReference = true; 7517 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7518 } 7519 } 7520 } 7521 7522 // If the variable is a pointer and is being dereferenced (i.e. is not 7523 // the last component), the base has to be the pointer itself, not its 7524 // reference. References are ignored for mapping purposes. 7525 QualType Ty = 7526 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7527 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7528 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7529 7530 // We do not need to generate individual map information for the 7531 // pointer, it can be associated with the combined storage. 7532 ++I; 7533 } 7534 } 7535 7536 // Track whether a component of the list should be marked as MEMBER_OF some 7537 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7538 // in a component list should be marked as MEMBER_OF, all subsequent entries 7539 // do not belong to the base struct. E.g. 7540 // struct S2 s; 7541 // s.ps->ps->ps->f[:] 7542 // (1) (2) (3) (4) 7543 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7544 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7545 // is the pointee of ps(2) which is not member of struct s, so it should not 7546 // be marked as such (it is still PTR_AND_OBJ). 7547 // The variable is initialized to false so that PTR_AND_OBJ entries which 7548 // are not struct members are not considered (e.g. array of pointers to 7549 // data). 7550 bool ShouldBeMemberOf = false; 7551 7552 // Variable keeping track of whether or not we have encountered a component 7553 // in the component list which is a member expression. Useful when we have a 7554 // pointer or a final array section, in which case it is the previous 7555 // component in the list which tells us whether we have a member expression. 7556 // E.g. X.f[:] 7557 // While processing the final array section "[:]" it is "f" which tells us 7558 // whether we are dealing with a member of a declared struct. 7559 const MemberExpr *EncounteredME = nullptr; 7560 7561 for (; I != CE; ++I) { 7562 // If the current component is member of a struct (parent struct) mark it. 7563 if (!EncounteredME) { 7564 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7565 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7566 // as MEMBER_OF the parent struct. 7567 if (EncounteredME) 7568 ShouldBeMemberOf = true; 7569 } 7570 7571 auto Next = std::next(I); 7572 7573 // We need to generate the addresses and sizes if this is the last 7574 // component, if the component is a pointer or if it is an array section 7575 // whose length can't be proved to be one. If this is a pointer, it 7576 // becomes the base address for the following components. 7577 7578 // A final array section, is one whose length can't be proved to be one. 7579 bool IsFinalArraySection = 7580 isFinalArraySectionExpression(I->getAssociatedExpression()); 7581 7582 // Get information on whether the element is a pointer. Have to do a 7583 // special treatment for array sections given that they are built-in 7584 // types. 7585 const auto *OASE = 7586 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7587 bool IsPointer = 7588 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7589 .getCanonicalType() 7590 ->isAnyPointerType()) || 7591 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7592 7593 if (Next == CE || IsPointer || IsFinalArraySection) { 7594 // If this is not the last component, we expect the pointer to be 7595 // associated with an array expression or member expression. 7596 assert((Next == CE || 7597 isa<MemberExpr>(Next->getAssociatedExpression()) || 7598 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7599 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 7600 "Unexpected expression"); 7601 7602 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7603 .getAddress(CGF); 7604 7605 // If this component is a pointer inside the base struct then we don't 7606 // need to create any entry for it - it will be combined with the object 7607 // it is pointing to into a single PTR_AND_OBJ entry. 7608 bool IsMemberPointer = 7609 IsPointer && EncounteredME && 7610 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7611 EncounteredME); 7612 if (!OverlappedElements.empty()) { 7613 // Handle base element with the info for overlapped elements. 7614 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7615 assert(Next == CE && 7616 "Expected last element for the overlapped elements."); 7617 assert(!IsPointer && 7618 "Unexpected base element with the pointer type."); 7619 // Mark the whole struct as the struct that requires allocation on the 7620 // device. 7621 PartialStruct.LowestElem = {0, LB}; 7622 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7623 I->getAssociatedExpression()->getType()); 7624 Address HB = CGF.Builder.CreateConstGEP( 7625 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7626 CGF.VoidPtrTy), 7627 TypeSize.getQuantity() - 1); 7628 PartialStruct.HighestElem = { 7629 std::numeric_limits<decltype( 7630 PartialStruct.HighestElem.first)>::max(), 7631 HB}; 7632 PartialStruct.Base = BP; 7633 // Emit data for non-overlapped data. 7634 OpenMPOffloadMappingFlags Flags = 7635 OMP_MAP_MEMBER_OF | 7636 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7637 /*AddPtrFlag=*/false, 7638 /*AddIsTargetParamFlag=*/false); 7639 LB = BP; 7640 llvm::Value *Size = nullptr; 7641 // Do bitcopy of all non-overlapped structure elements. 7642 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7643 Component : OverlappedElements) { 7644 Address ComponentLB = Address::invalid(); 7645 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7646 Component) { 7647 if (MC.getAssociatedDeclaration()) { 7648 ComponentLB = 7649 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7650 .getAddress(CGF); 7651 Size = CGF.Builder.CreatePtrDiff( 7652 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7653 CGF.EmitCastToVoidPtr(LB.getPointer())); 7654 break; 7655 } 7656 } 7657 BasePointers.push_back(BP.getPointer()); 7658 Pointers.push_back(LB.getPointer()); 7659 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7660 /*isSigned=*/true)); 7661 Types.push_back(Flags); 7662 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7663 } 7664 BasePointers.push_back(BP.getPointer()); 7665 Pointers.push_back(LB.getPointer()); 7666 Size = CGF.Builder.CreatePtrDiff( 7667 CGF.EmitCastToVoidPtr( 7668 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7669 CGF.EmitCastToVoidPtr(LB.getPointer())); 7670 Sizes.push_back( 7671 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7672 Types.push_back(Flags); 7673 break; 7674 } 7675 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7676 if (!IsMemberPointer) { 7677 BasePointers.push_back(BP.getPointer()); 7678 Pointers.push_back(LB.getPointer()); 7679 Sizes.push_back( 7680 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7681 7682 // We need to add a pointer flag for each map that comes from the 7683 // same expression except for the first one. We also need to signal 7684 // this map is the first one that relates with the current capture 7685 // (there is a set of entries for each capture). 7686 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7687 MapType, MapModifiers, IsImplicit, 7688 !IsExpressionFirstInfo || RequiresReference, 7689 IsCaptureFirstInfo && !RequiresReference); 7690 7691 if (!IsExpressionFirstInfo) { 7692 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7693 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7694 if (IsPointer) 7695 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7696 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7697 7698 if (ShouldBeMemberOf) { 7699 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7700 // should be later updated with the correct value of MEMBER_OF. 7701 Flags |= OMP_MAP_MEMBER_OF; 7702 // From now on, all subsequent PTR_AND_OBJ entries should not be 7703 // marked as MEMBER_OF. 7704 ShouldBeMemberOf = false; 7705 } 7706 } 7707 7708 Types.push_back(Flags); 7709 } 7710 7711 // If we have encountered a member expression so far, keep track of the 7712 // mapped member. If the parent is "*this", then the value declaration 7713 // is nullptr. 7714 if (EncounteredME) { 7715 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); 7716 unsigned FieldIndex = FD->getFieldIndex(); 7717 7718 // Update info about the lowest and highest elements for this struct 7719 if (!PartialStruct.Base.isValid()) { 7720 PartialStruct.LowestElem = {FieldIndex, LB}; 7721 PartialStruct.HighestElem = {FieldIndex, LB}; 7722 PartialStruct.Base = BP; 7723 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7724 PartialStruct.LowestElem = {FieldIndex, LB}; 7725 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7726 PartialStruct.HighestElem = {FieldIndex, LB}; 7727 } 7728 } 7729 7730 // If we have a final array section, we are done with this expression. 7731 if (IsFinalArraySection) 7732 break; 7733 7734 // The pointer becomes the base for the next element. 7735 if (Next != CE) 7736 BP = LB; 7737 7738 IsExpressionFirstInfo = false; 7739 IsCaptureFirstInfo = false; 7740 } 7741 } 7742 } 7743 7744 /// Return the adjusted map modifiers if the declaration a capture refers to 7745 /// appears in a first-private clause. This is expected to be used only with 7746 /// directives that start with 'target'. 7747 MappableExprsHandler::OpenMPOffloadMappingFlags 7748 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7749 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7750 7751 // A first private variable captured by reference will use only the 7752 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7753 // declaration is known as first-private in this handler. 7754 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7755 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7756 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7757 return MappableExprsHandler::OMP_MAP_ALWAYS | 7758 MappableExprsHandler::OMP_MAP_TO; 7759 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7760 return MappableExprsHandler::OMP_MAP_TO | 7761 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7762 return MappableExprsHandler::OMP_MAP_PRIVATE | 7763 MappableExprsHandler::OMP_MAP_TO; 7764 } 7765 return MappableExprsHandler::OMP_MAP_TO | 7766 MappableExprsHandler::OMP_MAP_FROM; 7767 } 7768 7769 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7770 // Rotate by getFlagMemberOffset() bits. 7771 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7772 << getFlagMemberOffset()); 7773 } 7774 7775 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7776 OpenMPOffloadMappingFlags MemberOfFlag) { 7777 // If the entry is PTR_AND_OBJ but has not been marked with the special 7778 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7779 // marked as MEMBER_OF. 7780 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7781 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7782 return; 7783 7784 // Reset the placeholder value to prepare the flag for the assignment of the 7785 // proper MEMBER_OF value. 7786 Flags &= ~OMP_MAP_MEMBER_OF; 7787 Flags |= MemberOfFlag; 7788 } 7789 7790 void getPlainLayout(const CXXRecordDecl *RD, 7791 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7792 bool AsBase) const { 7793 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7794 7795 llvm::StructType *St = 7796 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7797 7798 unsigned NumElements = St->getNumElements(); 7799 llvm::SmallVector< 7800 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7801 RecordLayout(NumElements); 7802 7803 // Fill bases. 7804 for (const auto &I : RD->bases()) { 7805 if (I.isVirtual()) 7806 continue; 7807 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7808 // Ignore empty bases. 7809 if (Base->isEmpty() || CGF.getContext() 7810 .getASTRecordLayout(Base) 7811 .getNonVirtualSize() 7812 .isZero()) 7813 continue; 7814 7815 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7816 RecordLayout[FieldIndex] = Base; 7817 } 7818 // Fill in virtual bases. 7819 for (const auto &I : RD->vbases()) { 7820 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7821 // Ignore empty bases. 7822 if (Base->isEmpty()) 7823 continue; 7824 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7825 if (RecordLayout[FieldIndex]) 7826 continue; 7827 RecordLayout[FieldIndex] = Base; 7828 } 7829 // Fill in all the fields. 7830 assert(!RD->isUnion() && "Unexpected union."); 7831 for (const auto *Field : RD->fields()) { 7832 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7833 // will fill in later.) 7834 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7835 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7836 RecordLayout[FieldIndex] = Field; 7837 } 7838 } 7839 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7840 &Data : RecordLayout) { 7841 if (Data.isNull()) 7842 continue; 7843 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7844 getPlainLayout(Base, Layout, /*AsBase=*/true); 7845 else 7846 Layout.push_back(Data.get<const FieldDecl *>()); 7847 } 7848 } 7849 7850 public: 7851 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7852 : CurDir(&Dir), CGF(CGF) { 7853 // Extract firstprivate clause information. 7854 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7855 for (const auto *D : C->varlists()) 7856 FirstPrivateDecls.try_emplace( 7857 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 7858 // Extract device pointer clause information. 7859 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7860 for (auto L : C->component_lists()) 7861 DevPointersMap[L.first].push_back(L.second); 7862 } 7863 7864 /// Constructor for the declare mapper directive. 7865 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 7866 : CurDir(&Dir), CGF(CGF) {} 7867 7868 /// Generate code for the combined entry if we have a partially mapped struct 7869 /// and take care of the mapping flags of the arguments corresponding to 7870 /// individual struct members. 7871 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 7872 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7873 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 7874 const StructRangeInfoTy &PartialStruct) const { 7875 // Base is the base of the struct 7876 BasePointers.push_back(PartialStruct.Base.getPointer()); 7877 // Pointer is the address of the lowest element 7878 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7879 Pointers.push_back(LB); 7880 // Size is (addr of {highest+1} element) - (addr of lowest element) 7881 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7882 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7883 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7884 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7885 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7886 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 7887 /*isSigned=*/false); 7888 Sizes.push_back(Size); 7889 // Map type is always TARGET_PARAM 7890 Types.push_back(OMP_MAP_TARGET_PARAM); 7891 // Remove TARGET_PARAM flag from the first element 7892 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7893 7894 // All other current entries will be MEMBER_OF the combined entry 7895 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7896 // 0xFFFF in the MEMBER_OF field). 7897 OpenMPOffloadMappingFlags MemberOfFlag = 7898 getMemberOfFlag(BasePointers.size() - 1); 7899 for (auto &M : CurTypes) 7900 setCorrectMemberOfFlag(M, MemberOfFlag); 7901 } 7902 7903 /// Generate all the base pointers, section pointers, sizes and map 7904 /// types for the extracted mappable expressions. Also, for each item that 7905 /// relates with a device pointer, a pair of the relevant declaration and 7906 /// index where it occurs is appended to the device pointers info array. 7907 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 7908 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7909 MapFlagsArrayTy &Types) const { 7910 // We have to process the component lists that relate with the same 7911 // declaration in a single chunk so that we can generate the map flags 7912 // correctly. Therefore, we organize all lists in a map. 7913 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7914 7915 // Helper function to fill the information map for the different supported 7916 // clauses. 7917 auto &&InfoGen = [&Info]( 7918 const ValueDecl *D, 7919 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7920 OpenMPMapClauseKind MapType, 7921 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7922 bool ReturnDevicePointer, bool IsImplicit) { 7923 const ValueDecl *VD = 7924 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7925 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7926 IsImplicit); 7927 }; 7928 7929 assert(CurDir.is<const OMPExecutableDirective *>() && 7930 "Expect a executable directive"); 7931 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 7932 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 7933 for (const auto L : C->component_lists()) { 7934 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 7935 /*ReturnDevicePointer=*/false, C->isImplicit()); 7936 } 7937 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 7938 for (const auto L : C->component_lists()) { 7939 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 7940 /*ReturnDevicePointer=*/false, C->isImplicit()); 7941 } 7942 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 7943 for (const auto L : C->component_lists()) { 7944 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 7945 /*ReturnDevicePointer=*/false, C->isImplicit()); 7946 } 7947 7948 // Look at the use_device_ptr clause information and mark the existing map 7949 // entries as such. If there is no map information for an entry in the 7950 // use_device_ptr list, we create one with map type 'alloc' and zero size 7951 // section. It is the user fault if that was not mapped before. If there is 7952 // no map information and the pointer is a struct member, then we defer the 7953 // emission of that entry until the whole struct has been processed. 7954 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 7955 DeferredInfo; 7956 7957 for (const auto *C : 7958 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 7959 for (const auto L : C->component_lists()) { 7960 assert(!L.second.empty() && "Not expecting empty list of components!"); 7961 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 7962 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 7963 const Expr *IE = L.second.back().getAssociatedExpression(); 7964 // If the first component is a member expression, we have to look into 7965 // 'this', which maps to null in the map of map information. Otherwise 7966 // look directly for the information. 7967 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 7968 7969 // We potentially have map information for this declaration already. 7970 // Look for the first set of components that refer to it. 7971 if (It != Info.end()) { 7972 auto CI = std::find_if( 7973 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 7974 return MI.Components.back().getAssociatedDeclaration() == VD; 7975 }); 7976 // If we found a map entry, signal that the pointer has to be returned 7977 // and move on to the next declaration. 7978 if (CI != It->second.end()) { 7979 CI->ReturnDevicePointer = true; 7980 continue; 7981 } 7982 } 7983 7984 // We didn't find any match in our map information - generate a zero 7985 // size array section - if the pointer is a struct member we defer this 7986 // action until the whole struct has been processed. 7987 if (isa<MemberExpr>(IE)) { 7988 // Insert the pointer into Info to be processed by 7989 // generateInfoForComponentList. Because it is a member pointer 7990 // without a pointee, no entry will be generated for it, therefore 7991 // we need to generate one after the whole struct has been processed. 7992 // Nonetheless, generateInfoForComponentList must be called to take 7993 // the pointer into account for the calculation of the range of the 7994 // partial struct. 7995 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 7996 /*ReturnDevicePointer=*/false, C->isImplicit()); 7997 DeferredInfo[nullptr].emplace_back(IE, VD); 7998 } else { 7999 llvm::Value *Ptr = 8000 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8001 BasePointers.emplace_back(Ptr, VD); 8002 Pointers.push_back(Ptr); 8003 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8004 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8005 } 8006 } 8007 } 8008 8009 for (const auto &M : Info) { 8010 // We need to know when we generate information for the first component 8011 // associated with a capture, because the mapping flags depend on it. 8012 bool IsFirstComponentList = true; 8013 8014 // Temporary versions of arrays 8015 MapBaseValuesArrayTy CurBasePointers; 8016 MapValuesArrayTy CurPointers; 8017 MapValuesArrayTy CurSizes; 8018 MapFlagsArrayTy CurTypes; 8019 StructRangeInfoTy PartialStruct; 8020 8021 for (const MapInfo &L : M.second) { 8022 assert(!L.Components.empty() && 8023 "Not expecting declaration with no component lists."); 8024 8025 // Remember the current base pointer index. 8026 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8027 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8028 CurBasePointers, CurPointers, CurSizes, 8029 CurTypes, PartialStruct, 8030 IsFirstComponentList, L.IsImplicit); 8031 8032 // If this entry relates with a device pointer, set the relevant 8033 // declaration and add the 'return pointer' flag. 8034 if (L.ReturnDevicePointer) { 8035 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8036 "Unexpected number of mapped base pointers."); 8037 8038 const ValueDecl *RelevantVD = 8039 L.Components.back().getAssociatedDeclaration(); 8040 assert(RelevantVD && 8041 "No relevant declaration related with device pointer??"); 8042 8043 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8044 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8045 } 8046 IsFirstComponentList = false; 8047 } 8048 8049 // Append any pending zero-length pointers which are struct members and 8050 // used with use_device_ptr. 8051 auto CI = DeferredInfo.find(M.first); 8052 if (CI != DeferredInfo.end()) { 8053 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8054 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8055 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8056 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8057 CurBasePointers.emplace_back(BasePtr, L.VD); 8058 CurPointers.push_back(Ptr); 8059 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8060 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8061 // value MEMBER_OF=FFFF so that the entry is later updated with the 8062 // correct value of MEMBER_OF. 8063 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8064 OMP_MAP_MEMBER_OF); 8065 } 8066 } 8067 8068 // If there is an entry in PartialStruct it means we have a struct with 8069 // individual members mapped. Emit an extra combined entry. 8070 if (PartialStruct.Base.isValid()) 8071 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8072 PartialStruct); 8073 8074 // We need to append the results of this capture to what we already have. 8075 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8076 Pointers.append(CurPointers.begin(), CurPointers.end()); 8077 Sizes.append(CurSizes.begin(), CurSizes.end()); 8078 Types.append(CurTypes.begin(), CurTypes.end()); 8079 } 8080 } 8081 8082 /// Generate all the base pointers, section pointers, sizes and map types for 8083 /// the extracted map clauses of user-defined mapper. 8084 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8085 MapValuesArrayTy &Pointers, 8086 MapValuesArrayTy &Sizes, 8087 MapFlagsArrayTy &Types) const { 8088 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8089 "Expect a declare mapper directive"); 8090 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8091 // We have to process the component lists that relate with the same 8092 // declaration in a single chunk so that we can generate the map flags 8093 // correctly. Therefore, we organize all lists in a map. 8094 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8095 8096 // Helper function to fill the information map for the different supported 8097 // clauses. 8098 auto &&InfoGen = [&Info]( 8099 const ValueDecl *D, 8100 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8101 OpenMPMapClauseKind MapType, 8102 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8103 bool ReturnDevicePointer, bool IsImplicit) { 8104 const ValueDecl *VD = 8105 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8106 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8107 IsImplicit); 8108 }; 8109 8110 for (const auto *C : CurMapperDir->clauselists()) { 8111 const auto *MC = cast<OMPMapClause>(C); 8112 for (const auto L : MC->component_lists()) { 8113 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8114 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8115 } 8116 } 8117 8118 for (const auto &M : Info) { 8119 // We need to know when we generate information for the first component 8120 // associated with a capture, because the mapping flags depend on it. 8121 bool IsFirstComponentList = true; 8122 8123 // Temporary versions of arrays 8124 MapBaseValuesArrayTy CurBasePointers; 8125 MapValuesArrayTy CurPointers; 8126 MapValuesArrayTy CurSizes; 8127 MapFlagsArrayTy CurTypes; 8128 StructRangeInfoTy PartialStruct; 8129 8130 for (const MapInfo &L : M.second) { 8131 assert(!L.Components.empty() && 8132 "Not expecting declaration with no component lists."); 8133 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8134 CurBasePointers, CurPointers, CurSizes, 8135 CurTypes, PartialStruct, 8136 IsFirstComponentList, L.IsImplicit); 8137 IsFirstComponentList = false; 8138 } 8139 8140 // If there is an entry in PartialStruct it means we have a struct with 8141 // individual members mapped. Emit an extra combined entry. 8142 if (PartialStruct.Base.isValid()) 8143 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8144 PartialStruct); 8145 8146 // We need to append the results of this capture to what we already have. 8147 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8148 Pointers.append(CurPointers.begin(), CurPointers.end()); 8149 Sizes.append(CurSizes.begin(), CurSizes.end()); 8150 Types.append(CurTypes.begin(), CurTypes.end()); 8151 } 8152 } 8153 8154 /// Emit capture info for lambdas for variables captured by reference. 8155 void generateInfoForLambdaCaptures( 8156 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8157 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8158 MapFlagsArrayTy &Types, 8159 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8160 const auto *RD = VD->getType() 8161 .getCanonicalType() 8162 .getNonReferenceType() 8163 ->getAsCXXRecordDecl(); 8164 if (!RD || !RD->isLambda()) 8165 return; 8166 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8167 LValue VDLVal = CGF.MakeAddrLValue( 8168 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8169 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8170 FieldDecl *ThisCapture = nullptr; 8171 RD->getCaptureFields(Captures, ThisCapture); 8172 if (ThisCapture) { 8173 LValue ThisLVal = 8174 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8175 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8176 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8177 VDLVal.getPointer(CGF)); 8178 BasePointers.push_back(ThisLVal.getPointer(CGF)); 8179 Pointers.push_back(ThisLValVal.getPointer(CGF)); 8180 Sizes.push_back( 8181 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8182 CGF.Int64Ty, /*isSigned=*/true)); 8183 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8184 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8185 } 8186 for (const LambdaCapture &LC : RD->captures()) { 8187 if (!LC.capturesVariable()) 8188 continue; 8189 const VarDecl *VD = LC.getCapturedVar(); 8190 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8191 continue; 8192 auto It = Captures.find(VD); 8193 assert(It != Captures.end() && "Found lambda capture without field."); 8194 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8195 if (LC.getCaptureKind() == LCK_ByRef) { 8196 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8197 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8198 VDLVal.getPointer(CGF)); 8199 BasePointers.push_back(VarLVal.getPointer(CGF)); 8200 Pointers.push_back(VarLValVal.getPointer(CGF)); 8201 Sizes.push_back(CGF.Builder.CreateIntCast( 8202 CGF.getTypeSize( 8203 VD->getType().getCanonicalType().getNonReferenceType()), 8204 CGF.Int64Ty, /*isSigned=*/true)); 8205 } else { 8206 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8207 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8208 VDLVal.getPointer(CGF)); 8209 BasePointers.push_back(VarLVal.getPointer(CGF)); 8210 Pointers.push_back(VarRVal.getScalarVal()); 8211 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8212 } 8213 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8214 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8215 } 8216 } 8217 8218 /// Set correct indices for lambdas captures. 8219 void adjustMemberOfForLambdaCaptures( 8220 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8221 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8222 MapFlagsArrayTy &Types) const { 8223 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8224 // Set correct member_of idx for all implicit lambda captures. 8225 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8226 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8227 continue; 8228 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8229 assert(BasePtr && "Unable to find base lambda address."); 8230 int TgtIdx = -1; 8231 for (unsigned J = I; J > 0; --J) { 8232 unsigned Idx = J - 1; 8233 if (Pointers[Idx] != BasePtr) 8234 continue; 8235 TgtIdx = Idx; 8236 break; 8237 } 8238 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8239 // All other current entries will be MEMBER_OF the combined entry 8240 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8241 // 0xFFFF in the MEMBER_OF field). 8242 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8243 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8244 } 8245 } 8246 8247 /// Generate the base pointers, section pointers, sizes and map types 8248 /// associated to a given capture. 8249 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8250 llvm::Value *Arg, 8251 MapBaseValuesArrayTy &BasePointers, 8252 MapValuesArrayTy &Pointers, 8253 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8254 StructRangeInfoTy &PartialStruct) const { 8255 assert(!Cap->capturesVariableArrayType() && 8256 "Not expecting to generate map info for a variable array type!"); 8257 8258 // We need to know when we generating information for the first component 8259 const ValueDecl *VD = Cap->capturesThis() 8260 ? nullptr 8261 : Cap->getCapturedVar()->getCanonicalDecl(); 8262 8263 // If this declaration appears in a is_device_ptr clause we just have to 8264 // pass the pointer by value. If it is a reference to a declaration, we just 8265 // pass its value. 8266 if (DevPointersMap.count(VD)) { 8267 BasePointers.emplace_back(Arg, VD); 8268 Pointers.push_back(Arg); 8269 Sizes.push_back( 8270 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8271 CGF.Int64Ty, /*isSigned=*/true)); 8272 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8273 return; 8274 } 8275 8276 using MapData = 8277 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8278 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8279 SmallVector<MapData, 4> DeclComponentLists; 8280 assert(CurDir.is<const OMPExecutableDirective *>() && 8281 "Expect a executable directive"); 8282 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8283 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8284 for (const auto L : C->decl_component_lists(VD)) { 8285 assert(L.first == VD && 8286 "We got information for the wrong declaration??"); 8287 assert(!L.second.empty() && 8288 "Not expecting declaration with no component lists."); 8289 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8290 C->getMapTypeModifiers(), 8291 C->isImplicit()); 8292 } 8293 } 8294 8295 // Find overlapping elements (including the offset from the base element). 8296 llvm::SmallDenseMap< 8297 const MapData *, 8298 llvm::SmallVector< 8299 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8300 4> 8301 OverlappedData; 8302 size_t Count = 0; 8303 for (const MapData &L : DeclComponentLists) { 8304 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8305 OpenMPMapClauseKind MapType; 8306 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8307 bool IsImplicit; 8308 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8309 ++Count; 8310 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8311 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8312 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8313 auto CI = Components.rbegin(); 8314 auto CE = Components.rend(); 8315 auto SI = Components1.rbegin(); 8316 auto SE = Components1.rend(); 8317 for (; CI != CE && SI != SE; ++CI, ++SI) { 8318 if (CI->getAssociatedExpression()->getStmtClass() != 8319 SI->getAssociatedExpression()->getStmtClass()) 8320 break; 8321 // Are we dealing with different variables/fields? 8322 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8323 break; 8324 } 8325 // Found overlapping if, at least for one component, reached the head of 8326 // the components list. 8327 if (CI == CE || SI == SE) { 8328 assert((CI != CE || SI != SE) && 8329 "Unexpected full match of the mapping components."); 8330 const MapData &BaseData = CI == CE ? L : L1; 8331 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8332 SI == SE ? Components : Components1; 8333 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8334 OverlappedElements.getSecond().push_back(SubData); 8335 } 8336 } 8337 } 8338 // Sort the overlapped elements for each item. 8339 llvm::SmallVector<const FieldDecl *, 4> Layout; 8340 if (!OverlappedData.empty()) { 8341 if (const auto *CRD = 8342 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8343 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8344 else { 8345 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8346 Layout.append(RD->field_begin(), RD->field_end()); 8347 } 8348 } 8349 for (auto &Pair : OverlappedData) { 8350 llvm::sort( 8351 Pair.getSecond(), 8352 [&Layout]( 8353 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8354 OMPClauseMappableExprCommon::MappableExprComponentListRef 8355 Second) { 8356 auto CI = First.rbegin(); 8357 auto CE = First.rend(); 8358 auto SI = Second.rbegin(); 8359 auto SE = Second.rend(); 8360 for (; CI != CE && SI != SE; ++CI, ++SI) { 8361 if (CI->getAssociatedExpression()->getStmtClass() != 8362 SI->getAssociatedExpression()->getStmtClass()) 8363 break; 8364 // Are we dealing with different variables/fields? 8365 if (CI->getAssociatedDeclaration() != 8366 SI->getAssociatedDeclaration()) 8367 break; 8368 } 8369 8370 // Lists contain the same elements. 8371 if (CI == CE && SI == SE) 8372 return false; 8373 8374 // List with less elements is less than list with more elements. 8375 if (CI == CE || SI == SE) 8376 return CI == CE; 8377 8378 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8379 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8380 if (FD1->getParent() == FD2->getParent()) 8381 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8382 const auto It = 8383 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8384 return FD == FD1 || FD == FD2; 8385 }); 8386 return *It == FD1; 8387 }); 8388 } 8389 8390 // Associated with a capture, because the mapping flags depend on it. 8391 // Go through all of the elements with the overlapped elements. 8392 for (const auto &Pair : OverlappedData) { 8393 const MapData &L = *Pair.getFirst(); 8394 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8395 OpenMPMapClauseKind MapType; 8396 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8397 bool IsImplicit; 8398 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8399 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8400 OverlappedComponents = Pair.getSecond(); 8401 bool IsFirstComponentList = true; 8402 generateInfoForComponentList(MapType, MapModifiers, Components, 8403 BasePointers, Pointers, Sizes, Types, 8404 PartialStruct, IsFirstComponentList, 8405 IsImplicit, OverlappedComponents); 8406 } 8407 // Go through other elements without overlapped elements. 8408 bool IsFirstComponentList = OverlappedData.empty(); 8409 for (const MapData &L : DeclComponentLists) { 8410 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8411 OpenMPMapClauseKind MapType; 8412 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8413 bool IsImplicit; 8414 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8415 auto It = OverlappedData.find(&L); 8416 if (It == OverlappedData.end()) 8417 generateInfoForComponentList(MapType, MapModifiers, Components, 8418 BasePointers, Pointers, Sizes, Types, 8419 PartialStruct, IsFirstComponentList, 8420 IsImplicit); 8421 IsFirstComponentList = false; 8422 } 8423 } 8424 8425 /// Generate the base pointers, section pointers, sizes and map types 8426 /// associated with the declare target link variables. 8427 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8428 MapValuesArrayTy &Pointers, 8429 MapValuesArrayTy &Sizes, 8430 MapFlagsArrayTy &Types) const { 8431 assert(CurDir.is<const OMPExecutableDirective *>() && 8432 "Expect a executable directive"); 8433 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8434 // Map other list items in the map clause which are not captured variables 8435 // but "declare target link" global variables. 8436 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8437 for (const auto L : C->component_lists()) { 8438 if (!L.first) 8439 continue; 8440 const auto *VD = dyn_cast<VarDecl>(L.first); 8441 if (!VD) 8442 continue; 8443 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8444 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8445 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8446 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8447 continue; 8448 StructRangeInfoTy PartialStruct; 8449 generateInfoForComponentList( 8450 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8451 Pointers, Sizes, Types, PartialStruct, 8452 /*IsFirstComponentList=*/true, C->isImplicit()); 8453 assert(!PartialStruct.Base.isValid() && 8454 "No partial structs for declare target link expected."); 8455 } 8456 } 8457 } 8458 8459 /// Generate the default map information for a given capture \a CI, 8460 /// record field declaration \a RI and captured value \a CV. 8461 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8462 const FieldDecl &RI, llvm::Value *CV, 8463 MapBaseValuesArrayTy &CurBasePointers, 8464 MapValuesArrayTy &CurPointers, 8465 MapValuesArrayTy &CurSizes, 8466 MapFlagsArrayTy &CurMapTypes) const { 8467 bool IsImplicit = true; 8468 // Do the default mapping. 8469 if (CI.capturesThis()) { 8470 CurBasePointers.push_back(CV); 8471 CurPointers.push_back(CV); 8472 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8473 CurSizes.push_back( 8474 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8475 CGF.Int64Ty, /*isSigned=*/true)); 8476 // Default map type. 8477 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8478 } else if (CI.capturesVariableByCopy()) { 8479 CurBasePointers.push_back(CV); 8480 CurPointers.push_back(CV); 8481 if (!RI.getType()->isAnyPointerType()) { 8482 // We have to signal to the runtime captures passed by value that are 8483 // not pointers. 8484 CurMapTypes.push_back(OMP_MAP_LITERAL); 8485 CurSizes.push_back(CGF.Builder.CreateIntCast( 8486 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8487 } else { 8488 // Pointers are implicitly mapped with a zero size and no flags 8489 // (other than first map that is added for all implicit maps). 8490 CurMapTypes.push_back(OMP_MAP_NONE); 8491 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8492 } 8493 const VarDecl *VD = CI.getCapturedVar(); 8494 auto I = FirstPrivateDecls.find(VD); 8495 if (I != FirstPrivateDecls.end()) 8496 IsImplicit = I->getSecond(); 8497 } else { 8498 assert(CI.capturesVariable() && "Expected captured reference."); 8499 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8500 QualType ElementType = PtrTy->getPointeeType(); 8501 CurSizes.push_back(CGF.Builder.CreateIntCast( 8502 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8503 // The default map type for a scalar/complex type is 'to' because by 8504 // default the value doesn't have to be retrieved. For an aggregate 8505 // type, the default is 'tofrom'. 8506 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8507 const VarDecl *VD = CI.getCapturedVar(); 8508 auto I = FirstPrivateDecls.find(VD); 8509 if (I != FirstPrivateDecls.end() && 8510 VD->getType().isConstant(CGF.getContext())) { 8511 llvm::Constant *Addr = 8512 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8513 // Copy the value of the original variable to the new global copy. 8514 CGF.Builder.CreateMemCpy( 8515 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 8516 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8517 CurSizes.back(), /*IsVolatile=*/false); 8518 // Use new global variable as the base pointers. 8519 CurBasePointers.push_back(Addr); 8520 CurPointers.push_back(Addr); 8521 } else { 8522 CurBasePointers.push_back(CV); 8523 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8524 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8525 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8526 AlignmentSource::Decl)); 8527 CurPointers.push_back(PtrAddr.getPointer()); 8528 } else { 8529 CurPointers.push_back(CV); 8530 } 8531 } 8532 if (I != FirstPrivateDecls.end()) 8533 IsImplicit = I->getSecond(); 8534 } 8535 // Every default map produces a single argument which is a target parameter. 8536 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8537 8538 // Add flag stating this is an implicit map. 8539 if (IsImplicit) 8540 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8541 } 8542 }; 8543 } // anonymous namespace 8544 8545 /// Emit the arrays used to pass the captures and map information to the 8546 /// offloading runtime library. If there is no map or capture information, 8547 /// return nullptr by reference. 8548 static void 8549 emitOffloadingArrays(CodeGenFunction &CGF, 8550 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8551 MappableExprsHandler::MapValuesArrayTy &Pointers, 8552 MappableExprsHandler::MapValuesArrayTy &Sizes, 8553 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8554 CGOpenMPRuntime::TargetDataInfo &Info) { 8555 CodeGenModule &CGM = CGF.CGM; 8556 ASTContext &Ctx = CGF.getContext(); 8557 8558 // Reset the array information. 8559 Info.clearArrayInfo(); 8560 Info.NumberOfPtrs = BasePointers.size(); 8561 8562 if (Info.NumberOfPtrs) { 8563 // Detect if we have any capture size requiring runtime evaluation of the 8564 // size so that a constant array could be eventually used. 8565 bool hasRuntimeEvaluationCaptureSize = false; 8566 for (llvm::Value *S : Sizes) 8567 if (!isa<llvm::Constant>(S)) { 8568 hasRuntimeEvaluationCaptureSize = true; 8569 break; 8570 } 8571 8572 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8573 QualType PointerArrayType = Ctx.getConstantArrayType( 8574 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8575 /*IndexTypeQuals=*/0); 8576 8577 Info.BasePointersArray = 8578 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8579 Info.PointersArray = 8580 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8581 8582 // If we don't have any VLA types or other types that require runtime 8583 // evaluation, we can use a constant array for the map sizes, otherwise we 8584 // need to fill up the arrays as we do for the pointers. 8585 QualType Int64Ty = 8586 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8587 if (hasRuntimeEvaluationCaptureSize) { 8588 QualType SizeArrayType = Ctx.getConstantArrayType( 8589 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8590 /*IndexTypeQuals=*/0); 8591 Info.SizesArray = 8592 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8593 } else { 8594 // We expect all the sizes to be constant, so we collect them to create 8595 // a constant array. 8596 SmallVector<llvm::Constant *, 16> ConstSizes; 8597 for (llvm::Value *S : Sizes) 8598 ConstSizes.push_back(cast<llvm::Constant>(S)); 8599 8600 auto *SizesArrayInit = llvm::ConstantArray::get( 8601 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8602 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8603 auto *SizesArrayGbl = new llvm::GlobalVariable( 8604 CGM.getModule(), SizesArrayInit->getType(), 8605 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8606 SizesArrayInit, Name); 8607 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8608 Info.SizesArray = SizesArrayGbl; 8609 } 8610 8611 // The map types are always constant so we don't need to generate code to 8612 // fill arrays. Instead, we create an array constant. 8613 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8614 llvm::copy(MapTypes, Mapping.begin()); 8615 llvm::Constant *MapTypesArrayInit = 8616 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8617 std::string MaptypesName = 8618 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8619 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8620 CGM.getModule(), MapTypesArrayInit->getType(), 8621 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8622 MapTypesArrayInit, MaptypesName); 8623 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8624 Info.MapTypesArray = MapTypesArrayGbl; 8625 8626 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8627 llvm::Value *BPVal = *BasePointers[I]; 8628 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8629 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8630 Info.BasePointersArray, 0, I); 8631 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8632 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8633 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8634 CGF.Builder.CreateStore(BPVal, BPAddr); 8635 8636 if (Info.requiresDevicePointerInfo()) 8637 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8638 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8639 8640 llvm::Value *PVal = Pointers[I]; 8641 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8642 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8643 Info.PointersArray, 0, I); 8644 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8645 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8646 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8647 CGF.Builder.CreateStore(PVal, PAddr); 8648 8649 if (hasRuntimeEvaluationCaptureSize) { 8650 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8651 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8652 Info.SizesArray, 8653 /*Idx0=*/0, 8654 /*Idx1=*/I); 8655 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8656 CGF.Builder.CreateStore( 8657 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8658 SAddr); 8659 } 8660 } 8661 } 8662 } 8663 8664 /// Emit the arguments to be passed to the runtime library based on the 8665 /// arrays of pointers, sizes and map types. 8666 static void emitOffloadingArraysArgument( 8667 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8668 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8669 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8670 CodeGenModule &CGM = CGF.CGM; 8671 if (Info.NumberOfPtrs) { 8672 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8673 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8674 Info.BasePointersArray, 8675 /*Idx0=*/0, /*Idx1=*/0); 8676 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8677 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8678 Info.PointersArray, 8679 /*Idx0=*/0, 8680 /*Idx1=*/0); 8681 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8682 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8683 /*Idx0=*/0, /*Idx1=*/0); 8684 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8685 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8686 Info.MapTypesArray, 8687 /*Idx0=*/0, 8688 /*Idx1=*/0); 8689 } else { 8690 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8691 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8692 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8693 MapTypesArrayArg = 8694 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8695 } 8696 } 8697 8698 /// Check for inner distribute directive. 8699 static const OMPExecutableDirective * 8700 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8701 const auto *CS = D.getInnermostCapturedStmt(); 8702 const auto *Body = 8703 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8704 const Stmt *ChildStmt = 8705 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8706 8707 if (const auto *NestedDir = 8708 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8709 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8710 switch (D.getDirectiveKind()) { 8711 case OMPD_target: 8712 if (isOpenMPDistributeDirective(DKind)) 8713 return NestedDir; 8714 if (DKind == OMPD_teams) { 8715 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8716 /*IgnoreCaptured=*/true); 8717 if (!Body) 8718 return nullptr; 8719 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8720 if (const auto *NND = 8721 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8722 DKind = NND->getDirectiveKind(); 8723 if (isOpenMPDistributeDirective(DKind)) 8724 return NND; 8725 } 8726 } 8727 return nullptr; 8728 case OMPD_target_teams: 8729 if (isOpenMPDistributeDirective(DKind)) 8730 return NestedDir; 8731 return nullptr; 8732 case OMPD_target_parallel: 8733 case OMPD_target_simd: 8734 case OMPD_target_parallel_for: 8735 case OMPD_target_parallel_for_simd: 8736 return nullptr; 8737 case OMPD_target_teams_distribute: 8738 case OMPD_target_teams_distribute_simd: 8739 case OMPD_target_teams_distribute_parallel_for: 8740 case OMPD_target_teams_distribute_parallel_for_simd: 8741 case OMPD_parallel: 8742 case OMPD_for: 8743 case OMPD_parallel_for: 8744 case OMPD_parallel_master: 8745 case OMPD_parallel_sections: 8746 case OMPD_for_simd: 8747 case OMPD_parallel_for_simd: 8748 case OMPD_cancel: 8749 case OMPD_cancellation_point: 8750 case OMPD_ordered: 8751 case OMPD_threadprivate: 8752 case OMPD_allocate: 8753 case OMPD_task: 8754 case OMPD_simd: 8755 case OMPD_sections: 8756 case OMPD_section: 8757 case OMPD_single: 8758 case OMPD_master: 8759 case OMPD_critical: 8760 case OMPD_taskyield: 8761 case OMPD_barrier: 8762 case OMPD_taskwait: 8763 case OMPD_taskgroup: 8764 case OMPD_atomic: 8765 case OMPD_flush: 8766 case OMPD_teams: 8767 case OMPD_target_data: 8768 case OMPD_target_exit_data: 8769 case OMPD_target_enter_data: 8770 case OMPD_distribute: 8771 case OMPD_distribute_simd: 8772 case OMPD_distribute_parallel_for: 8773 case OMPD_distribute_parallel_for_simd: 8774 case OMPD_teams_distribute: 8775 case OMPD_teams_distribute_simd: 8776 case OMPD_teams_distribute_parallel_for: 8777 case OMPD_teams_distribute_parallel_for_simd: 8778 case OMPD_target_update: 8779 case OMPD_declare_simd: 8780 case OMPD_declare_variant: 8781 case OMPD_declare_target: 8782 case OMPD_end_declare_target: 8783 case OMPD_declare_reduction: 8784 case OMPD_declare_mapper: 8785 case OMPD_taskloop: 8786 case OMPD_taskloop_simd: 8787 case OMPD_master_taskloop: 8788 case OMPD_master_taskloop_simd: 8789 case OMPD_parallel_master_taskloop: 8790 case OMPD_parallel_master_taskloop_simd: 8791 case OMPD_requires: 8792 case OMPD_unknown: 8793 llvm_unreachable("Unexpected directive."); 8794 } 8795 } 8796 8797 return nullptr; 8798 } 8799 8800 /// Emit the user-defined mapper function. The code generation follows the 8801 /// pattern in the example below. 8802 /// \code 8803 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8804 /// void *base, void *begin, 8805 /// int64_t size, int64_t type) { 8806 /// // Allocate space for an array section first. 8807 /// if (size > 1 && !maptype.IsDelete) 8808 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8809 /// size*sizeof(Ty), clearToFrom(type)); 8810 /// // Map members. 8811 /// for (unsigned i = 0; i < size; i++) { 8812 /// // For each component specified by this mapper: 8813 /// for (auto c : all_components) { 8814 /// if (c.hasMapper()) 8815 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8816 /// c.arg_type); 8817 /// else 8818 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8819 /// c.arg_begin, c.arg_size, c.arg_type); 8820 /// } 8821 /// } 8822 /// // Delete the array section. 8823 /// if (size > 1 && maptype.IsDelete) 8824 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8825 /// size*sizeof(Ty), clearToFrom(type)); 8826 /// } 8827 /// \endcode 8828 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8829 CodeGenFunction *CGF) { 8830 if (UDMMap.count(D) > 0) 8831 return; 8832 ASTContext &C = CGM.getContext(); 8833 QualType Ty = D->getType(); 8834 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8835 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8836 auto *MapperVarDecl = 8837 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8838 SourceLocation Loc = D->getLocation(); 8839 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8840 8841 // Prepare mapper function arguments and attributes. 8842 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8843 C.VoidPtrTy, ImplicitParamDecl::Other); 8844 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8845 ImplicitParamDecl::Other); 8846 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8847 C.VoidPtrTy, ImplicitParamDecl::Other); 8848 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8849 ImplicitParamDecl::Other); 8850 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8851 ImplicitParamDecl::Other); 8852 FunctionArgList Args; 8853 Args.push_back(&HandleArg); 8854 Args.push_back(&BaseArg); 8855 Args.push_back(&BeginArg); 8856 Args.push_back(&SizeArg); 8857 Args.push_back(&TypeArg); 8858 const CGFunctionInfo &FnInfo = 8859 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8860 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8861 SmallString<64> TyStr; 8862 llvm::raw_svector_ostream Out(TyStr); 8863 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 8864 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 8865 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 8866 Name, &CGM.getModule()); 8867 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 8868 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 8869 // Start the mapper function code generation. 8870 CodeGenFunction MapperCGF(CGM); 8871 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 8872 // Compute the starting and end addreses of array elements. 8873 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 8874 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 8875 C.getPointerType(Int64Ty), Loc); 8876 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 8877 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 8878 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 8879 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 8880 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 8881 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 8882 C.getPointerType(Int64Ty), Loc); 8883 // Prepare common arguments for array initiation and deletion. 8884 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 8885 MapperCGF.GetAddrOfLocalVar(&HandleArg), 8886 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8887 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 8888 MapperCGF.GetAddrOfLocalVar(&BaseArg), 8889 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8890 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 8891 MapperCGF.GetAddrOfLocalVar(&BeginArg), 8892 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8893 8894 // Emit array initiation if this is an array section and \p MapType indicates 8895 // that memory allocation is required. 8896 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 8897 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8898 ElementSize, HeadBB, /*IsInit=*/true); 8899 8900 // Emit a for loop to iterate through SizeArg of elements and map all of them. 8901 8902 // Emit the loop header block. 8903 MapperCGF.EmitBlock(HeadBB); 8904 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 8905 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 8906 // Evaluate whether the initial condition is satisfied. 8907 llvm::Value *IsEmpty = 8908 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 8909 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 8910 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 8911 8912 // Emit the loop body block. 8913 MapperCGF.EmitBlock(BodyBB); 8914 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 8915 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 8916 PtrPHI->addIncoming(PtrBegin, EntryBB); 8917 Address PtrCurrent = 8918 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 8919 .getAlignment() 8920 .alignmentOfArrayElement(ElementSize)); 8921 // Privatize the declared variable of mapper to be the current array element. 8922 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 8923 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 8924 return MapperCGF 8925 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 8926 .getAddress(MapperCGF); 8927 }); 8928 (void)Scope.Privatize(); 8929 8930 // Get map clause information. Fill up the arrays with all mapped variables. 8931 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 8932 MappableExprsHandler::MapValuesArrayTy Pointers; 8933 MappableExprsHandler::MapValuesArrayTy Sizes; 8934 MappableExprsHandler::MapFlagsArrayTy MapTypes; 8935 MappableExprsHandler MEHandler(*D, MapperCGF); 8936 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 8937 8938 // Call the runtime API __tgt_mapper_num_components to get the number of 8939 // pre-existing components. 8940 llvm::Value *OffloadingArgs[] = {Handle}; 8941 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 8942 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 8943 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 8944 PreviousSize, 8945 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 8946 8947 // Fill up the runtime mapper handle for all components. 8948 for (unsigned I = 0; I < BasePointers.size(); ++I) { 8949 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 8950 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8951 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 8952 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8953 llvm::Value *CurSizeArg = Sizes[I]; 8954 8955 // Extract the MEMBER_OF field from the map type. 8956 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 8957 MapperCGF.EmitBlock(MemberBB); 8958 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 8959 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 8960 OriMapType, 8961 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 8962 llvm::BasicBlock *MemberCombineBB = 8963 MapperCGF.createBasicBlock("omp.member.combine"); 8964 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 8965 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 8966 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 8967 // Add the number of pre-existing components to the MEMBER_OF field if it 8968 // is valid. 8969 MapperCGF.EmitBlock(MemberCombineBB); 8970 llvm::Value *CombinedMember = 8971 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 8972 // Do nothing if it is not a member of previous components. 8973 MapperCGF.EmitBlock(TypeBB); 8974 llvm::PHINode *MemberMapType = 8975 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 8976 MemberMapType->addIncoming(OriMapType, MemberBB); 8977 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 8978 8979 // Combine the map type inherited from user-defined mapper with that 8980 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 8981 // bits of the \a MapType, which is the input argument of the mapper 8982 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 8983 // bits of MemberMapType. 8984 // [OpenMP 5.0], 1.2.6. map-type decay. 8985 // | alloc | to | from | tofrom | release | delete 8986 // ---------------------------------------------------------- 8987 // alloc | alloc | alloc | alloc | alloc | release | delete 8988 // to | alloc | to | alloc | to | release | delete 8989 // from | alloc | alloc | from | from | release | delete 8990 // tofrom | alloc | to | from | tofrom | release | delete 8991 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 8992 MapType, 8993 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 8994 MappableExprsHandler::OMP_MAP_FROM)); 8995 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 8996 llvm::BasicBlock *AllocElseBB = 8997 MapperCGF.createBasicBlock("omp.type.alloc.else"); 8998 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 8999 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9000 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9001 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9002 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9003 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9004 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9005 MapperCGF.EmitBlock(AllocBB); 9006 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9007 MemberMapType, 9008 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9009 MappableExprsHandler::OMP_MAP_FROM))); 9010 MapperCGF.Builder.CreateBr(EndBB); 9011 MapperCGF.EmitBlock(AllocElseBB); 9012 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9013 LeftToFrom, 9014 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9015 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9016 // In case of to, clear OMP_MAP_FROM. 9017 MapperCGF.EmitBlock(ToBB); 9018 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9019 MemberMapType, 9020 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9021 MapperCGF.Builder.CreateBr(EndBB); 9022 MapperCGF.EmitBlock(ToElseBB); 9023 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9024 LeftToFrom, 9025 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9026 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9027 // In case of from, clear OMP_MAP_TO. 9028 MapperCGF.EmitBlock(FromBB); 9029 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9030 MemberMapType, 9031 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9032 // In case of tofrom, do nothing. 9033 MapperCGF.EmitBlock(EndBB); 9034 llvm::PHINode *CurMapType = 9035 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9036 CurMapType->addIncoming(AllocMapType, AllocBB); 9037 CurMapType->addIncoming(ToMapType, ToBB); 9038 CurMapType->addIncoming(FromMapType, FromBB); 9039 CurMapType->addIncoming(MemberMapType, ToElseBB); 9040 9041 // TODO: call the corresponding mapper function if a user-defined mapper is 9042 // associated with this map clause. 9043 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9044 // data structure. 9045 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9046 CurSizeArg, CurMapType}; 9047 MapperCGF.EmitRuntimeCall( 9048 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9049 OffloadingArgs); 9050 } 9051 9052 // Update the pointer to point to the next element that needs to be mapped, 9053 // and check whether we have mapped all elements. 9054 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9055 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9056 PtrPHI->addIncoming(PtrNext, BodyBB); 9057 llvm::Value *IsDone = 9058 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9059 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9060 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9061 9062 MapperCGF.EmitBlock(ExitBB); 9063 // Emit array deletion if this is an array section and \p MapType indicates 9064 // that deletion is required. 9065 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9066 ElementSize, DoneBB, /*IsInit=*/false); 9067 9068 // Emit the function exit block. 9069 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9070 MapperCGF.FinishFunction(); 9071 UDMMap.try_emplace(D, Fn); 9072 if (CGF) { 9073 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9074 Decls.second.push_back(D); 9075 } 9076 } 9077 9078 /// Emit the array initialization or deletion portion for user-defined mapper 9079 /// code generation. First, it evaluates whether an array section is mapped and 9080 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9081 /// true, and \a MapType indicates to not delete this array, array 9082 /// initialization code is generated. If \a IsInit is false, and \a MapType 9083 /// indicates to not this array, array deletion code is generated. 9084 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9085 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9086 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9087 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9088 StringRef Prefix = IsInit ? ".init" : ".del"; 9089 9090 // Evaluate if this is an array section. 9091 llvm::BasicBlock *IsDeleteBB = 9092 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"})); 9093 llvm::BasicBlock *BodyBB = 9094 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 9095 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9096 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9097 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9098 9099 // Evaluate if we are going to delete this section. 9100 MapperCGF.EmitBlock(IsDeleteBB); 9101 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9102 MapType, 9103 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9104 llvm::Value *DeleteCond; 9105 if (IsInit) { 9106 DeleteCond = MapperCGF.Builder.CreateIsNull( 9107 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9108 } else { 9109 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9110 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9111 } 9112 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9113 9114 MapperCGF.EmitBlock(BodyBB); 9115 // Get the array size by multiplying element size and element number (i.e., \p 9116 // Size). 9117 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9118 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9119 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9120 // memory allocation/deletion purpose only. 9121 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9122 MapType, 9123 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9124 MappableExprsHandler::OMP_MAP_FROM))); 9125 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9126 // data structure. 9127 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9128 MapperCGF.EmitRuntimeCall( 9129 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9130 } 9131 9132 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9133 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9134 llvm::Value *DeviceID, 9135 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9136 const OMPLoopDirective &D)> 9137 SizeEmitter) { 9138 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9139 const OMPExecutableDirective *TD = &D; 9140 // Get nested teams distribute kind directive, if any. 9141 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9142 TD = getNestedDistributeDirective(CGM.getContext(), D); 9143 if (!TD) 9144 return; 9145 const auto *LD = cast<OMPLoopDirective>(TD); 9146 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9147 PrePostActionTy &) { 9148 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9149 llvm::Value *Args[] = {DeviceID, NumIterations}; 9150 CGF.EmitRuntimeCall( 9151 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9152 } 9153 }; 9154 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9155 } 9156 9157 void CGOpenMPRuntime::emitTargetCall( 9158 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9159 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9160 const Expr *Device, 9161 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9162 const OMPLoopDirective &D)> 9163 SizeEmitter) { 9164 if (!CGF.HaveInsertPoint()) 9165 return; 9166 9167 assert(OutlinedFn && "Invalid outlined function!"); 9168 9169 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9170 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9171 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9172 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9173 PrePostActionTy &) { 9174 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9175 }; 9176 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9177 9178 CodeGenFunction::OMPTargetDataInfo InputInfo; 9179 llvm::Value *MapTypesArray = nullptr; 9180 // Fill up the pointer arrays and transfer execution to the device. 9181 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9182 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9183 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9184 // On top of the arrays that were filled up, the target offloading call 9185 // takes as arguments the device id as well as the host pointer. The host 9186 // pointer is used by the runtime library to identify the current target 9187 // region, so it only has to be unique and not necessarily point to 9188 // anything. It could be the pointer to the outlined function that 9189 // implements the target region, but we aren't using that so that the 9190 // compiler doesn't need to keep that, and could therefore inline the host 9191 // function if proven worthwhile during optimization. 9192 9193 // From this point on, we need to have an ID of the target region defined. 9194 assert(OutlinedFnID && "Invalid outlined function ID!"); 9195 9196 // Emit device ID if any. 9197 llvm::Value *DeviceID; 9198 if (Device) { 9199 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9200 CGF.Int64Ty, /*isSigned=*/true); 9201 } else { 9202 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9203 } 9204 9205 // Emit the number of elements in the offloading arrays. 9206 llvm::Value *PointerNum = 9207 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9208 9209 // Return value of the runtime offloading call. 9210 llvm::Value *Return; 9211 9212 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9213 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9214 9215 // Emit tripcount for the target loop-based directive. 9216 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9217 9218 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9219 // The target region is an outlined function launched by the runtime 9220 // via calls __tgt_target() or __tgt_target_teams(). 9221 // 9222 // __tgt_target() launches a target region with one team and one thread, 9223 // executing a serial region. This master thread may in turn launch 9224 // more threads within its team upon encountering a parallel region, 9225 // however, no additional teams can be launched on the device. 9226 // 9227 // __tgt_target_teams() launches a target region with one or more teams, 9228 // each with one or more threads. This call is required for target 9229 // constructs such as: 9230 // 'target teams' 9231 // 'target' / 'teams' 9232 // 'target teams distribute parallel for' 9233 // 'target parallel' 9234 // and so on. 9235 // 9236 // Note that on the host and CPU targets, the runtime implementation of 9237 // these calls simply call the outlined function without forking threads. 9238 // The outlined functions themselves have runtime calls to 9239 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9240 // the compiler in emitTeamsCall() and emitParallelCall(). 9241 // 9242 // In contrast, on the NVPTX target, the implementation of 9243 // __tgt_target_teams() launches a GPU kernel with the requested number 9244 // of teams and threads so no additional calls to the runtime are required. 9245 if (NumTeams) { 9246 // If we have NumTeams defined this means that we have an enclosed teams 9247 // region. Therefore we also expect to have NumThreads defined. These two 9248 // values should be defined in the presence of a teams directive, 9249 // regardless of having any clauses associated. If the user is using teams 9250 // but no clauses, these two values will be the default that should be 9251 // passed to the runtime library - a 32-bit integer with the value zero. 9252 assert(NumThreads && "Thread limit expression should be available along " 9253 "with number of teams."); 9254 llvm::Value *OffloadingArgs[] = {DeviceID, 9255 OutlinedFnID, 9256 PointerNum, 9257 InputInfo.BasePointersArray.getPointer(), 9258 InputInfo.PointersArray.getPointer(), 9259 InputInfo.SizesArray.getPointer(), 9260 MapTypesArray, 9261 NumTeams, 9262 NumThreads}; 9263 Return = CGF.EmitRuntimeCall( 9264 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9265 : OMPRTL__tgt_target_teams), 9266 OffloadingArgs); 9267 } else { 9268 llvm::Value *OffloadingArgs[] = {DeviceID, 9269 OutlinedFnID, 9270 PointerNum, 9271 InputInfo.BasePointersArray.getPointer(), 9272 InputInfo.PointersArray.getPointer(), 9273 InputInfo.SizesArray.getPointer(), 9274 MapTypesArray}; 9275 Return = CGF.EmitRuntimeCall( 9276 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9277 : OMPRTL__tgt_target), 9278 OffloadingArgs); 9279 } 9280 9281 // Check the error code and execute the host version if required. 9282 llvm::BasicBlock *OffloadFailedBlock = 9283 CGF.createBasicBlock("omp_offload.failed"); 9284 llvm::BasicBlock *OffloadContBlock = 9285 CGF.createBasicBlock("omp_offload.cont"); 9286 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9287 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9288 9289 CGF.EmitBlock(OffloadFailedBlock); 9290 if (RequiresOuterTask) { 9291 CapturedVars.clear(); 9292 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9293 } 9294 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9295 CGF.EmitBranch(OffloadContBlock); 9296 9297 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9298 }; 9299 9300 // Notify that the host version must be executed. 9301 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9302 RequiresOuterTask](CodeGenFunction &CGF, 9303 PrePostActionTy &) { 9304 if (RequiresOuterTask) { 9305 CapturedVars.clear(); 9306 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9307 } 9308 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9309 }; 9310 9311 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9312 &CapturedVars, RequiresOuterTask, 9313 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9314 // Fill up the arrays with all the captured variables. 9315 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9316 MappableExprsHandler::MapValuesArrayTy Pointers; 9317 MappableExprsHandler::MapValuesArrayTy Sizes; 9318 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9319 9320 // Get mappable expression information. 9321 MappableExprsHandler MEHandler(D, CGF); 9322 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9323 9324 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9325 auto CV = CapturedVars.begin(); 9326 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9327 CE = CS.capture_end(); 9328 CI != CE; ++CI, ++RI, ++CV) { 9329 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9330 MappableExprsHandler::MapValuesArrayTy CurPointers; 9331 MappableExprsHandler::MapValuesArrayTy CurSizes; 9332 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9333 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9334 9335 // VLA sizes are passed to the outlined region by copy and do not have map 9336 // information associated. 9337 if (CI->capturesVariableArrayType()) { 9338 CurBasePointers.push_back(*CV); 9339 CurPointers.push_back(*CV); 9340 CurSizes.push_back(CGF.Builder.CreateIntCast( 9341 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9342 // Copy to the device as an argument. No need to retrieve it. 9343 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9344 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9345 MappableExprsHandler::OMP_MAP_IMPLICIT); 9346 } else { 9347 // If we have any information in the map clause, we use it, otherwise we 9348 // just do a default mapping. 9349 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9350 CurSizes, CurMapTypes, PartialStruct); 9351 if (CurBasePointers.empty()) 9352 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9353 CurPointers, CurSizes, CurMapTypes); 9354 // Generate correct mapping for variables captured by reference in 9355 // lambdas. 9356 if (CI->capturesVariable()) 9357 MEHandler.generateInfoForLambdaCaptures( 9358 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9359 CurMapTypes, LambdaPointers); 9360 } 9361 // We expect to have at least an element of information for this capture. 9362 assert(!CurBasePointers.empty() && 9363 "Non-existing map pointer for capture!"); 9364 assert(CurBasePointers.size() == CurPointers.size() && 9365 CurBasePointers.size() == CurSizes.size() && 9366 CurBasePointers.size() == CurMapTypes.size() && 9367 "Inconsistent map information sizes!"); 9368 9369 // If there is an entry in PartialStruct it means we have a struct with 9370 // individual members mapped. Emit an extra combined entry. 9371 if (PartialStruct.Base.isValid()) 9372 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9373 CurMapTypes, PartialStruct); 9374 9375 // We need to append the results of this capture to what we already have. 9376 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9377 Pointers.append(CurPointers.begin(), CurPointers.end()); 9378 Sizes.append(CurSizes.begin(), CurSizes.end()); 9379 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9380 } 9381 // Adjust MEMBER_OF flags for the lambdas captures. 9382 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9383 Pointers, MapTypes); 9384 // Map other list items in the map clause which are not captured variables 9385 // but "declare target link" global variables. 9386 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9387 MapTypes); 9388 9389 TargetDataInfo Info; 9390 // Fill up the arrays and create the arguments. 9391 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9392 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9393 Info.PointersArray, Info.SizesArray, 9394 Info.MapTypesArray, Info); 9395 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9396 InputInfo.BasePointersArray = 9397 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9398 InputInfo.PointersArray = 9399 Address(Info.PointersArray, CGM.getPointerAlign()); 9400 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9401 MapTypesArray = Info.MapTypesArray; 9402 if (RequiresOuterTask) 9403 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9404 else 9405 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9406 }; 9407 9408 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9409 CodeGenFunction &CGF, PrePostActionTy &) { 9410 if (RequiresOuterTask) { 9411 CodeGenFunction::OMPTargetDataInfo InputInfo; 9412 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9413 } else { 9414 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9415 } 9416 }; 9417 9418 // If we have a target function ID it means that we need to support 9419 // offloading, otherwise, just execute on the host. We need to execute on host 9420 // regardless of the conditional in the if clause if, e.g., the user do not 9421 // specify target triples. 9422 if (OutlinedFnID) { 9423 if (IfCond) { 9424 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9425 } else { 9426 RegionCodeGenTy ThenRCG(TargetThenGen); 9427 ThenRCG(CGF); 9428 } 9429 } else { 9430 RegionCodeGenTy ElseRCG(TargetElseGen); 9431 ElseRCG(CGF); 9432 } 9433 } 9434 9435 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9436 StringRef ParentName) { 9437 if (!S) 9438 return; 9439 9440 // Codegen OMP target directives that offload compute to the device. 9441 bool RequiresDeviceCodegen = 9442 isa<OMPExecutableDirective>(S) && 9443 isOpenMPTargetExecutionDirective( 9444 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9445 9446 if (RequiresDeviceCodegen) { 9447 const auto &E = *cast<OMPExecutableDirective>(S); 9448 unsigned DeviceID; 9449 unsigned FileID; 9450 unsigned Line; 9451 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9452 FileID, Line); 9453 9454 // Is this a target region that should not be emitted as an entry point? If 9455 // so just signal we are done with this target region. 9456 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9457 ParentName, Line)) 9458 return; 9459 9460 switch (E.getDirectiveKind()) { 9461 case OMPD_target: 9462 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9463 cast<OMPTargetDirective>(E)); 9464 break; 9465 case OMPD_target_parallel: 9466 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9467 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9468 break; 9469 case OMPD_target_teams: 9470 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9471 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9472 break; 9473 case OMPD_target_teams_distribute: 9474 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9475 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9476 break; 9477 case OMPD_target_teams_distribute_simd: 9478 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9479 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9480 break; 9481 case OMPD_target_parallel_for: 9482 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9483 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9484 break; 9485 case OMPD_target_parallel_for_simd: 9486 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9487 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9488 break; 9489 case OMPD_target_simd: 9490 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9491 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9492 break; 9493 case OMPD_target_teams_distribute_parallel_for: 9494 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9495 CGM, ParentName, 9496 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9497 break; 9498 case OMPD_target_teams_distribute_parallel_for_simd: 9499 CodeGenFunction:: 9500 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9501 CGM, ParentName, 9502 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9503 break; 9504 case OMPD_parallel: 9505 case OMPD_for: 9506 case OMPD_parallel_for: 9507 case OMPD_parallel_master: 9508 case OMPD_parallel_sections: 9509 case OMPD_for_simd: 9510 case OMPD_parallel_for_simd: 9511 case OMPD_cancel: 9512 case OMPD_cancellation_point: 9513 case OMPD_ordered: 9514 case OMPD_threadprivate: 9515 case OMPD_allocate: 9516 case OMPD_task: 9517 case OMPD_simd: 9518 case OMPD_sections: 9519 case OMPD_section: 9520 case OMPD_single: 9521 case OMPD_master: 9522 case OMPD_critical: 9523 case OMPD_taskyield: 9524 case OMPD_barrier: 9525 case OMPD_taskwait: 9526 case OMPD_taskgroup: 9527 case OMPD_atomic: 9528 case OMPD_flush: 9529 case OMPD_teams: 9530 case OMPD_target_data: 9531 case OMPD_target_exit_data: 9532 case OMPD_target_enter_data: 9533 case OMPD_distribute: 9534 case OMPD_distribute_simd: 9535 case OMPD_distribute_parallel_for: 9536 case OMPD_distribute_parallel_for_simd: 9537 case OMPD_teams_distribute: 9538 case OMPD_teams_distribute_simd: 9539 case OMPD_teams_distribute_parallel_for: 9540 case OMPD_teams_distribute_parallel_for_simd: 9541 case OMPD_target_update: 9542 case OMPD_declare_simd: 9543 case OMPD_declare_variant: 9544 case OMPD_declare_target: 9545 case OMPD_end_declare_target: 9546 case OMPD_declare_reduction: 9547 case OMPD_declare_mapper: 9548 case OMPD_taskloop: 9549 case OMPD_taskloop_simd: 9550 case OMPD_master_taskloop: 9551 case OMPD_master_taskloop_simd: 9552 case OMPD_parallel_master_taskloop: 9553 case OMPD_parallel_master_taskloop_simd: 9554 case OMPD_requires: 9555 case OMPD_unknown: 9556 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9557 } 9558 return; 9559 } 9560 9561 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9562 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9563 return; 9564 9565 scanForTargetRegionsFunctions( 9566 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9567 return; 9568 } 9569 9570 // If this is a lambda function, look into its body. 9571 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9572 S = L->getBody(); 9573 9574 // Keep looking for target regions recursively. 9575 for (const Stmt *II : S->children()) 9576 scanForTargetRegionsFunctions(II, ParentName); 9577 } 9578 9579 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9580 // If emitting code for the host, we do not process FD here. Instead we do 9581 // the normal code generation. 9582 if (!CGM.getLangOpts().OpenMPIsDevice) { 9583 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9584 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9585 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9586 // Do not emit device_type(nohost) functions for the host. 9587 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9588 return true; 9589 } 9590 return false; 9591 } 9592 9593 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9594 // Try to detect target regions in the function. 9595 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9596 StringRef Name = CGM.getMangledName(GD); 9597 scanForTargetRegionsFunctions(FD->getBody(), Name); 9598 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9599 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9600 // Do not emit device_type(nohost) functions for the host. 9601 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9602 return true; 9603 } 9604 9605 // Do not to emit function if it is not marked as declare target. 9606 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9607 AlreadyEmittedTargetDecls.count(VD) == 0; 9608 } 9609 9610 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9611 if (!CGM.getLangOpts().OpenMPIsDevice) 9612 return false; 9613 9614 // Check if there are Ctors/Dtors in this declaration and look for target 9615 // regions in it. We use the complete variant to produce the kernel name 9616 // mangling. 9617 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9618 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9619 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9620 StringRef ParentName = 9621 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9622 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9623 } 9624 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9625 StringRef ParentName = 9626 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9627 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9628 } 9629 } 9630 9631 // Do not to emit variable if it is not marked as declare target. 9632 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9633 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9634 cast<VarDecl>(GD.getDecl())); 9635 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9636 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9637 HasRequiresUnifiedSharedMemory)) { 9638 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9639 return true; 9640 } 9641 return false; 9642 } 9643 9644 llvm::Constant * 9645 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9646 const VarDecl *VD) { 9647 assert(VD->getType().isConstant(CGM.getContext()) && 9648 "Expected constant variable."); 9649 StringRef VarName; 9650 llvm::Constant *Addr; 9651 llvm::GlobalValue::LinkageTypes Linkage; 9652 QualType Ty = VD->getType(); 9653 SmallString<128> Buffer; 9654 { 9655 unsigned DeviceID; 9656 unsigned FileID; 9657 unsigned Line; 9658 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9659 FileID, Line); 9660 llvm::raw_svector_ostream OS(Buffer); 9661 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9662 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9663 VarName = OS.str(); 9664 } 9665 Linkage = llvm::GlobalValue::InternalLinkage; 9666 Addr = 9667 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9668 getDefaultFirstprivateAddressSpace()); 9669 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9670 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9671 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9672 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9673 VarName, Addr, VarSize, 9674 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9675 return Addr; 9676 } 9677 9678 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9679 llvm::Constant *Addr) { 9680 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9681 !CGM.getLangOpts().OpenMPIsDevice) 9682 return; 9683 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9684 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9685 if (!Res) { 9686 if (CGM.getLangOpts().OpenMPIsDevice) { 9687 // Register non-target variables being emitted in device code (debug info 9688 // may cause this). 9689 StringRef VarName = CGM.getMangledName(VD); 9690 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9691 } 9692 return; 9693 } 9694 // Register declare target variables. 9695 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9696 StringRef VarName; 9697 CharUnits VarSize; 9698 llvm::GlobalValue::LinkageTypes Linkage; 9699 9700 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9701 !HasRequiresUnifiedSharedMemory) { 9702 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9703 VarName = CGM.getMangledName(VD); 9704 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9705 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9706 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9707 } else { 9708 VarSize = CharUnits::Zero(); 9709 } 9710 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9711 // Temp solution to prevent optimizations of the internal variables. 9712 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9713 std::string RefName = getName({VarName, "ref"}); 9714 if (!CGM.GetGlobalValue(RefName)) { 9715 llvm::Constant *AddrRef = 9716 getOrCreateInternalVariable(Addr->getType(), RefName); 9717 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9718 GVAddrRef->setConstant(/*Val=*/true); 9719 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9720 GVAddrRef->setInitializer(Addr); 9721 CGM.addCompilerUsedGlobal(GVAddrRef); 9722 } 9723 } 9724 } else { 9725 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9726 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9727 HasRequiresUnifiedSharedMemory)) && 9728 "Declare target attribute must link or to with unified memory."); 9729 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9730 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9731 else 9732 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9733 9734 if (CGM.getLangOpts().OpenMPIsDevice) { 9735 VarName = Addr->getName(); 9736 Addr = nullptr; 9737 } else { 9738 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9739 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9740 } 9741 VarSize = CGM.getPointerSize(); 9742 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9743 } 9744 9745 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9746 VarName, Addr, VarSize, Flags, Linkage); 9747 } 9748 9749 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9750 if (isa<FunctionDecl>(GD.getDecl()) || 9751 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9752 return emitTargetFunctions(GD); 9753 9754 return emitTargetGlobalVariable(GD); 9755 } 9756 9757 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9758 for (const VarDecl *VD : DeferredGlobalVariables) { 9759 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9760 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9761 if (!Res) 9762 continue; 9763 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9764 !HasRequiresUnifiedSharedMemory) { 9765 CGM.EmitGlobal(VD); 9766 } else { 9767 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9768 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9769 HasRequiresUnifiedSharedMemory)) && 9770 "Expected link clause or to clause with unified memory."); 9771 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9772 } 9773 } 9774 } 9775 9776 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9777 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9778 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9779 " Expected target-based directive."); 9780 } 9781 9782 void CGOpenMPRuntime::checkArchForUnifiedAddressing( 9783 const OMPRequiresDecl *D) { 9784 for (const OMPClause *Clause : D->clauselists()) { 9785 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9786 HasRequiresUnifiedSharedMemory = true; 9787 break; 9788 } 9789 } 9790 } 9791 9792 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9793 LangAS &AS) { 9794 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9795 return false; 9796 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9797 switch(A->getAllocatorType()) { 9798 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9799 // Not supported, fallback to the default mem space. 9800 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9801 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9802 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9803 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9804 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9805 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9806 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9807 AS = LangAS::Default; 9808 return true; 9809 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9810 llvm_unreachable("Expected predefined allocator for the variables with the " 9811 "static storage."); 9812 } 9813 return false; 9814 } 9815 9816 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9817 return HasRequiresUnifiedSharedMemory; 9818 } 9819 9820 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9821 CodeGenModule &CGM) 9822 : CGM(CGM) { 9823 if (CGM.getLangOpts().OpenMPIsDevice) { 9824 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9825 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9826 } 9827 } 9828 9829 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9830 if (CGM.getLangOpts().OpenMPIsDevice) 9831 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9832 } 9833 9834 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9835 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9836 return true; 9837 9838 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9839 // Do not to emit function if it is marked as declare target as it was already 9840 // emitted. 9841 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9842 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 9843 if (auto *F = dyn_cast_or_null<llvm::Function>( 9844 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 9845 return !F->isDeclaration(); 9846 return false; 9847 } 9848 return true; 9849 } 9850 9851 return !AlreadyEmittedTargetDecls.insert(D).second; 9852 } 9853 9854 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9855 // If we don't have entries or if we are emitting code for the device, we 9856 // don't need to do anything. 9857 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9858 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9859 (OffloadEntriesInfoManager.empty() && 9860 !HasEmittedDeclareTargetRegion && 9861 !HasEmittedTargetRegion)) 9862 return nullptr; 9863 9864 // Create and register the function that handles the requires directives. 9865 ASTContext &C = CGM.getContext(); 9866 9867 llvm::Function *RequiresRegFn; 9868 { 9869 CodeGenFunction CGF(CGM); 9870 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9871 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9872 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9873 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9874 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9875 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9876 // TODO: check for other requires clauses. 9877 // The requires directive takes effect only when a target region is 9878 // present in the compilation unit. Otherwise it is ignored and not 9879 // passed to the runtime. This avoids the runtime from throwing an error 9880 // for mismatching requires clauses across compilation units that don't 9881 // contain at least 1 target region. 9882 assert((HasEmittedTargetRegion || 9883 HasEmittedDeclareTargetRegion || 9884 !OffloadEntriesInfoManager.empty()) && 9885 "Target or declare target region expected."); 9886 if (HasRequiresUnifiedSharedMemory) 9887 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9888 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 9889 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9890 CGF.FinishFunction(); 9891 } 9892 return RequiresRegFn; 9893 } 9894 9895 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9896 const OMPExecutableDirective &D, 9897 SourceLocation Loc, 9898 llvm::Function *OutlinedFn, 9899 ArrayRef<llvm::Value *> CapturedVars) { 9900 if (!CGF.HaveInsertPoint()) 9901 return; 9902 9903 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9904 CodeGenFunction::RunCleanupsScope Scope(CGF); 9905 9906 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9907 llvm::Value *Args[] = { 9908 RTLoc, 9909 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9910 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9911 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9912 RealArgs.append(std::begin(Args), std::end(Args)); 9913 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9914 9915 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 9916 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9917 } 9918 9919 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9920 const Expr *NumTeams, 9921 const Expr *ThreadLimit, 9922 SourceLocation Loc) { 9923 if (!CGF.HaveInsertPoint()) 9924 return; 9925 9926 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9927 9928 llvm::Value *NumTeamsVal = 9929 NumTeams 9930 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9931 CGF.CGM.Int32Ty, /* isSigned = */ true) 9932 : CGF.Builder.getInt32(0); 9933 9934 llvm::Value *ThreadLimitVal = 9935 ThreadLimit 9936 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 9937 CGF.CGM.Int32Ty, /* isSigned = */ true) 9938 : CGF.Builder.getInt32(0); 9939 9940 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 9941 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 9942 ThreadLimitVal}; 9943 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 9944 PushNumTeamsArgs); 9945 } 9946 9947 void CGOpenMPRuntime::emitTargetDataCalls( 9948 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 9949 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 9950 if (!CGF.HaveInsertPoint()) 9951 return; 9952 9953 // Action used to replace the default codegen action and turn privatization 9954 // off. 9955 PrePostActionTy NoPrivAction; 9956 9957 // Generate the code for the opening of the data environment. Capture all the 9958 // arguments of the runtime call by reference because they are used in the 9959 // closing of the region. 9960 auto &&BeginThenGen = [this, &D, Device, &Info, 9961 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 9962 // Fill up the arrays with all the mapped variables. 9963 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9964 MappableExprsHandler::MapValuesArrayTy Pointers; 9965 MappableExprsHandler::MapValuesArrayTy Sizes; 9966 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9967 9968 // Get map clause information. 9969 MappableExprsHandler MCHandler(D, CGF); 9970 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 9971 9972 // Fill up the arrays and create the arguments. 9973 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9974 9975 llvm::Value *BasePointersArrayArg = nullptr; 9976 llvm::Value *PointersArrayArg = nullptr; 9977 llvm::Value *SizesArrayArg = nullptr; 9978 llvm::Value *MapTypesArrayArg = nullptr; 9979 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 9980 SizesArrayArg, MapTypesArrayArg, Info); 9981 9982 // Emit device ID if any. 9983 llvm::Value *DeviceID = nullptr; 9984 if (Device) { 9985 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9986 CGF.Int64Ty, /*isSigned=*/true); 9987 } else { 9988 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9989 } 9990 9991 // Emit the number of elements in the offloading arrays. 9992 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 9993 9994 llvm::Value *OffloadingArgs[] = { 9995 DeviceID, PointerNum, BasePointersArrayArg, 9996 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 9997 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 9998 OffloadingArgs); 9999 10000 // If device pointer privatization is required, emit the body of the region 10001 // here. It will have to be duplicated: with and without privatization. 10002 if (!Info.CaptureDeviceAddrMap.empty()) 10003 CodeGen(CGF); 10004 }; 10005 10006 // Generate code for the closing of the data region. 10007 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10008 PrePostActionTy &) { 10009 assert(Info.isValid() && "Invalid data environment closing arguments."); 10010 10011 llvm::Value *BasePointersArrayArg = nullptr; 10012 llvm::Value *PointersArrayArg = nullptr; 10013 llvm::Value *SizesArrayArg = nullptr; 10014 llvm::Value *MapTypesArrayArg = nullptr; 10015 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10016 SizesArrayArg, MapTypesArrayArg, Info); 10017 10018 // Emit device ID if any. 10019 llvm::Value *DeviceID = nullptr; 10020 if (Device) { 10021 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10022 CGF.Int64Ty, /*isSigned=*/true); 10023 } else { 10024 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10025 } 10026 10027 // Emit the number of elements in the offloading arrays. 10028 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10029 10030 llvm::Value *OffloadingArgs[] = { 10031 DeviceID, PointerNum, BasePointersArrayArg, 10032 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10033 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10034 OffloadingArgs); 10035 }; 10036 10037 // If we need device pointer privatization, we need to emit the body of the 10038 // region with no privatization in the 'else' branch of the conditional. 10039 // Otherwise, we don't have to do anything. 10040 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10041 PrePostActionTy &) { 10042 if (!Info.CaptureDeviceAddrMap.empty()) { 10043 CodeGen.setAction(NoPrivAction); 10044 CodeGen(CGF); 10045 } 10046 }; 10047 10048 // We don't have to do anything to close the region if the if clause evaluates 10049 // to false. 10050 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10051 10052 if (IfCond) { 10053 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10054 } else { 10055 RegionCodeGenTy RCG(BeginThenGen); 10056 RCG(CGF); 10057 } 10058 10059 // If we don't require privatization of device pointers, we emit the body in 10060 // between the runtime calls. This avoids duplicating the body code. 10061 if (Info.CaptureDeviceAddrMap.empty()) { 10062 CodeGen.setAction(NoPrivAction); 10063 CodeGen(CGF); 10064 } 10065 10066 if (IfCond) { 10067 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10068 } else { 10069 RegionCodeGenTy RCG(EndThenGen); 10070 RCG(CGF); 10071 } 10072 } 10073 10074 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10075 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10076 const Expr *Device) { 10077 if (!CGF.HaveInsertPoint()) 10078 return; 10079 10080 assert((isa<OMPTargetEnterDataDirective>(D) || 10081 isa<OMPTargetExitDataDirective>(D) || 10082 isa<OMPTargetUpdateDirective>(D)) && 10083 "Expecting either target enter, exit data, or update directives."); 10084 10085 CodeGenFunction::OMPTargetDataInfo InputInfo; 10086 llvm::Value *MapTypesArray = nullptr; 10087 // Generate the code for the opening of the data environment. 10088 auto &&ThenGen = [this, &D, Device, &InputInfo, 10089 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10090 // Emit device ID if any. 10091 llvm::Value *DeviceID = nullptr; 10092 if (Device) { 10093 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10094 CGF.Int64Ty, /*isSigned=*/true); 10095 } else { 10096 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10097 } 10098 10099 // Emit the number of elements in the offloading arrays. 10100 llvm::Constant *PointerNum = 10101 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10102 10103 llvm::Value *OffloadingArgs[] = {DeviceID, 10104 PointerNum, 10105 InputInfo.BasePointersArray.getPointer(), 10106 InputInfo.PointersArray.getPointer(), 10107 InputInfo.SizesArray.getPointer(), 10108 MapTypesArray}; 10109 10110 // Select the right runtime function call for each expected standalone 10111 // directive. 10112 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10113 OpenMPRTLFunction RTLFn; 10114 switch (D.getDirectiveKind()) { 10115 case OMPD_target_enter_data: 10116 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10117 : OMPRTL__tgt_target_data_begin; 10118 break; 10119 case OMPD_target_exit_data: 10120 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10121 : OMPRTL__tgt_target_data_end; 10122 break; 10123 case OMPD_target_update: 10124 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10125 : OMPRTL__tgt_target_data_update; 10126 break; 10127 case OMPD_parallel: 10128 case OMPD_for: 10129 case OMPD_parallel_for: 10130 case OMPD_parallel_master: 10131 case OMPD_parallel_sections: 10132 case OMPD_for_simd: 10133 case OMPD_parallel_for_simd: 10134 case OMPD_cancel: 10135 case OMPD_cancellation_point: 10136 case OMPD_ordered: 10137 case OMPD_threadprivate: 10138 case OMPD_allocate: 10139 case OMPD_task: 10140 case OMPD_simd: 10141 case OMPD_sections: 10142 case OMPD_section: 10143 case OMPD_single: 10144 case OMPD_master: 10145 case OMPD_critical: 10146 case OMPD_taskyield: 10147 case OMPD_barrier: 10148 case OMPD_taskwait: 10149 case OMPD_taskgroup: 10150 case OMPD_atomic: 10151 case OMPD_flush: 10152 case OMPD_teams: 10153 case OMPD_target_data: 10154 case OMPD_distribute: 10155 case OMPD_distribute_simd: 10156 case OMPD_distribute_parallel_for: 10157 case OMPD_distribute_parallel_for_simd: 10158 case OMPD_teams_distribute: 10159 case OMPD_teams_distribute_simd: 10160 case OMPD_teams_distribute_parallel_for: 10161 case OMPD_teams_distribute_parallel_for_simd: 10162 case OMPD_declare_simd: 10163 case OMPD_declare_variant: 10164 case OMPD_declare_target: 10165 case OMPD_end_declare_target: 10166 case OMPD_declare_reduction: 10167 case OMPD_declare_mapper: 10168 case OMPD_taskloop: 10169 case OMPD_taskloop_simd: 10170 case OMPD_master_taskloop: 10171 case OMPD_master_taskloop_simd: 10172 case OMPD_parallel_master_taskloop: 10173 case OMPD_parallel_master_taskloop_simd: 10174 case OMPD_target: 10175 case OMPD_target_simd: 10176 case OMPD_target_teams_distribute: 10177 case OMPD_target_teams_distribute_simd: 10178 case OMPD_target_teams_distribute_parallel_for: 10179 case OMPD_target_teams_distribute_parallel_for_simd: 10180 case OMPD_target_teams: 10181 case OMPD_target_parallel: 10182 case OMPD_target_parallel_for: 10183 case OMPD_target_parallel_for_simd: 10184 case OMPD_requires: 10185 case OMPD_unknown: 10186 llvm_unreachable("Unexpected standalone target data directive."); 10187 break; 10188 } 10189 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10190 }; 10191 10192 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10193 CodeGenFunction &CGF, PrePostActionTy &) { 10194 // Fill up the arrays with all the mapped variables. 10195 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10196 MappableExprsHandler::MapValuesArrayTy Pointers; 10197 MappableExprsHandler::MapValuesArrayTy Sizes; 10198 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10199 10200 // Get map clause information. 10201 MappableExprsHandler MEHandler(D, CGF); 10202 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10203 10204 TargetDataInfo Info; 10205 // Fill up the arrays and create the arguments. 10206 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10207 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10208 Info.PointersArray, Info.SizesArray, 10209 Info.MapTypesArray, Info); 10210 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10211 InputInfo.BasePointersArray = 10212 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10213 InputInfo.PointersArray = 10214 Address(Info.PointersArray, CGM.getPointerAlign()); 10215 InputInfo.SizesArray = 10216 Address(Info.SizesArray, CGM.getPointerAlign()); 10217 MapTypesArray = Info.MapTypesArray; 10218 if (D.hasClausesOfKind<OMPDependClause>()) 10219 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10220 else 10221 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10222 }; 10223 10224 if (IfCond) { 10225 emitIfClause(CGF, IfCond, TargetThenGen, 10226 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10227 } else { 10228 RegionCodeGenTy ThenRCG(TargetThenGen); 10229 ThenRCG(CGF); 10230 } 10231 } 10232 10233 namespace { 10234 /// Kind of parameter in a function with 'declare simd' directive. 10235 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10236 /// Attribute set of the parameter. 10237 struct ParamAttrTy { 10238 ParamKindTy Kind = Vector; 10239 llvm::APSInt StrideOrArg; 10240 llvm::APSInt Alignment; 10241 }; 10242 } // namespace 10243 10244 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10245 ArrayRef<ParamAttrTy> ParamAttrs) { 10246 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10247 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10248 // of that clause. The VLEN value must be power of 2. 10249 // In other case the notion of the function`s "characteristic data type" (CDT) 10250 // is used to compute the vector length. 10251 // CDT is defined in the following order: 10252 // a) For non-void function, the CDT is the return type. 10253 // b) If the function has any non-uniform, non-linear parameters, then the 10254 // CDT is the type of the first such parameter. 10255 // c) If the CDT determined by a) or b) above is struct, union, or class 10256 // type which is pass-by-value (except for the type that maps to the 10257 // built-in complex data type), the characteristic data type is int. 10258 // d) If none of the above three cases is applicable, the CDT is int. 10259 // The VLEN is then determined based on the CDT and the size of vector 10260 // register of that ISA for which current vector version is generated. The 10261 // VLEN is computed using the formula below: 10262 // VLEN = sizeof(vector_register) / sizeof(CDT), 10263 // where vector register size specified in section 3.2.1 Registers and the 10264 // Stack Frame of original AMD64 ABI document. 10265 QualType RetType = FD->getReturnType(); 10266 if (RetType.isNull()) 10267 return 0; 10268 ASTContext &C = FD->getASTContext(); 10269 QualType CDT; 10270 if (!RetType.isNull() && !RetType->isVoidType()) { 10271 CDT = RetType; 10272 } else { 10273 unsigned Offset = 0; 10274 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10275 if (ParamAttrs[Offset].Kind == Vector) 10276 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10277 ++Offset; 10278 } 10279 if (CDT.isNull()) { 10280 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10281 if (ParamAttrs[I + Offset].Kind == Vector) { 10282 CDT = FD->getParamDecl(I)->getType(); 10283 break; 10284 } 10285 } 10286 } 10287 } 10288 if (CDT.isNull()) 10289 CDT = C.IntTy; 10290 CDT = CDT->getCanonicalTypeUnqualified(); 10291 if (CDT->isRecordType() || CDT->isUnionType()) 10292 CDT = C.IntTy; 10293 return C.getTypeSize(CDT); 10294 } 10295 10296 static void 10297 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10298 const llvm::APSInt &VLENVal, 10299 ArrayRef<ParamAttrTy> ParamAttrs, 10300 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10301 struct ISADataTy { 10302 char ISA; 10303 unsigned VecRegSize; 10304 }; 10305 ISADataTy ISAData[] = { 10306 { 10307 'b', 128 10308 }, // SSE 10309 { 10310 'c', 256 10311 }, // AVX 10312 { 10313 'd', 256 10314 }, // AVX2 10315 { 10316 'e', 512 10317 }, // AVX512 10318 }; 10319 llvm::SmallVector<char, 2> Masked; 10320 switch (State) { 10321 case OMPDeclareSimdDeclAttr::BS_Undefined: 10322 Masked.push_back('N'); 10323 Masked.push_back('M'); 10324 break; 10325 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10326 Masked.push_back('N'); 10327 break; 10328 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10329 Masked.push_back('M'); 10330 break; 10331 } 10332 for (char Mask : Masked) { 10333 for (const ISADataTy &Data : ISAData) { 10334 SmallString<256> Buffer; 10335 llvm::raw_svector_ostream Out(Buffer); 10336 Out << "_ZGV" << Data.ISA << Mask; 10337 if (!VLENVal) { 10338 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10339 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10340 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10341 } else { 10342 Out << VLENVal; 10343 } 10344 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10345 switch (ParamAttr.Kind){ 10346 case LinearWithVarStride: 10347 Out << 's' << ParamAttr.StrideOrArg; 10348 break; 10349 case Linear: 10350 Out << 'l'; 10351 if (!!ParamAttr.StrideOrArg) 10352 Out << ParamAttr.StrideOrArg; 10353 break; 10354 case Uniform: 10355 Out << 'u'; 10356 break; 10357 case Vector: 10358 Out << 'v'; 10359 break; 10360 } 10361 if (!!ParamAttr.Alignment) 10362 Out << 'a' << ParamAttr.Alignment; 10363 } 10364 Out << '_' << Fn->getName(); 10365 Fn->addFnAttr(Out.str()); 10366 } 10367 } 10368 } 10369 10370 // This are the Functions that are needed to mangle the name of the 10371 // vector functions generated by the compiler, according to the rules 10372 // defined in the "Vector Function ABI specifications for AArch64", 10373 // available at 10374 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10375 10376 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10377 /// 10378 /// TODO: Need to implement the behavior for reference marked with a 10379 /// var or no linear modifiers (1.b in the section). For this, we 10380 /// need to extend ParamKindTy to support the linear modifiers. 10381 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10382 QT = QT.getCanonicalType(); 10383 10384 if (QT->isVoidType()) 10385 return false; 10386 10387 if (Kind == ParamKindTy::Uniform) 10388 return false; 10389 10390 if (Kind == ParamKindTy::Linear) 10391 return false; 10392 10393 // TODO: Handle linear references with modifiers 10394 10395 if (Kind == ParamKindTy::LinearWithVarStride) 10396 return false; 10397 10398 return true; 10399 } 10400 10401 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10402 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10403 QT = QT.getCanonicalType(); 10404 unsigned Size = C.getTypeSize(QT); 10405 10406 // Only scalars and complex within 16 bytes wide set PVB to true. 10407 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10408 return false; 10409 10410 if (QT->isFloatingType()) 10411 return true; 10412 10413 if (QT->isIntegerType()) 10414 return true; 10415 10416 if (QT->isPointerType()) 10417 return true; 10418 10419 // TODO: Add support for complex types (section 3.1.2, item 2). 10420 10421 return false; 10422 } 10423 10424 /// Computes the lane size (LS) of a return type or of an input parameter, 10425 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10426 /// TODO: Add support for references, section 3.2.1, item 1. 10427 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10428 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10429 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10430 if (getAArch64PBV(PTy, C)) 10431 return C.getTypeSize(PTy); 10432 } 10433 if (getAArch64PBV(QT, C)) 10434 return C.getTypeSize(QT); 10435 10436 return C.getTypeSize(C.getUIntPtrType()); 10437 } 10438 10439 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10440 // signature of the scalar function, as defined in 3.2.2 of the 10441 // AAVFABI. 10442 static std::tuple<unsigned, unsigned, bool> 10443 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10444 QualType RetType = FD->getReturnType().getCanonicalType(); 10445 10446 ASTContext &C = FD->getASTContext(); 10447 10448 bool OutputBecomesInput = false; 10449 10450 llvm::SmallVector<unsigned, 8> Sizes; 10451 if (!RetType->isVoidType()) { 10452 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10453 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10454 OutputBecomesInput = true; 10455 } 10456 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10457 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10458 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10459 } 10460 10461 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10462 // The LS of a function parameter / return value can only be a power 10463 // of 2, starting from 8 bits, up to 128. 10464 assert(std::all_of(Sizes.begin(), Sizes.end(), 10465 [](unsigned Size) { 10466 return Size == 8 || Size == 16 || Size == 32 || 10467 Size == 64 || Size == 128; 10468 }) && 10469 "Invalid size"); 10470 10471 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10472 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10473 OutputBecomesInput); 10474 } 10475 10476 /// Mangle the parameter part of the vector function name according to 10477 /// their OpenMP classification. The mangling function is defined in 10478 /// section 3.5 of the AAVFABI. 10479 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10480 SmallString<256> Buffer; 10481 llvm::raw_svector_ostream Out(Buffer); 10482 for (const auto &ParamAttr : ParamAttrs) { 10483 switch (ParamAttr.Kind) { 10484 case LinearWithVarStride: 10485 Out << "ls" << ParamAttr.StrideOrArg; 10486 break; 10487 case Linear: 10488 Out << 'l'; 10489 // Don't print the step value if it is not present or if it is 10490 // equal to 1. 10491 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10492 Out << ParamAttr.StrideOrArg; 10493 break; 10494 case Uniform: 10495 Out << 'u'; 10496 break; 10497 case Vector: 10498 Out << 'v'; 10499 break; 10500 } 10501 10502 if (!!ParamAttr.Alignment) 10503 Out << 'a' << ParamAttr.Alignment; 10504 } 10505 10506 return std::string(Out.str()); 10507 } 10508 10509 // Function used to add the attribute. The parameter `VLEN` is 10510 // templated to allow the use of "x" when targeting scalable functions 10511 // for SVE. 10512 template <typename T> 10513 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10514 char ISA, StringRef ParSeq, 10515 StringRef MangledName, bool OutputBecomesInput, 10516 llvm::Function *Fn) { 10517 SmallString<256> Buffer; 10518 llvm::raw_svector_ostream Out(Buffer); 10519 Out << Prefix << ISA << LMask << VLEN; 10520 if (OutputBecomesInput) 10521 Out << "v"; 10522 Out << ParSeq << "_" << MangledName; 10523 Fn->addFnAttr(Out.str()); 10524 } 10525 10526 // Helper function to generate the Advanced SIMD names depending on 10527 // the value of the NDS when simdlen is not present. 10528 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10529 StringRef Prefix, char ISA, 10530 StringRef ParSeq, StringRef MangledName, 10531 bool OutputBecomesInput, 10532 llvm::Function *Fn) { 10533 switch (NDS) { 10534 case 8: 10535 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10536 OutputBecomesInput, Fn); 10537 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10538 OutputBecomesInput, Fn); 10539 break; 10540 case 16: 10541 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10542 OutputBecomesInput, Fn); 10543 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10544 OutputBecomesInput, Fn); 10545 break; 10546 case 32: 10547 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10548 OutputBecomesInput, Fn); 10549 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10550 OutputBecomesInput, Fn); 10551 break; 10552 case 64: 10553 case 128: 10554 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10555 OutputBecomesInput, Fn); 10556 break; 10557 default: 10558 llvm_unreachable("Scalar type is too wide."); 10559 } 10560 } 10561 10562 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10563 static void emitAArch64DeclareSimdFunction( 10564 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10565 ArrayRef<ParamAttrTy> ParamAttrs, 10566 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10567 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10568 10569 // Get basic data for building the vector signature. 10570 const auto Data = getNDSWDS(FD, ParamAttrs); 10571 const unsigned NDS = std::get<0>(Data); 10572 const unsigned WDS = std::get<1>(Data); 10573 const bool OutputBecomesInput = std::get<2>(Data); 10574 10575 // Check the values provided via `simdlen` by the user. 10576 // 1. A `simdlen(1)` doesn't produce vector signatures, 10577 if (UserVLEN == 1) { 10578 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10579 DiagnosticsEngine::Warning, 10580 "The clause simdlen(1) has no effect when targeting aarch64."); 10581 CGM.getDiags().Report(SLoc, DiagID); 10582 return; 10583 } 10584 10585 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10586 // Advanced SIMD output. 10587 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10588 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10589 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10590 "power of 2 when targeting Advanced SIMD."); 10591 CGM.getDiags().Report(SLoc, DiagID); 10592 return; 10593 } 10594 10595 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10596 // limits. 10597 if (ISA == 's' && UserVLEN != 0) { 10598 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10599 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10600 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10601 "lanes in the architectural constraints " 10602 "for SVE (min is 128-bit, max is " 10603 "2048-bit, by steps of 128-bit)"); 10604 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10605 return; 10606 } 10607 } 10608 10609 // Sort out parameter sequence. 10610 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10611 StringRef Prefix = "_ZGV"; 10612 // Generate simdlen from user input (if any). 10613 if (UserVLEN) { 10614 if (ISA == 's') { 10615 // SVE generates only a masked function. 10616 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10617 OutputBecomesInput, Fn); 10618 } else { 10619 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10620 // Advanced SIMD generates one or two functions, depending on 10621 // the `[not]inbranch` clause. 10622 switch (State) { 10623 case OMPDeclareSimdDeclAttr::BS_Undefined: 10624 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10625 OutputBecomesInput, Fn); 10626 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10627 OutputBecomesInput, Fn); 10628 break; 10629 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10630 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10631 OutputBecomesInput, Fn); 10632 break; 10633 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10634 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10635 OutputBecomesInput, Fn); 10636 break; 10637 } 10638 } 10639 } else { 10640 // If no user simdlen is provided, follow the AAVFABI rules for 10641 // generating the vector length. 10642 if (ISA == 's') { 10643 // SVE, section 3.4.1, item 1. 10644 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10645 OutputBecomesInput, Fn); 10646 } else { 10647 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10648 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10649 // two vector names depending on the use of the clause 10650 // `[not]inbranch`. 10651 switch (State) { 10652 case OMPDeclareSimdDeclAttr::BS_Undefined: 10653 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10654 OutputBecomesInput, Fn); 10655 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10656 OutputBecomesInput, Fn); 10657 break; 10658 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10659 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10660 OutputBecomesInput, Fn); 10661 break; 10662 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10663 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10664 OutputBecomesInput, Fn); 10665 break; 10666 } 10667 } 10668 } 10669 } 10670 10671 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10672 llvm::Function *Fn) { 10673 ASTContext &C = CGM.getContext(); 10674 FD = FD->getMostRecentDecl(); 10675 // Map params to their positions in function decl. 10676 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10677 if (isa<CXXMethodDecl>(FD)) 10678 ParamPositions.try_emplace(FD, 0); 10679 unsigned ParamPos = ParamPositions.size(); 10680 for (const ParmVarDecl *P : FD->parameters()) { 10681 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10682 ++ParamPos; 10683 } 10684 while (FD) { 10685 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10686 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10687 // Mark uniform parameters. 10688 for (const Expr *E : Attr->uniforms()) { 10689 E = E->IgnoreParenImpCasts(); 10690 unsigned Pos; 10691 if (isa<CXXThisExpr>(E)) { 10692 Pos = ParamPositions[FD]; 10693 } else { 10694 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10695 ->getCanonicalDecl(); 10696 Pos = ParamPositions[PVD]; 10697 } 10698 ParamAttrs[Pos].Kind = Uniform; 10699 } 10700 // Get alignment info. 10701 auto NI = Attr->alignments_begin(); 10702 for (const Expr *E : Attr->aligneds()) { 10703 E = E->IgnoreParenImpCasts(); 10704 unsigned Pos; 10705 QualType ParmTy; 10706 if (isa<CXXThisExpr>(E)) { 10707 Pos = ParamPositions[FD]; 10708 ParmTy = E->getType(); 10709 } else { 10710 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10711 ->getCanonicalDecl(); 10712 Pos = ParamPositions[PVD]; 10713 ParmTy = PVD->getType(); 10714 } 10715 ParamAttrs[Pos].Alignment = 10716 (*NI) 10717 ? (*NI)->EvaluateKnownConstInt(C) 10718 : llvm::APSInt::getUnsigned( 10719 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10720 .getQuantity()); 10721 ++NI; 10722 } 10723 // Mark linear parameters. 10724 auto SI = Attr->steps_begin(); 10725 auto MI = Attr->modifiers_begin(); 10726 for (const Expr *E : Attr->linears()) { 10727 E = E->IgnoreParenImpCasts(); 10728 unsigned Pos; 10729 if (isa<CXXThisExpr>(E)) { 10730 Pos = ParamPositions[FD]; 10731 } else { 10732 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10733 ->getCanonicalDecl(); 10734 Pos = ParamPositions[PVD]; 10735 } 10736 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10737 ParamAttr.Kind = Linear; 10738 if (*SI) { 10739 Expr::EvalResult Result; 10740 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10741 if (const auto *DRE = 10742 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10743 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10744 ParamAttr.Kind = LinearWithVarStride; 10745 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10746 ParamPositions[StridePVD->getCanonicalDecl()]); 10747 } 10748 } 10749 } else { 10750 ParamAttr.StrideOrArg = Result.Val.getInt(); 10751 } 10752 } 10753 ++SI; 10754 ++MI; 10755 } 10756 llvm::APSInt VLENVal; 10757 SourceLocation ExprLoc; 10758 const Expr *VLENExpr = Attr->getSimdlen(); 10759 if (VLENExpr) { 10760 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10761 ExprLoc = VLENExpr->getExprLoc(); 10762 } 10763 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10764 if (CGM.getTriple().isX86()) { 10765 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10766 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10767 unsigned VLEN = VLENVal.getExtValue(); 10768 StringRef MangledName = Fn->getName(); 10769 if (CGM.getTarget().hasFeature("sve")) 10770 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10771 MangledName, 's', 128, Fn, ExprLoc); 10772 if (CGM.getTarget().hasFeature("neon")) 10773 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10774 MangledName, 'n', 128, Fn, ExprLoc); 10775 } 10776 } 10777 FD = FD->getPreviousDecl(); 10778 } 10779 } 10780 10781 namespace { 10782 /// Cleanup action for doacross support. 10783 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10784 public: 10785 static const int DoacrossFinArgs = 2; 10786 10787 private: 10788 llvm::FunctionCallee RTLFn; 10789 llvm::Value *Args[DoacrossFinArgs]; 10790 10791 public: 10792 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10793 ArrayRef<llvm::Value *> CallArgs) 10794 : RTLFn(RTLFn) { 10795 assert(CallArgs.size() == DoacrossFinArgs); 10796 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10797 } 10798 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10799 if (!CGF.HaveInsertPoint()) 10800 return; 10801 CGF.EmitRuntimeCall(RTLFn, Args); 10802 } 10803 }; 10804 } // namespace 10805 10806 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10807 const OMPLoopDirective &D, 10808 ArrayRef<Expr *> NumIterations) { 10809 if (!CGF.HaveInsertPoint()) 10810 return; 10811 10812 ASTContext &C = CGM.getContext(); 10813 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10814 RecordDecl *RD; 10815 if (KmpDimTy.isNull()) { 10816 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10817 // kmp_int64 lo; // lower 10818 // kmp_int64 up; // upper 10819 // kmp_int64 st; // stride 10820 // }; 10821 RD = C.buildImplicitRecord("kmp_dim"); 10822 RD->startDefinition(); 10823 addFieldToRecordDecl(C, RD, Int64Ty); 10824 addFieldToRecordDecl(C, RD, Int64Ty); 10825 addFieldToRecordDecl(C, RD, Int64Ty); 10826 RD->completeDefinition(); 10827 KmpDimTy = C.getRecordType(RD); 10828 } else { 10829 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10830 } 10831 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10832 QualType ArrayTy = 10833 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 10834 10835 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10836 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10837 enum { LowerFD = 0, UpperFD, StrideFD }; 10838 // Fill dims with data. 10839 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10840 LValue DimsLVal = CGF.MakeAddrLValue( 10841 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10842 // dims.upper = num_iterations; 10843 LValue UpperLVal = CGF.EmitLValueForField( 10844 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10845 llvm::Value *NumIterVal = 10846 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10847 D.getNumIterations()->getType(), Int64Ty, 10848 D.getNumIterations()->getExprLoc()); 10849 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10850 // dims.stride = 1; 10851 LValue StrideLVal = CGF.EmitLValueForField( 10852 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10853 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10854 StrideLVal); 10855 } 10856 10857 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10858 // kmp_int32 num_dims, struct kmp_dim * dims); 10859 llvm::Value *Args[] = { 10860 emitUpdateLocation(CGF, D.getBeginLoc()), 10861 getThreadID(CGF, D.getBeginLoc()), 10862 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10863 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10864 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10865 CGM.VoidPtrTy)}; 10866 10867 llvm::FunctionCallee RTLFn = 10868 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 10869 CGF.EmitRuntimeCall(RTLFn, Args); 10870 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10871 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10872 llvm::FunctionCallee FiniRTLFn = 10873 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 10874 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10875 llvm::makeArrayRef(FiniArgs)); 10876 } 10877 10878 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10879 const OMPDependClause *C) { 10880 QualType Int64Ty = 10881 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10882 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10883 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10884 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 10885 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10886 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10887 const Expr *CounterVal = C->getLoopData(I); 10888 assert(CounterVal); 10889 llvm::Value *CntVal = CGF.EmitScalarConversion( 10890 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10891 CounterVal->getExprLoc()); 10892 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10893 /*Volatile=*/false, Int64Ty); 10894 } 10895 llvm::Value *Args[] = { 10896 emitUpdateLocation(CGF, C->getBeginLoc()), 10897 getThreadID(CGF, C->getBeginLoc()), 10898 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10899 llvm::FunctionCallee RTLFn; 10900 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10901 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 10902 } else { 10903 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10904 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 10905 } 10906 CGF.EmitRuntimeCall(RTLFn, Args); 10907 } 10908 10909 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10910 llvm::FunctionCallee Callee, 10911 ArrayRef<llvm::Value *> Args) const { 10912 assert(Loc.isValid() && "Outlined function call location must be valid."); 10913 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10914 10915 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10916 if (Fn->doesNotThrow()) { 10917 CGF.EmitNounwindRuntimeCall(Fn, Args); 10918 return; 10919 } 10920 } 10921 CGF.EmitRuntimeCall(Callee, Args); 10922 } 10923 10924 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10925 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10926 ArrayRef<llvm::Value *> Args) const { 10927 emitCall(CGF, Loc, OutlinedFn, Args); 10928 } 10929 10930 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10931 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 10932 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 10933 HasEmittedDeclareTargetRegion = true; 10934 } 10935 10936 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 10937 const VarDecl *NativeParam, 10938 const VarDecl *TargetParam) const { 10939 return CGF.GetAddrOfLocalVar(NativeParam); 10940 } 10941 10942 namespace { 10943 /// Cleanup action for allocate support. 10944 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 10945 public: 10946 static const int CleanupArgs = 3; 10947 10948 private: 10949 llvm::FunctionCallee RTLFn; 10950 llvm::Value *Args[CleanupArgs]; 10951 10952 public: 10953 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 10954 ArrayRef<llvm::Value *> CallArgs) 10955 : RTLFn(RTLFn) { 10956 assert(CallArgs.size() == CleanupArgs && 10957 "Size of arguments does not match."); 10958 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10959 } 10960 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10961 if (!CGF.HaveInsertPoint()) 10962 return; 10963 CGF.EmitRuntimeCall(RTLFn, Args); 10964 } 10965 }; 10966 } // namespace 10967 10968 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 10969 const VarDecl *VD) { 10970 if (!VD) 10971 return Address::invalid(); 10972 const VarDecl *CVD = VD->getCanonicalDecl(); 10973 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 10974 return Address::invalid(); 10975 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 10976 // Use the default allocation. 10977 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 10978 !AA->getAllocator()) 10979 return Address::invalid(); 10980 llvm::Value *Size; 10981 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 10982 if (CVD->getType()->isVariablyModifiedType()) { 10983 Size = CGF.getTypeSize(CVD->getType()); 10984 // Align the size: ((size + align - 1) / align) * align 10985 Size = CGF.Builder.CreateNUWAdd( 10986 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 10987 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 10988 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 10989 } else { 10990 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 10991 Size = CGM.getSize(Sz.alignTo(Align)); 10992 } 10993 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 10994 assert(AA->getAllocator() && 10995 "Expected allocator expression for non-default allocator."); 10996 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 10997 // According to the standard, the original allocator type is a enum (integer). 10998 // Convert to pointer type, if required. 10999 if (Allocator->getType()->isIntegerTy()) 11000 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11001 else if (Allocator->getType()->isPointerTy()) 11002 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11003 CGM.VoidPtrTy); 11004 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11005 11006 llvm::Value *Addr = 11007 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11008 getName({CVD->getName(), ".void.addr"})); 11009 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11010 Allocator}; 11011 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11012 11013 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11014 llvm::makeArrayRef(FiniArgs)); 11015 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11016 Addr, 11017 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11018 getName({CVD->getName(), ".addr"})); 11019 return Address(Addr, Align); 11020 } 11021 11022 namespace { 11023 using OMPContextSelectorData = 11024 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>; 11025 using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>; 11026 } // anonymous namespace 11027 11028 /// Checks current context and returns true if it matches the context selector. 11029 template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx, 11030 typename... Arguments> 11031 static bool checkContext(const OMPContextSelectorData &Data, 11032 Arguments... Params) { 11033 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown && 11034 "Unknown context selector or context selector set."); 11035 return false; 11036 } 11037 11038 /// Checks for implementation={vendor(<vendor>)} context selector. 11039 /// \returns true iff <vendor>="llvm", false otherwise. 11040 template <> 11041 bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>( 11042 const OMPContextSelectorData &Data) { 11043 return llvm::all_of(Data.Names, 11044 [](StringRef S) { return !S.compare_lower("llvm"); }); 11045 } 11046 11047 /// Checks for device={kind(<kind>)} context selector. 11048 /// \returns true if <kind>="host" and compilation is for host. 11049 /// true if <kind>="nohost" and compilation is for device. 11050 /// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU. 11051 /// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN. 11052 /// false otherwise. 11053 template <> 11054 bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>( 11055 const OMPContextSelectorData &Data, CodeGenModule &CGM) { 11056 for (StringRef Name : Data.Names) { 11057 if (!Name.compare_lower("host")) { 11058 if (CGM.getLangOpts().OpenMPIsDevice) 11059 return false; 11060 continue; 11061 } 11062 if (!Name.compare_lower("nohost")) { 11063 if (!CGM.getLangOpts().OpenMPIsDevice) 11064 return false; 11065 continue; 11066 } 11067 switch (CGM.getTriple().getArch()) { 11068 case llvm::Triple::arm: 11069 case llvm::Triple::armeb: 11070 case llvm::Triple::aarch64: 11071 case llvm::Triple::aarch64_be: 11072 case llvm::Triple::aarch64_32: 11073 case llvm::Triple::ppc: 11074 case llvm::Triple::ppc64: 11075 case llvm::Triple::ppc64le: 11076 case llvm::Triple::x86: 11077 case llvm::Triple::x86_64: 11078 if (Name.compare_lower("cpu")) 11079 return false; 11080 break; 11081 case llvm::Triple::amdgcn: 11082 case llvm::Triple::nvptx: 11083 case llvm::Triple::nvptx64: 11084 if (Name.compare_lower("gpu")) 11085 return false; 11086 break; 11087 case llvm::Triple::UnknownArch: 11088 case llvm::Triple::arc: 11089 case llvm::Triple::avr: 11090 case llvm::Triple::bpfel: 11091 case llvm::Triple::bpfeb: 11092 case llvm::Triple::hexagon: 11093 case llvm::Triple::mips: 11094 case llvm::Triple::mipsel: 11095 case llvm::Triple::mips64: 11096 case llvm::Triple::mips64el: 11097 case llvm::Triple::msp430: 11098 case llvm::Triple::r600: 11099 case llvm::Triple::riscv32: 11100 case llvm::Triple::riscv64: 11101 case llvm::Triple::sparc: 11102 case llvm::Triple::sparcv9: 11103 case llvm::Triple::sparcel: 11104 case llvm::Triple::systemz: 11105 case llvm::Triple::tce: 11106 case llvm::Triple::tcele: 11107 case llvm::Triple::thumb: 11108 case llvm::Triple::thumbeb: 11109 case llvm::Triple::xcore: 11110 case llvm::Triple::le32: 11111 case llvm::Triple::le64: 11112 case llvm::Triple::amdil: 11113 case llvm::Triple::amdil64: 11114 case llvm::Triple::hsail: 11115 case llvm::Triple::hsail64: 11116 case llvm::Triple::spir: 11117 case llvm::Triple::spir64: 11118 case llvm::Triple::kalimba: 11119 case llvm::Triple::shave: 11120 case llvm::Triple::lanai: 11121 case llvm::Triple::wasm32: 11122 case llvm::Triple::wasm64: 11123 case llvm::Triple::renderscript32: 11124 case llvm::Triple::renderscript64: 11125 case llvm::Triple::ve: 11126 return false; 11127 } 11128 } 11129 return true; 11130 } 11131 11132 static bool matchesContext(CodeGenModule &CGM, 11133 const CompleteOMPContextSelectorData &ContextData) { 11134 for (const OMPContextSelectorData &Data : ContextData) { 11135 switch (Data.Ctx) { 11136 case OMP_CTX_vendor: 11137 assert(Data.CtxSet == OMP_CTX_SET_implementation && 11138 "Expected implementation context selector set."); 11139 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data)) 11140 return false; 11141 break; 11142 case OMP_CTX_kind: 11143 assert(Data.CtxSet == OMP_CTX_SET_device && 11144 "Expected device context selector set."); 11145 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data, 11146 CGM)) 11147 return false; 11148 break; 11149 case OMP_CTX_unknown: 11150 llvm_unreachable("Unknown context selector kind."); 11151 } 11152 } 11153 return true; 11154 } 11155 11156 static CompleteOMPContextSelectorData 11157 translateAttrToContextSelectorData(ASTContext &C, 11158 const OMPDeclareVariantAttr *A) { 11159 CompleteOMPContextSelectorData Data; 11160 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) { 11161 Data.emplace_back(); 11162 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( 11163 *std::next(A->ctxSelectorSets_begin(), I)); 11164 auto Ctx = static_cast<OpenMPContextSelectorKind>( 11165 *std::next(A->ctxSelectors_begin(), I)); 11166 Data.back().CtxSet = CtxSet; 11167 Data.back().Ctx = Ctx; 11168 const Expr *Score = *std::next(A->scores_begin(), I); 11169 Data.back().Score = Score->EvaluateKnownConstInt(C); 11170 switch (Ctx) { 11171 case OMP_CTX_vendor: 11172 assert(CtxSet == OMP_CTX_SET_implementation && 11173 "Expected implementation context selector set."); 11174 Data.back().Names = 11175 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end()); 11176 break; 11177 case OMP_CTX_kind: 11178 assert(CtxSet == OMP_CTX_SET_device && 11179 "Expected device context selector set."); 11180 Data.back().Names = 11181 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end()); 11182 break; 11183 case OMP_CTX_unknown: 11184 llvm_unreachable("Unknown context selector kind."); 11185 } 11186 } 11187 return Data; 11188 } 11189 11190 static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS, 11191 const CompleteOMPContextSelectorData &RHS) { 11192 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData; 11193 for (const OMPContextSelectorData &D : RHS) { 11194 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx)); 11195 Pair.getSecond().insert(D.Names.begin(), D.Names.end()); 11196 } 11197 bool AllSetsAreEqual = true; 11198 for (const OMPContextSelectorData &D : LHS) { 11199 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx)); 11200 if (It == RHSData.end()) 11201 return false; 11202 if (D.Names.size() > It->getSecond().size()) 11203 return false; 11204 if (llvm::set_union(It->getSecond(), D.Names)) 11205 return false; 11206 AllSetsAreEqual = 11207 AllSetsAreEqual && (D.Names.size() == It->getSecond().size()); 11208 } 11209 11210 return LHS.size() != RHS.size() || !AllSetsAreEqual; 11211 } 11212 11213 static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS, 11214 const CompleteOMPContextSelectorData &RHS) { 11215 // Score is calculated as sum of all scores + 1. 11216 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11217 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS); 11218 if (RHSIsSubsetOfLHS) { 11219 LHSScore = llvm::APSInt::get(0); 11220 } else { 11221 for (const OMPContextSelectorData &Data : LHS) { 11222 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) { 11223 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11224 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) { 11225 LHSScore += Data.Score.extend(LHSScore.getBitWidth()); 11226 } else { 11227 LHSScore += Data.Score; 11228 } 11229 } 11230 } 11231 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11232 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) { 11233 RHSScore = llvm::APSInt::get(0); 11234 } else { 11235 for (const OMPContextSelectorData &Data : RHS) { 11236 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) { 11237 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11238 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) { 11239 RHSScore += Data.Score.extend(RHSScore.getBitWidth()); 11240 } else { 11241 RHSScore += Data.Score; 11242 } 11243 } 11244 } 11245 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0; 11246 } 11247 11248 /// Finds the variant function that matches current context with its context 11249 /// selector. 11250 static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, 11251 const FunctionDecl *FD) { 11252 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11253 return FD; 11254 // Iterate through all DeclareVariant attributes and check context selectors. 11255 const OMPDeclareVariantAttr *TopMostAttr = nullptr; 11256 CompleteOMPContextSelectorData TopMostData; 11257 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11258 CompleteOMPContextSelectorData Data = 11259 translateAttrToContextSelectorData(CGM.getContext(), A); 11260 if (!matchesContext(CGM, Data)) 11261 continue; 11262 // If the attribute matches the context, find the attribute with the highest 11263 // score. 11264 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) { 11265 TopMostAttr = A; 11266 TopMostData.swap(Data); 11267 } 11268 } 11269 if (!TopMostAttr) 11270 return FD; 11271 return cast<FunctionDecl>( 11272 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) 11273 ->getDecl()); 11274 } 11275 11276 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11277 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11278 // If the original function is defined already, use its definition. 11279 StringRef MangledName = CGM.getMangledName(GD); 11280 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11281 if (Orig && !Orig->isDeclaration()) 11282 return false; 11283 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D); 11284 // Emit original function if it does not have declare variant attribute or the 11285 // context does not match. 11286 if (NewFD == D) 11287 return false; 11288 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11289 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) { 11290 DeferredVariantFunction.erase(D); 11291 return true; 11292 } 11293 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11294 return true; 11295 } 11296 11297 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 11298 CodeGenModule &CGM, const OMPLoopDirective &S) 11299 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 11300 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11301 if (!NeedToPush) 11302 return; 11303 NontemporalDeclsSet &DS = 11304 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 11305 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 11306 for (const Stmt *Ref : C->private_refs()) { 11307 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 11308 const ValueDecl *VD; 11309 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 11310 VD = DRE->getDecl(); 11311 } else { 11312 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 11313 assert((ME->isImplicitCXXThis() || 11314 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 11315 "Expected member of current class."); 11316 VD = ME->getMemberDecl(); 11317 } 11318 DS.insert(VD); 11319 } 11320 } 11321 } 11322 11323 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 11324 if (!NeedToPush) 11325 return; 11326 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 11327 } 11328 11329 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 11330 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11331 11332 return llvm::any_of( 11333 CGM.getOpenMPRuntime().NontemporalDeclsStack, 11334 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 11335 } 11336 11337 void CGOpenMPRuntime::LastprivateConditionalRAII::tryToDisableInnerAnalysis( 11338 const OMPExecutableDirective &S, 11339 llvm::DenseSet<CanonicalDeclPtr<const Decl>> &NeedToAddForLPCsAsDisabled) 11340 const { 11341 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToCheckForLPCs; 11342 // Vars in target/task regions must be excluded completely. 11343 if (isOpenMPTargetExecutionDirective(S.getDirectiveKind()) || 11344 isOpenMPTaskingDirective(S.getDirectiveKind())) { 11345 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11346 getOpenMPCaptureRegions(CaptureRegions, S.getDirectiveKind()); 11347 const CapturedStmt *CS = S.getCapturedStmt(CaptureRegions.front()); 11348 for (const CapturedStmt::Capture &Cap : CS->captures()) { 11349 if (Cap.capturesVariable() || Cap.capturesVariableByCopy()) 11350 NeedToCheckForLPCs.insert(Cap.getCapturedVar()); 11351 } 11352 } 11353 // Exclude vars in private clauses. 11354 for (const auto *C : S.getClausesOfKind<OMPPrivateClause>()) { 11355 for (const Expr *Ref : C->varlists()) { 11356 if (!Ref->getType()->isScalarType()) 11357 continue; 11358 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11359 if (!DRE) 11360 continue; 11361 NeedToCheckForLPCs.insert(DRE->getDecl()); 11362 } 11363 } 11364 for (const auto *C : S.getClausesOfKind<OMPFirstprivateClause>()) { 11365 for (const Expr *Ref : C->varlists()) { 11366 if (!Ref->getType()->isScalarType()) 11367 continue; 11368 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11369 if (!DRE) 11370 continue; 11371 NeedToCheckForLPCs.insert(DRE->getDecl()); 11372 } 11373 } 11374 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11375 for (const Expr *Ref : C->varlists()) { 11376 if (!Ref->getType()->isScalarType()) 11377 continue; 11378 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11379 if (!DRE) 11380 continue; 11381 NeedToCheckForLPCs.insert(DRE->getDecl()); 11382 } 11383 } 11384 for (const auto *C : S.getClausesOfKind<OMPReductionClause>()) { 11385 for (const Expr *Ref : C->varlists()) { 11386 if (!Ref->getType()->isScalarType()) 11387 continue; 11388 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11389 if (!DRE) 11390 continue; 11391 NeedToCheckForLPCs.insert(DRE->getDecl()); 11392 } 11393 } 11394 for (const auto *C : S.getClausesOfKind<OMPLinearClause>()) { 11395 for (const Expr *Ref : C->varlists()) { 11396 if (!Ref->getType()->isScalarType()) 11397 continue; 11398 const auto *DRE = dyn_cast<DeclRefExpr>(Ref->IgnoreParenImpCasts()); 11399 if (!DRE) 11400 continue; 11401 NeedToCheckForLPCs.insert(DRE->getDecl()); 11402 } 11403 } 11404 for (const Decl *VD : NeedToCheckForLPCs) { 11405 for (const LastprivateConditionalData &Data : 11406 llvm::reverse(CGM.getOpenMPRuntime().LastprivateConditionalStack)) { 11407 if (Data.DeclToUniqueName.count(VD) > 0) { 11408 if (!Data.Disabled) 11409 NeedToAddForLPCsAsDisabled.insert(VD); 11410 break; 11411 } 11412 } 11413 } 11414 } 11415 11416 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11417 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 11418 : CGM(CGF.CGM), 11419 Action((CGM.getLangOpts().OpenMP >= 50 && 11420 llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 11421 [](const OMPLastprivateClause *C) { 11422 return C->getKind() == 11423 OMPC_LASTPRIVATE_conditional; 11424 })) 11425 ? ActionToDo::PushAsLastprivateConditional 11426 : ActionToDo::DoNotPush) { 11427 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11428 if (CGM.getLangOpts().OpenMP < 50 || Action == ActionToDo::DoNotPush) 11429 return; 11430 assert(Action == ActionToDo::PushAsLastprivateConditional && 11431 "Expected a push action."); 11432 LastprivateConditionalData &Data = 11433 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11434 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11435 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 11436 continue; 11437 11438 for (const Expr *Ref : C->varlists()) { 11439 Data.DeclToUniqueName.insert(std::make_pair( 11440 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 11441 SmallString<16>(generateUniqueName(CGM, "pl_cond", Ref)))); 11442 } 11443 } 11444 Data.IVLVal = IVLVal; 11445 Data.Fn = CGF.CurFn; 11446 } 11447 11448 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11449 CodeGenFunction &CGF, const OMPExecutableDirective &S) 11450 : CGM(CGF.CGM), Action(ActionToDo::DoNotPush) { 11451 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11452 if (CGM.getLangOpts().OpenMP < 50) 11453 return; 11454 llvm::DenseSet<CanonicalDeclPtr<const Decl>> NeedToAddForLPCsAsDisabled; 11455 tryToDisableInnerAnalysis(S, NeedToAddForLPCsAsDisabled); 11456 if (!NeedToAddForLPCsAsDisabled.empty()) { 11457 Action = ActionToDo::DisableLastprivateConditional; 11458 LastprivateConditionalData &Data = 11459 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11460 for (const Decl *VD : NeedToAddForLPCsAsDisabled) 11461 Data.DeclToUniqueName.insert(std::make_pair(VD, SmallString<16>())); 11462 Data.Fn = CGF.CurFn; 11463 Data.Disabled = true; 11464 } 11465 } 11466 11467 CGOpenMPRuntime::LastprivateConditionalRAII 11468 CGOpenMPRuntime::LastprivateConditionalRAII::disable( 11469 CodeGenFunction &CGF, const OMPExecutableDirective &S) { 11470 return LastprivateConditionalRAII(CGF, S); 11471 } 11472 11473 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 11474 if (CGM.getLangOpts().OpenMP < 50) 11475 return; 11476 if (Action == ActionToDo::DisableLastprivateConditional) { 11477 assert(CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11478 "Expected list of disabled private vars."); 11479 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11480 } 11481 if (Action == ActionToDo::PushAsLastprivateConditional) { 11482 assert( 11483 !CGM.getOpenMPRuntime().LastprivateConditionalStack.back().Disabled && 11484 "Expected list of lastprivate conditional vars."); 11485 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11486 } 11487 } 11488 11489 Address CGOpenMPRuntime::emitLastprivateConditionalInit(CodeGenFunction &CGF, 11490 const VarDecl *VD) { 11491 ASTContext &C = CGM.getContext(); 11492 auto I = LastprivateConditionalToTypes.find(CGF.CurFn); 11493 if (I == LastprivateConditionalToTypes.end()) 11494 I = LastprivateConditionalToTypes.try_emplace(CGF.CurFn).first; 11495 QualType NewType; 11496 const FieldDecl *VDField; 11497 const FieldDecl *FiredField; 11498 LValue BaseLVal; 11499 auto VI = I->getSecond().find(VD); 11500 if (VI == I->getSecond().end()) { 11501 RecordDecl *RD = C.buildImplicitRecord("lasprivate.conditional"); 11502 RD->startDefinition(); 11503 VDField = addFieldToRecordDecl(C, RD, VD->getType().getNonReferenceType()); 11504 FiredField = addFieldToRecordDecl(C, RD, C.CharTy); 11505 RD->completeDefinition(); 11506 NewType = C.getRecordType(RD); 11507 Address Addr = CGF.CreateMemTemp(NewType, C.getDeclAlign(VD), VD->getName()); 11508 BaseLVal = CGF.MakeAddrLValue(Addr, NewType, AlignmentSource::Decl); 11509 I->getSecond().try_emplace(VD, NewType, VDField, FiredField, BaseLVal); 11510 } else { 11511 NewType = std::get<0>(VI->getSecond()); 11512 VDField = std::get<1>(VI->getSecond()); 11513 FiredField = std::get<2>(VI->getSecond()); 11514 BaseLVal = std::get<3>(VI->getSecond()); 11515 } 11516 LValue FiredLVal = 11517 CGF.EmitLValueForField(BaseLVal, FiredField); 11518 CGF.EmitStoreOfScalar( 11519 llvm::ConstantInt::getNullValue(CGF.ConvertTypeForMem(C.CharTy)), 11520 FiredLVal); 11521 return CGF.EmitLValueForField(BaseLVal, VDField).getAddress(CGF); 11522 } 11523 11524 namespace { 11525 /// Checks if the lastprivate conditional variable is referenced in LHS. 11526 class LastprivateConditionalRefChecker final 11527 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 11528 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 11529 const Expr *FoundE = nullptr; 11530 const Decl *FoundD = nullptr; 11531 StringRef UniqueDeclName; 11532 LValue IVLVal; 11533 llvm::Function *FoundFn = nullptr; 11534 SourceLocation Loc; 11535 11536 public: 11537 bool VisitDeclRefExpr(const DeclRefExpr *E) { 11538 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11539 llvm::reverse(LPM)) { 11540 auto It = D.DeclToUniqueName.find(E->getDecl()); 11541 if (It == D.DeclToUniqueName.end()) 11542 continue; 11543 if (D.Disabled) 11544 return false; 11545 FoundE = E; 11546 FoundD = E->getDecl()->getCanonicalDecl(); 11547 UniqueDeclName = It->second; 11548 IVLVal = D.IVLVal; 11549 FoundFn = D.Fn; 11550 break; 11551 } 11552 return FoundE == E; 11553 } 11554 bool VisitMemberExpr(const MemberExpr *E) { 11555 if (!CodeGenFunction::IsWrappedCXXThis(E->getBase())) 11556 return false; 11557 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11558 llvm::reverse(LPM)) { 11559 auto It = D.DeclToUniqueName.find(E->getMemberDecl()); 11560 if (It == D.DeclToUniqueName.end()) 11561 continue; 11562 if (D.Disabled) 11563 return false; 11564 FoundE = E; 11565 FoundD = E->getMemberDecl()->getCanonicalDecl(); 11566 UniqueDeclName = It->second; 11567 IVLVal = D.IVLVal; 11568 FoundFn = D.Fn; 11569 break; 11570 } 11571 return FoundE == E; 11572 } 11573 bool VisitStmt(const Stmt *S) { 11574 for (const Stmt *Child : S->children()) { 11575 if (!Child) 11576 continue; 11577 if (const auto *E = dyn_cast<Expr>(Child)) 11578 if (!E->isGLValue()) 11579 continue; 11580 if (Visit(Child)) 11581 return true; 11582 } 11583 return false; 11584 } 11585 explicit LastprivateConditionalRefChecker( 11586 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 11587 : LPM(LPM) {} 11588 std::tuple<const Expr *, const Decl *, StringRef, LValue, llvm::Function *> 11589 getFoundData() const { 11590 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn); 11591 } 11592 }; 11593 } // namespace 11594 11595 void CGOpenMPRuntime::emitLastprivateConditionalUpdate(CodeGenFunction &CGF, 11596 LValue IVLVal, 11597 StringRef UniqueDeclName, 11598 LValue LVal, 11599 SourceLocation Loc) { 11600 // Last updated loop counter for the lastprivate conditional var. 11601 // int<xx> last_iv = 0; 11602 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 11603 llvm::Constant *LastIV = 11604 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 11605 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 11606 IVLVal.getAlignment().getAsAlign()); 11607 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 11608 11609 // Last value of the lastprivate conditional. 11610 // decltype(priv_a) last_a; 11611 llvm::Constant *Last = getOrCreateInternalVariable( 11612 CGF.ConvertTypeForMem(LVal.getType()), UniqueDeclName); 11613 cast<llvm::GlobalVariable>(Last)->setAlignment( 11614 LVal.getAlignment().getAsAlign()); 11615 LValue LastLVal = 11616 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 11617 11618 // Global loop counter. Required to handle inner parallel-for regions. 11619 // iv 11620 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, Loc); 11621 11622 // #pragma omp critical(a) 11623 // if (last_iv <= iv) { 11624 // last_iv = iv; 11625 // last_a = priv_a; 11626 // } 11627 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 11628 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 11629 Action.Enter(CGF); 11630 llvm::Value *LastIVVal = CGF.EmitLoadOfScalar(LastIVLVal, Loc); 11631 // (last_iv <= iv) ? Check if the variable is updated and store new 11632 // value in global var. 11633 llvm::Value *CmpRes; 11634 if (IVLVal.getType()->isSignedIntegerType()) { 11635 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 11636 } else { 11637 assert(IVLVal.getType()->isUnsignedIntegerType() && 11638 "Loop iteration variable must be integer."); 11639 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 11640 } 11641 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 11642 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 11643 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 11644 // { 11645 CGF.EmitBlock(ThenBB); 11646 11647 // last_iv = iv; 11648 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 11649 11650 // last_a = priv_a; 11651 switch (CGF.getEvaluationKind(LVal.getType())) { 11652 case TEK_Scalar: { 11653 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, Loc); 11654 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 11655 break; 11656 } 11657 case TEK_Complex: { 11658 CodeGenFunction::ComplexPairTy PrivVal = CGF.EmitLoadOfComplex(LVal, Loc); 11659 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 11660 break; 11661 } 11662 case TEK_Aggregate: 11663 llvm_unreachable( 11664 "Aggregates are not supported in lastprivate conditional."); 11665 } 11666 // } 11667 CGF.EmitBranch(ExitBB); 11668 // There is no need to emit line number for unconditional branch. 11669 (void)ApplyDebugLocation::CreateEmpty(CGF); 11670 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 11671 }; 11672 11673 if (CGM.getLangOpts().OpenMPSimd) { 11674 // Do not emit as a critical region as no parallel region could be emitted. 11675 RegionCodeGenTy ThenRCG(CodeGen); 11676 ThenRCG(CGF); 11677 } else { 11678 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, Loc); 11679 } 11680 } 11681 11682 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 11683 const Expr *LHS) { 11684 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11685 return; 11686 LastprivateConditionalRefChecker Checker(LastprivateConditionalStack); 11687 if (!Checker.Visit(LHS)) 11688 return; 11689 const Expr *FoundE; 11690 const Decl *FoundD; 11691 StringRef UniqueDeclName; 11692 LValue IVLVal; 11693 llvm::Function *FoundFn; 11694 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal, FoundFn) = 11695 Checker.getFoundData(); 11696 if (FoundFn != CGF.CurFn) { 11697 // Special codegen for inner parallel regions. 11698 // ((struct.lastprivate.conditional*)&priv_a)->Fired = 1; 11699 auto It = LastprivateConditionalToTypes[FoundFn].find(FoundD); 11700 assert(It != LastprivateConditionalToTypes[FoundFn].end() && 11701 "Lastprivate conditional is not found in outer region."); 11702 QualType StructTy = std::get<0>(It->getSecond()); 11703 const FieldDecl* FiredDecl = std::get<2>(It->getSecond()); 11704 LValue PrivLVal = CGF.EmitLValue(FoundE); 11705 Address StructAddr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11706 PrivLVal.getAddress(CGF), 11707 CGF.ConvertTypeForMem(CGF.getContext().getPointerType(StructTy))); 11708 LValue BaseLVal = 11709 CGF.MakeAddrLValue(StructAddr, StructTy, AlignmentSource::Decl); 11710 LValue FiredLVal = CGF.EmitLValueForField(BaseLVal, FiredDecl); 11711 CGF.EmitAtomicStore(RValue::get(llvm::ConstantInt::get( 11712 CGF.ConvertTypeForMem(FiredDecl->getType()), 1)), 11713 FiredLVal, llvm::AtomicOrdering::Unordered, 11714 /*IsVolatile=*/true, /*isInit=*/false); 11715 return; 11716 } 11717 11718 // Private address of the lastprivate conditional in the current context. 11719 // priv_a 11720 LValue LVal = CGF.EmitLValue(FoundE); 11721 emitLastprivateConditionalUpdate(CGF, IVLVal, UniqueDeclName, LVal, 11722 FoundE->getExprLoc()); 11723 } 11724 11725 void CGOpenMPRuntime::checkAndEmitSharedLastprivateConditional( 11726 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11727 const llvm::DenseSet<CanonicalDeclPtr<const VarDecl>> &IgnoredDecls) { 11728 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty()) 11729 return; 11730 auto Range = llvm::reverse(LastprivateConditionalStack); 11731 auto It = llvm::find_if( 11732 Range, [](const LastprivateConditionalData &D) { return !D.Disabled; }); 11733 if (It == Range.end() || It->Fn != CGF.CurFn) 11734 return; 11735 auto LPCI = LastprivateConditionalToTypes.find(It->Fn); 11736 assert(LPCI != LastprivateConditionalToTypes.end() && 11737 "Lastprivates must be registered already."); 11738 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; 11739 getOpenMPCaptureRegions(CaptureRegions, D.getDirectiveKind()); 11740 const CapturedStmt *CS = D.getCapturedStmt(CaptureRegions.back()); 11741 for (const auto &Pair : It->DeclToUniqueName) { 11742 const auto *VD = cast<VarDecl>(Pair.first->getCanonicalDecl()); 11743 if (!CS->capturesVariable(VD) || IgnoredDecls.count(VD) > 0) 11744 continue; 11745 auto I = LPCI->getSecond().find(Pair.first); 11746 assert(I != LPCI->getSecond().end() && 11747 "Lastprivate must be rehistered already."); 11748 // bool Cmp = priv_a.Fired != 0; 11749 LValue BaseLVal = std::get<3>(I->getSecond()); 11750 LValue FiredLVal = 11751 CGF.EmitLValueForField(BaseLVal, std::get<2>(I->getSecond())); 11752 llvm::Value *Res = CGF.EmitLoadOfScalar(FiredLVal, D.getBeginLoc()); 11753 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Res); 11754 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lpc.then"); 11755 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("lpc.done"); 11756 // if (Cmp) { 11757 CGF.Builder.CreateCondBr(Cmp, ThenBB, DoneBB); 11758 CGF.EmitBlock(ThenBB); 11759 Address Addr = CGF.GetAddrOfLocalVar(VD); 11760 LValue LVal; 11761 if (VD->getType()->isReferenceType()) 11762 LVal = CGF.EmitLoadOfReferenceLValue(Addr, VD->getType(), 11763 AlignmentSource::Decl); 11764 else 11765 LVal = CGF.MakeAddrLValue(Addr, VD->getType().getNonReferenceType(), 11766 AlignmentSource::Decl); 11767 emitLastprivateConditionalUpdate(CGF, It->IVLVal, Pair.second, LVal, 11768 D.getBeginLoc()); 11769 auto AL = ApplyDebugLocation::CreateArtificial(CGF); 11770 CGF.EmitBlock(DoneBB, /*IsFinal=*/true); 11771 // } 11772 } 11773 } 11774 11775 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 11776 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 11777 SourceLocation Loc) { 11778 if (CGF.getLangOpts().OpenMP < 50) 11779 return; 11780 auto It = LastprivateConditionalStack.back().DeclToUniqueName.find(VD); 11781 assert(It != LastprivateConditionalStack.back().DeclToUniqueName.end() && 11782 "Unknown lastprivate conditional variable."); 11783 StringRef UniqueName = It->second; 11784 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 11785 // The variable was not updated in the region - exit. 11786 if (!GV) 11787 return; 11788 LValue LPLVal = CGF.MakeAddrLValue( 11789 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 11790 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 11791 CGF.EmitStoreOfScalar(Res, PrivLVal); 11792 } 11793 11794 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11795 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11796 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11797 llvm_unreachable("Not supported in SIMD-only mode"); 11798 } 11799 11800 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11801 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11802 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11803 llvm_unreachable("Not supported in SIMD-only mode"); 11804 } 11805 11806 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11807 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11808 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11809 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11810 bool Tied, unsigned &NumberOfParts) { 11811 llvm_unreachable("Not supported in SIMD-only mode"); 11812 } 11813 11814 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11815 SourceLocation Loc, 11816 llvm::Function *OutlinedFn, 11817 ArrayRef<llvm::Value *> CapturedVars, 11818 const Expr *IfCond) { 11819 llvm_unreachable("Not supported in SIMD-only mode"); 11820 } 11821 11822 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11823 CodeGenFunction &CGF, StringRef CriticalName, 11824 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11825 const Expr *Hint) { 11826 llvm_unreachable("Not supported in SIMD-only mode"); 11827 } 11828 11829 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11830 const RegionCodeGenTy &MasterOpGen, 11831 SourceLocation Loc) { 11832 llvm_unreachable("Not supported in SIMD-only mode"); 11833 } 11834 11835 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11836 SourceLocation Loc) { 11837 llvm_unreachable("Not supported in SIMD-only mode"); 11838 } 11839 11840 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11841 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11842 SourceLocation Loc) { 11843 llvm_unreachable("Not supported in SIMD-only mode"); 11844 } 11845 11846 void CGOpenMPSIMDRuntime::emitSingleRegion( 11847 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11848 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11849 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11850 ArrayRef<const Expr *> AssignmentOps) { 11851 llvm_unreachable("Not supported in SIMD-only mode"); 11852 } 11853 11854 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11855 const RegionCodeGenTy &OrderedOpGen, 11856 SourceLocation Loc, 11857 bool IsThreads) { 11858 llvm_unreachable("Not supported in SIMD-only mode"); 11859 } 11860 11861 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11862 SourceLocation Loc, 11863 OpenMPDirectiveKind Kind, 11864 bool EmitChecks, 11865 bool ForceSimpleCall) { 11866 llvm_unreachable("Not supported in SIMD-only mode"); 11867 } 11868 11869 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11870 CodeGenFunction &CGF, SourceLocation Loc, 11871 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11872 bool Ordered, const DispatchRTInput &DispatchValues) { 11873 llvm_unreachable("Not supported in SIMD-only mode"); 11874 } 11875 11876 void CGOpenMPSIMDRuntime::emitForStaticInit( 11877 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11878 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11879 llvm_unreachable("Not supported in SIMD-only mode"); 11880 } 11881 11882 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11883 CodeGenFunction &CGF, SourceLocation Loc, 11884 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11885 llvm_unreachable("Not supported in SIMD-only mode"); 11886 } 11887 11888 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11889 SourceLocation Loc, 11890 unsigned IVSize, 11891 bool IVSigned) { 11892 llvm_unreachable("Not supported in SIMD-only mode"); 11893 } 11894 11895 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11896 SourceLocation Loc, 11897 OpenMPDirectiveKind DKind) { 11898 llvm_unreachable("Not supported in SIMD-only mode"); 11899 } 11900 11901 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11902 SourceLocation Loc, 11903 unsigned IVSize, bool IVSigned, 11904 Address IL, Address LB, 11905 Address UB, Address ST) { 11906 llvm_unreachable("Not supported in SIMD-only mode"); 11907 } 11908 11909 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11910 llvm::Value *NumThreads, 11911 SourceLocation Loc) { 11912 llvm_unreachable("Not supported in SIMD-only mode"); 11913 } 11914 11915 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11916 ProcBindKind ProcBind, 11917 SourceLocation Loc) { 11918 llvm_unreachable("Not supported in SIMD-only mode"); 11919 } 11920 11921 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11922 const VarDecl *VD, 11923 Address VDAddr, 11924 SourceLocation Loc) { 11925 llvm_unreachable("Not supported in SIMD-only mode"); 11926 } 11927 11928 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11929 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11930 CodeGenFunction *CGF) { 11931 llvm_unreachable("Not supported in SIMD-only mode"); 11932 } 11933 11934 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11935 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11936 llvm_unreachable("Not supported in SIMD-only mode"); 11937 } 11938 11939 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11940 ArrayRef<const Expr *> Vars, 11941 SourceLocation Loc) { 11942 llvm_unreachable("Not supported in SIMD-only mode"); 11943 } 11944 11945 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11946 const OMPExecutableDirective &D, 11947 llvm::Function *TaskFunction, 11948 QualType SharedsTy, Address Shareds, 11949 const Expr *IfCond, 11950 const OMPTaskDataTy &Data) { 11951 llvm_unreachable("Not supported in SIMD-only mode"); 11952 } 11953 11954 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11955 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11956 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11957 const Expr *IfCond, const OMPTaskDataTy &Data) { 11958 llvm_unreachable("Not supported in SIMD-only mode"); 11959 } 11960 11961 void CGOpenMPSIMDRuntime::emitReduction( 11962 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11963 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11964 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11965 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11966 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 11967 ReductionOps, Options); 11968 } 11969 11970 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 11971 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 11972 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 11973 llvm_unreachable("Not supported in SIMD-only mode"); 11974 } 11975 11976 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 11977 SourceLocation Loc, 11978 ReductionCodeGen &RCG, 11979 unsigned N) { 11980 llvm_unreachable("Not supported in SIMD-only mode"); 11981 } 11982 11983 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 11984 SourceLocation Loc, 11985 llvm::Value *ReductionsPtr, 11986 LValue SharedLVal) { 11987 llvm_unreachable("Not supported in SIMD-only mode"); 11988 } 11989 11990 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 11991 SourceLocation Loc) { 11992 llvm_unreachable("Not supported in SIMD-only mode"); 11993 } 11994 11995 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 11996 CodeGenFunction &CGF, SourceLocation Loc, 11997 OpenMPDirectiveKind CancelRegion) { 11998 llvm_unreachable("Not supported in SIMD-only mode"); 11999 } 12000 12001 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 12002 SourceLocation Loc, const Expr *IfCond, 12003 OpenMPDirectiveKind CancelRegion) { 12004 llvm_unreachable("Not supported in SIMD-only mode"); 12005 } 12006 12007 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 12008 const OMPExecutableDirective &D, StringRef ParentName, 12009 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 12010 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 12011 llvm_unreachable("Not supported in SIMD-only mode"); 12012 } 12013 12014 void CGOpenMPSIMDRuntime::emitTargetCall( 12015 CodeGenFunction &CGF, const OMPExecutableDirective &D, 12016 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 12017 const Expr *Device, 12018 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 12019 const OMPLoopDirective &D)> 12020 SizeEmitter) { 12021 llvm_unreachable("Not supported in SIMD-only mode"); 12022 } 12023 12024 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 12025 llvm_unreachable("Not supported in SIMD-only mode"); 12026 } 12027 12028 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 12029 llvm_unreachable("Not supported in SIMD-only mode"); 12030 } 12031 12032 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 12033 return false; 12034 } 12035 12036 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 12037 const OMPExecutableDirective &D, 12038 SourceLocation Loc, 12039 llvm::Function *OutlinedFn, 12040 ArrayRef<llvm::Value *> CapturedVars) { 12041 llvm_unreachable("Not supported in SIMD-only mode"); 12042 } 12043 12044 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 12045 const Expr *NumTeams, 12046 const Expr *ThreadLimit, 12047 SourceLocation Loc) { 12048 llvm_unreachable("Not supported in SIMD-only mode"); 12049 } 12050 12051 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 12052 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12053 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 12054 llvm_unreachable("Not supported in SIMD-only mode"); 12055 } 12056 12057 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 12058 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 12059 const Expr *Device) { 12060 llvm_unreachable("Not supported in SIMD-only mode"); 12061 } 12062 12063 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 12064 const OMPLoopDirective &D, 12065 ArrayRef<Expr *> NumIterations) { 12066 llvm_unreachable("Not supported in SIMD-only mode"); 12067 } 12068 12069 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 12070 const OMPDependClause *C) { 12071 llvm_unreachable("Not supported in SIMD-only mode"); 12072 } 12073 12074 const VarDecl * 12075 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 12076 const VarDecl *NativeParam) const { 12077 llvm_unreachable("Not supported in SIMD-only mode"); 12078 } 12079 12080 Address 12081 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 12082 const VarDecl *NativeParam, 12083 const VarDecl *TargetParam) const { 12084 llvm_unreachable("Not supported in SIMD-only mode"); 12085 } 12086