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 "CGCXXABI.h" 14 #include "CGCleanup.h" 15 #include "CGOpenMPRuntime.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/CodeGen/ConstantInitBuilder.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/StmtOpenMP.h" 21 #include "clang/Basic/BitmaskEnum.h" 22 #include "llvm/ADT/ArrayRef.h" 23 #include "llvm/Bitcode/BitcodeReader.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/IR/GlobalValue.h" 26 #include "llvm/IR/Value.h" 27 #include "llvm/Support/Format.h" 28 #include "llvm/Support/raw_ostream.h" 29 #include <cassert> 30 31 using namespace clang; 32 using namespace CodeGen; 33 34 namespace { 35 /// Base class for handling code generation inside OpenMP regions. 36 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 37 public: 38 /// Kinds of OpenMP regions used in codegen. 39 enum CGOpenMPRegionKind { 40 /// Region with outlined function for standalone 'parallel' 41 /// directive. 42 ParallelOutlinedRegion, 43 /// Region with outlined function for standalone 'task' directive. 44 TaskOutlinedRegion, 45 /// Region for constructs that do not require function outlining, 46 /// like 'for', 'sections', 'atomic' etc. directives. 47 InlinedRegion, 48 /// Region with outlined function for standalone 'target' directive. 49 TargetRegion, 50 }; 51 52 CGOpenMPRegionInfo(const CapturedStmt &CS, 53 const CGOpenMPRegionKind RegionKind, 54 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 55 bool HasCancel) 56 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 57 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 58 59 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 60 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 61 bool HasCancel) 62 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 63 Kind(Kind), HasCancel(HasCancel) {} 64 65 /// Get a variable or parameter for storing global thread id 66 /// inside OpenMP construct. 67 virtual const VarDecl *getThreadIDVariable() const = 0; 68 69 /// Emit the captured statement body. 70 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 71 72 /// Get an LValue for the current ThreadID variable. 73 /// \return LValue for thread id variable. This LValue always has type int32*. 74 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 75 76 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 77 78 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 79 80 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 81 82 bool hasCancel() const { return HasCancel; } 83 84 static bool classof(const CGCapturedStmtInfo *Info) { 85 return Info->getKind() == CR_OpenMP; 86 } 87 88 ~CGOpenMPRegionInfo() override = default; 89 90 protected: 91 CGOpenMPRegionKind RegionKind; 92 RegionCodeGenTy CodeGen; 93 OpenMPDirectiveKind Kind; 94 bool HasCancel; 95 }; 96 97 /// API for captured statement code generation in OpenMP constructs. 98 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 99 public: 100 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 101 const RegionCodeGenTy &CodeGen, 102 OpenMPDirectiveKind Kind, bool HasCancel, 103 StringRef HelperName) 104 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 105 HasCancel), 106 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 107 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 108 } 109 110 /// Get a variable or parameter for storing global thread id 111 /// inside OpenMP construct. 112 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 113 114 /// Get the name of the capture helper. 115 StringRef getHelperName() const override { return HelperName; } 116 117 static bool classof(const CGCapturedStmtInfo *Info) { 118 return CGOpenMPRegionInfo::classof(Info) && 119 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 120 ParallelOutlinedRegion; 121 } 122 123 private: 124 /// A variable or parameter storing global thread id for OpenMP 125 /// constructs. 126 const VarDecl *ThreadIDVar; 127 StringRef HelperName; 128 }; 129 130 /// API for captured statement code generation in OpenMP constructs. 131 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 132 public: 133 class UntiedTaskActionTy final : public PrePostActionTy { 134 bool Untied; 135 const VarDecl *PartIDVar; 136 const RegionCodeGenTy UntiedCodeGen; 137 llvm::SwitchInst *UntiedSwitch = nullptr; 138 139 public: 140 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 141 const RegionCodeGenTy &UntiedCodeGen) 142 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 143 void Enter(CodeGenFunction &CGF) override { 144 if (Untied) { 145 // Emit task switching point. 146 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 147 CGF.GetAddrOfLocalVar(PartIDVar), 148 PartIDVar->getType()->castAs<PointerType>()); 149 llvm::Value *Res = 150 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 151 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 152 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 153 CGF.EmitBlock(DoneBB); 154 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 155 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 156 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 157 CGF.Builder.GetInsertBlock()); 158 emitUntiedSwitch(CGF); 159 } 160 } 161 void emitUntiedSwitch(CodeGenFunction &CGF) const { 162 if (Untied) { 163 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 164 CGF.GetAddrOfLocalVar(PartIDVar), 165 PartIDVar->getType()->castAs<PointerType>()); 166 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 167 PartIdLVal); 168 UntiedCodeGen(CGF); 169 CodeGenFunction::JumpDest CurPoint = 170 CGF.getJumpDestInCurrentScope(".untied.next."); 171 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 172 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 173 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 174 CGF.Builder.GetInsertBlock()); 175 CGF.EmitBranchThroughCleanup(CurPoint); 176 CGF.EmitBlock(CurPoint.getBlock()); 177 } 178 } 179 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 180 }; 181 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 182 const VarDecl *ThreadIDVar, 183 const RegionCodeGenTy &CodeGen, 184 OpenMPDirectiveKind Kind, bool HasCancel, 185 const UntiedTaskActionTy &Action) 186 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 187 ThreadIDVar(ThreadIDVar), Action(Action) { 188 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 189 } 190 191 /// Get a variable or parameter for storing global thread id 192 /// inside OpenMP construct. 193 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 194 195 /// Get an LValue for the current ThreadID variable. 196 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 197 198 /// Get the name of the capture helper. 199 StringRef getHelperName() const override { return ".omp_outlined."; } 200 201 void emitUntiedSwitch(CodeGenFunction &CGF) override { 202 Action.emitUntiedSwitch(CGF); 203 } 204 205 static bool classof(const CGCapturedStmtInfo *Info) { 206 return CGOpenMPRegionInfo::classof(Info) && 207 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 208 TaskOutlinedRegion; 209 } 210 211 private: 212 /// A variable or parameter storing global thread id for OpenMP 213 /// constructs. 214 const VarDecl *ThreadIDVar; 215 /// Action for emitting code for untied tasks. 216 const UntiedTaskActionTy &Action; 217 }; 218 219 /// API for inlined captured statement code generation in OpenMP 220 /// constructs. 221 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 222 public: 223 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 224 const RegionCodeGenTy &CodeGen, 225 OpenMPDirectiveKind Kind, bool HasCancel) 226 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 227 OldCSI(OldCSI), 228 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 229 230 // Retrieve the value of the context parameter. 231 llvm::Value *getContextValue() const override { 232 if (OuterRegionInfo) 233 return OuterRegionInfo->getContextValue(); 234 llvm_unreachable("No context value for inlined OpenMP region"); 235 } 236 237 void setContextValue(llvm::Value *V) override { 238 if (OuterRegionInfo) { 239 OuterRegionInfo->setContextValue(V); 240 return; 241 } 242 llvm_unreachable("No context value for inlined OpenMP region"); 243 } 244 245 /// Lookup the captured field decl for a variable. 246 const FieldDecl *lookup(const VarDecl *VD) const override { 247 if (OuterRegionInfo) 248 return OuterRegionInfo->lookup(VD); 249 // If there is no outer outlined region,no need to lookup in a list of 250 // captured variables, we can use the original one. 251 return nullptr; 252 } 253 254 FieldDecl *getThisFieldDecl() const override { 255 if (OuterRegionInfo) 256 return OuterRegionInfo->getThisFieldDecl(); 257 return nullptr; 258 } 259 260 /// Get a variable or parameter for storing global thread id 261 /// inside OpenMP construct. 262 const VarDecl *getThreadIDVariable() const override { 263 if (OuterRegionInfo) 264 return OuterRegionInfo->getThreadIDVariable(); 265 return nullptr; 266 } 267 268 /// Get an LValue for the current ThreadID variable. 269 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 270 if (OuterRegionInfo) 271 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 272 llvm_unreachable("No LValue for inlined OpenMP construct"); 273 } 274 275 /// Get the name of the capture helper. 276 StringRef getHelperName() const override { 277 if (auto *OuterRegionInfo = getOldCSI()) 278 return OuterRegionInfo->getHelperName(); 279 llvm_unreachable("No helper name for inlined OpenMP construct"); 280 } 281 282 void emitUntiedSwitch(CodeGenFunction &CGF) override { 283 if (OuterRegionInfo) 284 OuterRegionInfo->emitUntiedSwitch(CGF); 285 } 286 287 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 288 289 static bool classof(const CGCapturedStmtInfo *Info) { 290 return CGOpenMPRegionInfo::classof(Info) && 291 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 292 } 293 294 ~CGOpenMPInlinedRegionInfo() override = default; 295 296 private: 297 /// CodeGen info about outer OpenMP region. 298 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 299 CGOpenMPRegionInfo *OuterRegionInfo; 300 }; 301 302 /// API for captured statement code generation in OpenMP target 303 /// constructs. For this captures, implicit parameters are used instead of the 304 /// captured fields. The name of the target region has to be unique in a given 305 /// application so it is provided by the client, because only the client has 306 /// the information to generate that. 307 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 308 public: 309 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 310 const RegionCodeGenTy &CodeGen, StringRef HelperName) 311 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 312 /*HasCancel=*/false), 313 HelperName(HelperName) {} 314 315 /// This is unused for target regions because each starts executing 316 /// with a single thread. 317 const VarDecl *getThreadIDVariable() const override { return nullptr; } 318 319 /// Get the name of the capture helper. 320 StringRef getHelperName() const override { return HelperName; } 321 322 static bool classof(const CGCapturedStmtInfo *Info) { 323 return CGOpenMPRegionInfo::classof(Info) && 324 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 325 } 326 327 private: 328 StringRef HelperName; 329 }; 330 331 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 332 llvm_unreachable("No codegen for expressions"); 333 } 334 /// API for generation of expressions captured in a innermost OpenMP 335 /// region. 336 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 337 public: 338 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 339 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 340 OMPD_unknown, 341 /*HasCancel=*/false), 342 PrivScope(CGF) { 343 // Make sure the globals captured in the provided statement are local by 344 // using the privatization logic. We assume the same variable is not 345 // captured more than once. 346 for (const auto &C : CS.captures()) { 347 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 348 continue; 349 350 const VarDecl *VD = C.getCapturedVar(); 351 if (VD->isLocalVarDeclOrParm()) 352 continue; 353 354 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 355 /*RefersToEnclosingVariableOrCapture=*/false, 356 VD->getType().getNonReferenceType(), VK_LValue, 357 C.getLocation()); 358 PrivScope.addPrivate( 359 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(); }); 360 } 361 (void)PrivScope.Privatize(); 362 } 363 364 /// Lookup the captured field decl for a variable. 365 const FieldDecl *lookup(const VarDecl *VD) const override { 366 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 367 return FD; 368 return nullptr; 369 } 370 371 /// Emit the captured statement body. 372 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 373 llvm_unreachable("No body for expressions"); 374 } 375 376 /// Get a variable or parameter for storing global thread id 377 /// inside OpenMP construct. 378 const VarDecl *getThreadIDVariable() const override { 379 llvm_unreachable("No thread id for expressions"); 380 } 381 382 /// Get the name of the capture helper. 383 StringRef getHelperName() const override { 384 llvm_unreachable("No helper name for expressions"); 385 } 386 387 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 388 389 private: 390 /// Private scope to capture global variables. 391 CodeGenFunction::OMPPrivateScope PrivScope; 392 }; 393 394 /// RAII for emitting code of OpenMP constructs. 395 class InlinedOpenMPRegionRAII { 396 CodeGenFunction &CGF; 397 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 398 FieldDecl *LambdaThisCaptureField = nullptr; 399 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 400 401 public: 402 /// Constructs region for combined constructs. 403 /// \param CodeGen Code generation sequence for combined directives. Includes 404 /// a list of functions used for code generation of implicitly inlined 405 /// regions. 406 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 407 OpenMPDirectiveKind Kind, bool HasCancel) 408 : CGF(CGF) { 409 // Start emission for the construct. 410 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 411 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 412 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 413 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 414 CGF.LambdaThisCaptureField = nullptr; 415 BlockInfo = CGF.BlockInfo; 416 CGF.BlockInfo = nullptr; 417 } 418 419 ~InlinedOpenMPRegionRAII() { 420 // Restore original CapturedStmtInfo only if we're done with code emission. 421 auto *OldCSI = 422 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 423 delete CGF.CapturedStmtInfo; 424 CGF.CapturedStmtInfo = OldCSI; 425 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 426 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 427 CGF.BlockInfo = BlockInfo; 428 } 429 }; 430 431 /// Values for bit flags used in the ident_t to describe the fields. 432 /// All enumeric elements are named and described in accordance with the code 433 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 434 enum OpenMPLocationFlags : unsigned { 435 /// Use trampoline for internal microtask. 436 OMP_IDENT_IMD = 0x01, 437 /// Use c-style ident structure. 438 OMP_IDENT_KMPC = 0x02, 439 /// Atomic reduction option for kmpc_reduce. 440 OMP_ATOMIC_REDUCE = 0x10, 441 /// Explicit 'barrier' directive. 442 OMP_IDENT_BARRIER_EXPL = 0x20, 443 /// Implicit barrier in code. 444 OMP_IDENT_BARRIER_IMPL = 0x40, 445 /// Implicit barrier in 'for' directive. 446 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 447 /// Implicit barrier in 'sections' directive. 448 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 449 /// Implicit barrier in 'single' directive. 450 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 451 /// Call of __kmp_for_static_init for static loop. 452 OMP_IDENT_WORK_LOOP = 0x200, 453 /// Call of __kmp_for_static_init for sections. 454 OMP_IDENT_WORK_SECTIONS = 0x400, 455 /// Call of __kmp_for_static_init for distribute. 456 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 457 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 458 }; 459 460 namespace { 461 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 462 /// Values for bit flags for marking which requires clauses have been used. 463 enum OpenMPOffloadingRequiresDirFlags : int64_t { 464 /// flag undefined. 465 OMP_REQ_UNDEFINED = 0x000, 466 /// no requires clause present. 467 OMP_REQ_NONE = 0x001, 468 /// reverse_offload clause. 469 OMP_REQ_REVERSE_OFFLOAD = 0x002, 470 /// unified_address clause. 471 OMP_REQ_UNIFIED_ADDRESS = 0x004, 472 /// unified_shared_memory clause. 473 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 474 /// dynamic_allocators clause. 475 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 476 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 477 }; 478 479 enum OpenMPOffloadingReservedDeviceIDs { 480 /// Device ID if the device was not defined, runtime should get it 481 /// from environment variables in the spec. 482 OMP_DEVICEID_UNDEF = -1, 483 }; 484 } // anonymous namespace 485 486 /// Describes ident structure that describes a source location. 487 /// All descriptions are taken from 488 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 489 /// Original structure: 490 /// typedef struct ident { 491 /// kmp_int32 reserved_1; /**< might be used in Fortran; 492 /// see above */ 493 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 494 /// KMP_IDENT_KMPC identifies this union 495 /// member */ 496 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 497 /// see above */ 498 ///#if USE_ITT_BUILD 499 /// /* but currently used for storing 500 /// region-specific ITT */ 501 /// /* contextual information. */ 502 ///#endif /* USE_ITT_BUILD */ 503 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 504 /// C++ */ 505 /// char const *psource; /**< String describing the source location. 506 /// The string is composed of semi-colon separated 507 // fields which describe the source file, 508 /// the function and a pair of line numbers that 509 /// delimit the construct. 510 /// */ 511 /// } ident_t; 512 enum IdentFieldIndex { 513 /// might be used in Fortran 514 IdentField_Reserved_1, 515 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 516 IdentField_Flags, 517 /// Not really used in Fortran any more 518 IdentField_Reserved_2, 519 /// Source[4] in Fortran, do not use for C++ 520 IdentField_Reserved_3, 521 /// String describing the source location. The string is composed of 522 /// semi-colon separated fields which describe the source file, the function 523 /// and a pair of line numbers that delimit the construct. 524 IdentField_PSource 525 }; 526 527 /// Schedule types for 'omp for' loops (these enumerators are taken from 528 /// the enum sched_type in kmp.h). 529 enum OpenMPSchedType { 530 /// Lower bound for default (unordered) versions. 531 OMP_sch_lower = 32, 532 OMP_sch_static_chunked = 33, 533 OMP_sch_static = 34, 534 OMP_sch_dynamic_chunked = 35, 535 OMP_sch_guided_chunked = 36, 536 OMP_sch_runtime = 37, 537 OMP_sch_auto = 38, 538 /// static with chunk adjustment (e.g., simd) 539 OMP_sch_static_balanced_chunked = 45, 540 /// Lower bound for 'ordered' versions. 541 OMP_ord_lower = 64, 542 OMP_ord_static_chunked = 65, 543 OMP_ord_static = 66, 544 OMP_ord_dynamic_chunked = 67, 545 OMP_ord_guided_chunked = 68, 546 OMP_ord_runtime = 69, 547 OMP_ord_auto = 70, 548 OMP_sch_default = OMP_sch_static, 549 /// dist_schedule types 550 OMP_dist_sch_static_chunked = 91, 551 OMP_dist_sch_static = 92, 552 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 553 /// Set if the monotonic schedule modifier was present. 554 OMP_sch_modifier_monotonic = (1 << 29), 555 /// Set if the nonmonotonic schedule modifier was present. 556 OMP_sch_modifier_nonmonotonic = (1 << 30), 557 }; 558 559 enum OpenMPRTLFunction { 560 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 561 /// kmpc_micro microtask, ...); 562 OMPRTL__kmpc_fork_call, 563 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 564 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 565 OMPRTL__kmpc_threadprivate_cached, 566 /// Call to void __kmpc_threadprivate_register( ident_t *, 567 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 568 OMPRTL__kmpc_threadprivate_register, 569 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 570 OMPRTL__kmpc_global_thread_num, 571 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 572 // kmp_critical_name *crit); 573 OMPRTL__kmpc_critical, 574 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 575 // global_tid, kmp_critical_name *crit, uintptr_t hint); 576 OMPRTL__kmpc_critical_with_hint, 577 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 578 // kmp_critical_name *crit); 579 OMPRTL__kmpc_end_critical, 580 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 581 // global_tid); 582 OMPRTL__kmpc_cancel_barrier, 583 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 584 OMPRTL__kmpc_barrier, 585 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 586 OMPRTL__kmpc_for_static_fini, 587 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 588 // global_tid); 589 OMPRTL__kmpc_serialized_parallel, 590 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 591 // global_tid); 592 OMPRTL__kmpc_end_serialized_parallel, 593 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 594 // kmp_int32 num_threads); 595 OMPRTL__kmpc_push_num_threads, 596 // Call to void __kmpc_flush(ident_t *loc); 597 OMPRTL__kmpc_flush, 598 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 599 OMPRTL__kmpc_master, 600 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 601 OMPRTL__kmpc_end_master, 602 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 603 // int end_part); 604 OMPRTL__kmpc_omp_taskyield, 605 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 606 OMPRTL__kmpc_single, 607 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 608 OMPRTL__kmpc_end_single, 609 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 610 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 611 // kmp_routine_entry_t *task_entry); 612 OMPRTL__kmpc_omp_task_alloc, 613 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 614 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 615 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 616 // kmp_int64 device_id); 617 OMPRTL__kmpc_omp_target_task_alloc, 618 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 619 // new_task); 620 OMPRTL__kmpc_omp_task, 621 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 622 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 623 // kmp_int32 didit); 624 OMPRTL__kmpc_copyprivate, 625 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 626 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 627 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 628 OMPRTL__kmpc_reduce, 629 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 630 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 631 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 632 // *lck); 633 OMPRTL__kmpc_reduce_nowait, 634 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 635 // kmp_critical_name *lck); 636 OMPRTL__kmpc_end_reduce, 637 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 638 // kmp_critical_name *lck); 639 OMPRTL__kmpc_end_reduce_nowait, 640 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 641 // kmp_task_t * new_task); 642 OMPRTL__kmpc_omp_task_begin_if0, 643 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 644 // kmp_task_t * new_task); 645 OMPRTL__kmpc_omp_task_complete_if0, 646 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 647 OMPRTL__kmpc_ordered, 648 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 649 OMPRTL__kmpc_end_ordered, 650 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 651 // global_tid); 652 OMPRTL__kmpc_omp_taskwait, 653 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 654 OMPRTL__kmpc_taskgroup, 655 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 656 OMPRTL__kmpc_end_taskgroup, 657 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 658 // int proc_bind); 659 OMPRTL__kmpc_push_proc_bind, 660 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 661 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 662 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 663 OMPRTL__kmpc_omp_task_with_deps, 664 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 665 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 666 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 667 OMPRTL__kmpc_omp_wait_deps, 668 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 669 // global_tid, kmp_int32 cncl_kind); 670 OMPRTL__kmpc_cancellationpoint, 671 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 672 // kmp_int32 cncl_kind); 673 OMPRTL__kmpc_cancel, 674 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 675 // kmp_int32 num_teams, kmp_int32 thread_limit); 676 OMPRTL__kmpc_push_num_teams, 677 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 678 // microtask, ...); 679 OMPRTL__kmpc_fork_teams, 680 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 681 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 682 // sched, kmp_uint64 grainsize, void *task_dup); 683 OMPRTL__kmpc_taskloop, 684 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 685 // num_dims, struct kmp_dim *dims); 686 OMPRTL__kmpc_doacross_init, 687 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 688 OMPRTL__kmpc_doacross_fini, 689 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 690 // *vec); 691 OMPRTL__kmpc_doacross_post, 692 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 693 // *vec); 694 OMPRTL__kmpc_doacross_wait, 695 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 696 // *data); 697 OMPRTL__kmpc_task_reduction_init, 698 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 699 // *d); 700 OMPRTL__kmpc_task_reduction_get_th_data, 701 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 702 OMPRTL__kmpc_alloc, 703 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 704 OMPRTL__kmpc_free, 705 706 // 707 // Offloading related calls 708 // 709 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 710 // size); 711 OMPRTL__kmpc_push_target_tripcount, 712 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 713 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 714 // *arg_types); 715 OMPRTL__tgt_target, 716 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 717 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 718 // *arg_types); 719 OMPRTL__tgt_target_nowait, 720 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 721 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 722 // *arg_types, int32_t num_teams, int32_t thread_limit); 723 OMPRTL__tgt_target_teams, 724 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 725 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 726 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 727 OMPRTL__tgt_target_teams_nowait, 728 // Call to void __tgt_register_requires(int64_t flags); 729 OMPRTL__tgt_register_requires, 730 // Call to void __tgt_register_lib(__tgt_bin_desc *desc); 731 OMPRTL__tgt_register_lib, 732 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); 733 OMPRTL__tgt_unregister_lib, 734 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 735 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 736 OMPRTL__tgt_target_data_begin, 737 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 738 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 739 // *arg_types); 740 OMPRTL__tgt_target_data_begin_nowait, 741 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 742 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 743 OMPRTL__tgt_target_data_end, 744 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 745 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 746 // *arg_types); 747 OMPRTL__tgt_target_data_end_nowait, 748 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 749 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 750 OMPRTL__tgt_target_data_update, 751 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 752 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 753 // *arg_types); 754 OMPRTL__tgt_target_data_update_nowait, 755 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 756 OMPRTL__tgt_mapper_num_components, 757 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 758 // *base, void *begin, int64_t size, int64_t type); 759 OMPRTL__tgt_push_mapper_component, 760 }; 761 762 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 763 /// region. 764 class CleanupTy final : public EHScopeStack::Cleanup { 765 PrePostActionTy *Action; 766 767 public: 768 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 769 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 770 if (!CGF.HaveInsertPoint()) 771 return; 772 Action->Exit(CGF); 773 } 774 }; 775 776 } // anonymous namespace 777 778 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 779 CodeGenFunction::RunCleanupsScope Scope(CGF); 780 if (PrePostAction) { 781 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 782 Callback(CodeGen, CGF, *PrePostAction); 783 } else { 784 PrePostActionTy Action; 785 Callback(CodeGen, CGF, Action); 786 } 787 } 788 789 /// Check if the combiner is a call to UDR combiner and if it is so return the 790 /// UDR decl used for reduction. 791 static const OMPDeclareReductionDecl * 792 getReductionInit(const Expr *ReductionOp) { 793 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 794 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 795 if (const auto *DRE = 796 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 797 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 798 return DRD; 799 return nullptr; 800 } 801 802 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 803 const OMPDeclareReductionDecl *DRD, 804 const Expr *InitOp, 805 Address Private, Address Original, 806 QualType Ty) { 807 if (DRD->getInitializer()) { 808 std::pair<llvm::Function *, llvm::Function *> Reduction = 809 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 810 const auto *CE = cast<CallExpr>(InitOp); 811 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 812 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 813 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 814 const auto *LHSDRE = 815 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 816 const auto *RHSDRE = 817 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 818 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 819 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 820 [=]() { return Private; }); 821 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 822 [=]() { return Original; }); 823 (void)PrivateScope.Privatize(); 824 RValue Func = RValue::get(Reduction.second); 825 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 826 CGF.EmitIgnoredExpr(InitOp); 827 } else { 828 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 829 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 830 auto *GV = new llvm::GlobalVariable( 831 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 832 llvm::GlobalValue::PrivateLinkage, Init, Name); 833 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 834 RValue InitRVal; 835 switch (CGF.getEvaluationKind(Ty)) { 836 case TEK_Scalar: 837 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 838 break; 839 case TEK_Complex: 840 InitRVal = 841 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 842 break; 843 case TEK_Aggregate: 844 InitRVal = RValue::getAggregate(LV.getAddress()); 845 break; 846 } 847 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 848 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 849 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 850 /*IsInitializer=*/false); 851 } 852 } 853 854 /// Emit initialization of arrays of complex types. 855 /// \param DestAddr Address of the array. 856 /// \param Type Type of array. 857 /// \param Init Initial expression of array. 858 /// \param SrcAddr Address of the original array. 859 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 860 QualType Type, bool EmitDeclareReductionInit, 861 const Expr *Init, 862 const OMPDeclareReductionDecl *DRD, 863 Address SrcAddr = Address::invalid()) { 864 // Perform element-by-element initialization. 865 QualType ElementTy; 866 867 // Drill down to the base element type on both arrays. 868 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 869 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 870 DestAddr = 871 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 872 if (DRD) 873 SrcAddr = 874 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 875 876 llvm::Value *SrcBegin = nullptr; 877 if (DRD) 878 SrcBegin = SrcAddr.getPointer(); 879 llvm::Value *DestBegin = DestAddr.getPointer(); 880 // Cast from pointer to array type to pointer to single element. 881 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 882 // The basic structure here is a while-do loop. 883 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 884 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 885 llvm::Value *IsEmpty = 886 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 887 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 888 889 // Enter the loop body, making that address the current address. 890 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 891 CGF.EmitBlock(BodyBB); 892 893 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 894 895 llvm::PHINode *SrcElementPHI = nullptr; 896 Address SrcElementCurrent = Address::invalid(); 897 if (DRD) { 898 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 899 "omp.arraycpy.srcElementPast"); 900 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 901 SrcElementCurrent = 902 Address(SrcElementPHI, 903 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 904 } 905 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 906 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 907 DestElementPHI->addIncoming(DestBegin, EntryBB); 908 Address DestElementCurrent = 909 Address(DestElementPHI, 910 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 911 912 // Emit copy. 913 { 914 CodeGenFunction::RunCleanupsScope InitScope(CGF); 915 if (EmitDeclareReductionInit) { 916 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 917 SrcElementCurrent, ElementTy); 918 } else 919 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 920 /*IsInitializer=*/false); 921 } 922 923 if (DRD) { 924 // Shift the address forward by one element. 925 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 926 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 927 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 928 } 929 930 // Shift the address forward by one element. 931 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 932 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 933 // Check whether we've reached the end. 934 llvm::Value *Done = 935 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 936 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 937 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 938 939 // Done. 940 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 941 } 942 943 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 944 return CGF.EmitOMPSharedLValue(E); 945 } 946 947 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 948 const Expr *E) { 949 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 950 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 951 return LValue(); 952 } 953 954 void ReductionCodeGen::emitAggregateInitialization( 955 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 956 const OMPDeclareReductionDecl *DRD) { 957 // Emit VarDecl with copy init for arrays. 958 // Get the address of the original variable captured in current 959 // captured region. 960 const auto *PrivateVD = 961 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 962 bool EmitDeclareReductionInit = 963 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 964 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 965 EmitDeclareReductionInit, 966 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 967 : PrivateVD->getInit(), 968 DRD, SharedLVal.getAddress()); 969 } 970 971 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 972 ArrayRef<const Expr *> Privates, 973 ArrayRef<const Expr *> ReductionOps) { 974 ClausesData.reserve(Shareds.size()); 975 SharedAddresses.reserve(Shareds.size()); 976 Sizes.reserve(Shareds.size()); 977 BaseDecls.reserve(Shareds.size()); 978 auto IPriv = Privates.begin(); 979 auto IRed = ReductionOps.begin(); 980 for (const Expr *Ref : Shareds) { 981 ClausesData.emplace_back(Ref, *IPriv, *IRed); 982 std::advance(IPriv, 1); 983 std::advance(IRed, 1); 984 } 985 } 986 987 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 988 assert(SharedAddresses.size() == N && 989 "Number of generated lvalues must be exactly N."); 990 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 991 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 992 SharedAddresses.emplace_back(First, Second); 993 } 994 995 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 996 const auto *PrivateVD = 997 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 998 QualType PrivateType = PrivateVD->getType(); 999 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1000 if (!PrivateType->isVariablyModifiedType()) { 1001 Sizes.emplace_back( 1002 CGF.getTypeSize( 1003 SharedAddresses[N].first.getType().getNonReferenceType()), 1004 nullptr); 1005 return; 1006 } 1007 llvm::Value *Size; 1008 llvm::Value *SizeInChars; 1009 auto *ElemType = 1010 cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType()) 1011 ->getElementType(); 1012 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1013 if (AsArraySection) { 1014 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(), 1015 SharedAddresses[N].first.getPointer()); 1016 Size = CGF.Builder.CreateNUWAdd( 1017 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1018 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1019 } else { 1020 SizeInChars = CGF.getTypeSize( 1021 SharedAddresses[N].first.getType().getNonReferenceType()); 1022 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1023 } 1024 Sizes.emplace_back(SizeInChars, Size); 1025 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1026 CGF, 1027 cast<OpaqueValueExpr>( 1028 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1029 RValue::get(Size)); 1030 CGF.EmitVariablyModifiedType(PrivateType); 1031 } 1032 1033 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1034 llvm::Value *Size) { 1035 const auto *PrivateVD = 1036 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1037 QualType PrivateType = PrivateVD->getType(); 1038 if (!PrivateType->isVariablyModifiedType()) { 1039 assert(!Size && !Sizes[N].second && 1040 "Size should be nullptr for non-variably modified reduction " 1041 "items."); 1042 return; 1043 } 1044 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1045 CGF, 1046 cast<OpaqueValueExpr>( 1047 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1048 RValue::get(Size)); 1049 CGF.EmitVariablyModifiedType(PrivateType); 1050 } 1051 1052 void ReductionCodeGen::emitInitialization( 1053 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1054 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1055 assert(SharedAddresses.size() > N && "No variable was generated"); 1056 const auto *PrivateVD = 1057 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1058 const OMPDeclareReductionDecl *DRD = 1059 getReductionInit(ClausesData[N].ReductionOp); 1060 QualType PrivateType = PrivateVD->getType(); 1061 PrivateAddr = CGF.Builder.CreateElementBitCast( 1062 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1063 QualType SharedType = SharedAddresses[N].first.getType(); 1064 SharedLVal = CGF.MakeAddrLValue( 1065 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(), 1066 CGF.ConvertTypeForMem(SharedType)), 1067 SharedType, SharedAddresses[N].first.getBaseInfo(), 1068 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1069 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1070 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1071 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1072 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1073 PrivateAddr, SharedLVal.getAddress(), 1074 SharedLVal.getType()); 1075 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1076 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1077 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1078 PrivateVD->getType().getQualifiers(), 1079 /*IsInitializer=*/false); 1080 } 1081 } 1082 1083 bool ReductionCodeGen::needCleanups(unsigned N) { 1084 const auto *PrivateVD = 1085 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1086 QualType PrivateType = PrivateVD->getType(); 1087 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1088 return DTorKind != QualType::DK_none; 1089 } 1090 1091 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1092 Address PrivateAddr) { 1093 const auto *PrivateVD = 1094 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1095 QualType PrivateType = PrivateVD->getType(); 1096 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1097 if (needCleanups(N)) { 1098 PrivateAddr = CGF.Builder.CreateElementBitCast( 1099 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1100 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1101 } 1102 } 1103 1104 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1105 LValue BaseLV) { 1106 BaseTy = BaseTy.getNonReferenceType(); 1107 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1108 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1109 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1110 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy); 1111 } else { 1112 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy); 1113 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1114 } 1115 BaseTy = BaseTy->getPointeeType(); 1116 } 1117 return CGF.MakeAddrLValue( 1118 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(), 1119 CGF.ConvertTypeForMem(ElTy)), 1120 BaseLV.getType(), BaseLV.getBaseInfo(), 1121 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1122 } 1123 1124 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1125 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1126 llvm::Value *Addr) { 1127 Address Tmp = Address::invalid(); 1128 Address TopTmp = Address::invalid(); 1129 Address MostTopTmp = Address::invalid(); 1130 BaseTy = BaseTy.getNonReferenceType(); 1131 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1132 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1133 Tmp = CGF.CreateMemTemp(BaseTy); 1134 if (TopTmp.isValid()) 1135 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1136 else 1137 MostTopTmp = Tmp; 1138 TopTmp = Tmp; 1139 BaseTy = BaseTy->getPointeeType(); 1140 } 1141 llvm::Type *Ty = BaseLVType; 1142 if (Tmp.isValid()) 1143 Ty = Tmp.getElementType(); 1144 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1145 if (Tmp.isValid()) { 1146 CGF.Builder.CreateStore(Addr, Tmp); 1147 return MostTopTmp; 1148 } 1149 return Address(Addr, BaseLVAlignment); 1150 } 1151 1152 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1153 const VarDecl *OrigVD = nullptr; 1154 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1155 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1156 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1157 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1158 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1159 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1160 DE = cast<DeclRefExpr>(Base); 1161 OrigVD = cast<VarDecl>(DE->getDecl()); 1162 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1163 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1164 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1165 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1166 DE = cast<DeclRefExpr>(Base); 1167 OrigVD = cast<VarDecl>(DE->getDecl()); 1168 } 1169 return OrigVD; 1170 } 1171 1172 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1173 Address PrivateAddr) { 1174 const DeclRefExpr *DE; 1175 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1176 BaseDecls.emplace_back(OrigVD); 1177 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1178 LValue BaseLValue = 1179 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1180 OriginalBaseLValue); 1181 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1182 BaseLValue.getPointer(), SharedAddresses[N].first.getPointer()); 1183 llvm::Value *PrivatePointer = 1184 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1185 PrivateAddr.getPointer(), 1186 SharedAddresses[N].first.getAddress().getType()); 1187 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1188 return castToBase(CGF, OrigVD->getType(), 1189 SharedAddresses[N].first.getType(), 1190 OriginalBaseLValue.getAddress().getType(), 1191 OriginalBaseLValue.getAlignment(), Ptr); 1192 } 1193 BaseDecls.emplace_back( 1194 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1195 return PrivateAddr; 1196 } 1197 1198 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1199 const OMPDeclareReductionDecl *DRD = 1200 getReductionInit(ClausesData[N].ReductionOp); 1201 return DRD && DRD->getInitializer(); 1202 } 1203 1204 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1205 return CGF.EmitLoadOfPointerLValue( 1206 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1207 getThreadIDVariable()->getType()->castAs<PointerType>()); 1208 } 1209 1210 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1211 if (!CGF.HaveInsertPoint()) 1212 return; 1213 // 1.2.2 OpenMP Language Terminology 1214 // Structured block - An executable statement with a single entry at the 1215 // top and a single exit at the bottom. 1216 // The point of exit cannot be a branch out of the structured block. 1217 // longjmp() and throw() must not violate the entry/exit criteria. 1218 CGF.EHStack.pushTerminate(); 1219 CodeGen(CGF); 1220 CGF.EHStack.popTerminate(); 1221 } 1222 1223 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1224 CodeGenFunction &CGF) { 1225 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1226 getThreadIDVariable()->getType(), 1227 AlignmentSource::Decl); 1228 } 1229 1230 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1231 QualType FieldTy) { 1232 auto *Field = FieldDecl::Create( 1233 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1234 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1235 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1236 Field->setAccess(AS_public); 1237 DC->addDecl(Field); 1238 return Field; 1239 } 1240 1241 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1242 StringRef Separator) 1243 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1244 OffloadEntriesInfoManager(CGM) { 1245 ASTContext &C = CGM.getContext(); 1246 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1247 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1248 RD->startDefinition(); 1249 // reserved_1 1250 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1251 // flags 1252 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1253 // reserved_2 1254 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1255 // reserved_3 1256 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1257 // psource 1258 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1259 RD->completeDefinition(); 1260 IdentQTy = C.getRecordType(RD); 1261 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1262 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1263 1264 loadOffloadInfoMetadata(); 1265 } 1266 1267 void CGOpenMPRuntime::clear() { 1268 InternalVars.clear(); 1269 // Clean non-target variable declarations possibly used only in debug info. 1270 for (const auto &Data : EmittedNonTargetVariables) { 1271 if (!Data.getValue().pointsToAliveValue()) 1272 continue; 1273 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1274 if (!GV) 1275 continue; 1276 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1277 continue; 1278 GV->eraseFromParent(); 1279 } 1280 } 1281 1282 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1283 SmallString<128> Buffer; 1284 llvm::raw_svector_ostream OS(Buffer); 1285 StringRef Sep = FirstSeparator; 1286 for (StringRef Part : Parts) { 1287 OS << Sep << Part; 1288 Sep = Separator; 1289 } 1290 return OS.str(); 1291 } 1292 1293 static llvm::Function * 1294 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1295 const Expr *CombinerInitializer, const VarDecl *In, 1296 const VarDecl *Out, bool IsCombiner) { 1297 // void .omp_combiner.(Ty *in, Ty *out); 1298 ASTContext &C = CGM.getContext(); 1299 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1300 FunctionArgList Args; 1301 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1302 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1303 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1304 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1305 Args.push_back(&OmpOutParm); 1306 Args.push_back(&OmpInParm); 1307 const CGFunctionInfo &FnInfo = 1308 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1309 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1310 std::string Name = CGM.getOpenMPRuntime().getName( 1311 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1312 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1313 Name, &CGM.getModule()); 1314 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1315 if (CGM.getLangOpts().Optimize) { 1316 Fn->removeFnAttr(llvm::Attribute::NoInline); 1317 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1318 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1319 } 1320 CodeGenFunction CGF(CGM); 1321 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1322 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1323 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1324 Out->getLocation()); 1325 CodeGenFunction::OMPPrivateScope Scope(CGF); 1326 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1327 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1328 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1329 .getAddress(); 1330 }); 1331 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1332 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1333 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1334 .getAddress(); 1335 }); 1336 (void)Scope.Privatize(); 1337 if (!IsCombiner && Out->hasInit() && 1338 !CGF.isTrivialInitializer(Out->getInit())) { 1339 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1340 Out->getType().getQualifiers(), 1341 /*IsInitializer=*/true); 1342 } 1343 if (CombinerInitializer) 1344 CGF.EmitIgnoredExpr(CombinerInitializer); 1345 Scope.ForceCleanup(); 1346 CGF.FinishFunction(); 1347 return Fn; 1348 } 1349 1350 void CGOpenMPRuntime::emitUserDefinedReduction( 1351 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1352 if (UDRMap.count(D) > 0) 1353 return; 1354 llvm::Function *Combiner = emitCombinerOrInitializer( 1355 CGM, D->getType(), D->getCombiner(), 1356 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1357 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1358 /*IsCombiner=*/true); 1359 llvm::Function *Initializer = nullptr; 1360 if (const Expr *Init = D->getInitializer()) { 1361 Initializer = emitCombinerOrInitializer( 1362 CGM, D->getType(), 1363 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1364 : nullptr, 1365 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1366 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1367 /*IsCombiner=*/false); 1368 } 1369 UDRMap.try_emplace(D, Combiner, Initializer); 1370 if (CGF) { 1371 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1372 Decls.second.push_back(D); 1373 } 1374 } 1375 1376 std::pair<llvm::Function *, llvm::Function *> 1377 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1378 auto I = UDRMap.find(D); 1379 if (I != UDRMap.end()) 1380 return I->second; 1381 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1382 return UDRMap.lookup(D); 1383 } 1384 1385 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1386 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1387 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1388 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1389 assert(ThreadIDVar->getType()->isPointerType() && 1390 "thread id variable must be of type kmp_int32 *"); 1391 CodeGenFunction CGF(CGM, true); 1392 bool HasCancel = false; 1393 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1394 HasCancel = OPD->hasCancel(); 1395 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1396 HasCancel = OPSD->hasCancel(); 1397 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1398 HasCancel = OPFD->hasCancel(); 1399 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1400 HasCancel = OPFD->hasCancel(); 1401 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1402 HasCancel = OPFD->hasCancel(); 1403 else if (const auto *OPFD = 1404 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1405 HasCancel = OPFD->hasCancel(); 1406 else if (const auto *OPFD = 1407 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1408 HasCancel = OPFD->hasCancel(); 1409 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1410 HasCancel, OutlinedHelperName); 1411 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1412 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 1413 } 1414 1415 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1416 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1417 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1418 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1419 return emitParallelOrTeamsOutlinedFunction( 1420 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1421 } 1422 1423 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1424 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1425 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1426 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1427 return emitParallelOrTeamsOutlinedFunction( 1428 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1429 } 1430 1431 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1432 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1433 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1434 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1435 bool Tied, unsigned &NumberOfParts) { 1436 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1437 PrePostActionTy &) { 1438 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1439 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1440 llvm::Value *TaskArgs[] = { 1441 UpLoc, ThreadID, 1442 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1443 TaskTVar->getType()->castAs<PointerType>()) 1444 .getPointer()}; 1445 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1446 }; 1447 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1448 UntiedCodeGen); 1449 CodeGen.setAction(Action); 1450 assert(!ThreadIDVar->getType()->isPointerType() && 1451 "thread id variable must be of type kmp_int32 for tasks"); 1452 const OpenMPDirectiveKind Region = 1453 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1454 : OMPD_task; 1455 const CapturedStmt *CS = D.getCapturedStmt(Region); 1456 const auto *TD = dyn_cast<OMPTaskDirective>(&D); 1457 CodeGenFunction CGF(CGM, true); 1458 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1459 InnermostKind, 1460 TD ? TD->hasCancel() : false, Action); 1461 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1462 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1463 if (!Tied) 1464 NumberOfParts = Action.getNumberOfParts(); 1465 return Res; 1466 } 1467 1468 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1469 const RecordDecl *RD, const CGRecordLayout &RL, 1470 ArrayRef<llvm::Constant *> Data) { 1471 llvm::StructType *StructTy = RL.getLLVMType(); 1472 unsigned PrevIdx = 0; 1473 ConstantInitBuilder CIBuilder(CGM); 1474 auto DI = Data.begin(); 1475 for (const FieldDecl *FD : RD->fields()) { 1476 unsigned Idx = RL.getLLVMFieldNo(FD); 1477 // Fill the alignment. 1478 for (unsigned I = PrevIdx; I < Idx; ++I) 1479 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1480 PrevIdx = Idx + 1; 1481 Fields.add(*DI); 1482 ++DI; 1483 } 1484 } 1485 1486 template <class... As> 1487 static llvm::GlobalVariable * 1488 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1489 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1490 As &&... Args) { 1491 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1492 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1493 ConstantInitBuilder CIBuilder(CGM); 1494 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1495 buildStructValue(Fields, CGM, RD, RL, Data); 1496 return Fields.finishAndCreateGlobal( 1497 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1498 std::forward<As>(Args)...); 1499 } 1500 1501 template <typename T> 1502 static void 1503 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1504 ArrayRef<llvm::Constant *> Data, 1505 T &Parent) { 1506 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1507 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1508 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1509 buildStructValue(Fields, CGM, RD, RL, Data); 1510 Fields.finishAndAddTo(Parent); 1511 } 1512 1513 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1514 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1515 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1516 FlagsTy FlagsKey(Flags, Reserved2Flags); 1517 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1518 if (!Entry) { 1519 if (!DefaultOpenMPPSource) { 1520 // Initialize default location for psource field of ident_t structure of 1521 // all ident_t objects. Format is ";file;function;line;column;;". 1522 // Taken from 1523 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1524 DefaultOpenMPPSource = 1525 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1526 DefaultOpenMPPSource = 1527 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1528 } 1529 1530 llvm::Constant *Data[] = { 1531 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1532 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1533 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1534 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1535 llvm::GlobalValue *DefaultOpenMPLocation = 1536 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1537 llvm::GlobalValue::PrivateLinkage); 1538 DefaultOpenMPLocation->setUnnamedAddr( 1539 llvm::GlobalValue::UnnamedAddr::Global); 1540 1541 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1542 } 1543 return Address(Entry, Align); 1544 } 1545 1546 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1547 bool AtCurrentPoint) { 1548 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1549 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1550 1551 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1552 if (AtCurrentPoint) { 1553 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1554 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1555 } else { 1556 Elem.second.ServiceInsertPt = 1557 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1558 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1559 } 1560 } 1561 1562 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1563 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1564 if (Elem.second.ServiceInsertPt) { 1565 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1566 Elem.second.ServiceInsertPt = nullptr; 1567 Ptr->eraseFromParent(); 1568 } 1569 } 1570 1571 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1572 SourceLocation Loc, 1573 unsigned Flags) { 1574 Flags |= OMP_IDENT_KMPC; 1575 // If no debug info is generated - return global default location. 1576 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1577 Loc.isInvalid()) 1578 return getOrCreateDefaultLocation(Flags).getPointer(); 1579 1580 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1581 1582 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1583 Address LocValue = Address::invalid(); 1584 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1585 if (I != OpenMPLocThreadIDMap.end()) 1586 LocValue = Address(I->second.DebugLoc, Align); 1587 1588 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1589 // GetOpenMPThreadID was called before this routine. 1590 if (!LocValue.isValid()) { 1591 // Generate "ident_t .kmpc_loc.addr;" 1592 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1593 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1594 Elem.second.DebugLoc = AI.getPointer(); 1595 LocValue = AI; 1596 1597 if (!Elem.second.ServiceInsertPt) 1598 setLocThreadIdInsertPt(CGF); 1599 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1600 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1601 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1602 CGF.getTypeSize(IdentQTy)); 1603 } 1604 1605 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1606 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1607 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1608 LValue PSource = 1609 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1610 1611 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1612 if (OMPDebugLoc == nullptr) { 1613 SmallString<128> Buffer2; 1614 llvm::raw_svector_ostream OS2(Buffer2); 1615 // Build debug location 1616 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1617 OS2 << ";" << PLoc.getFilename() << ";"; 1618 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1619 OS2 << FD->getQualifiedNameAsString(); 1620 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1621 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1622 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1623 } 1624 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1625 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1626 1627 // Our callers always pass this to a runtime function, so for 1628 // convenience, go ahead and return a naked pointer. 1629 return LocValue.getPointer(); 1630 } 1631 1632 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1633 SourceLocation Loc) { 1634 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1635 1636 llvm::Value *ThreadID = nullptr; 1637 // Check whether we've already cached a load of the thread id in this 1638 // function. 1639 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1640 if (I != OpenMPLocThreadIDMap.end()) { 1641 ThreadID = I->second.ThreadID; 1642 if (ThreadID != nullptr) 1643 return ThreadID; 1644 } 1645 // If exceptions are enabled, do not use parameter to avoid possible crash. 1646 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1647 !CGF.getLangOpts().CXXExceptions || 1648 CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 1649 if (auto *OMPRegionInfo = 1650 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1651 if (OMPRegionInfo->getThreadIDVariable()) { 1652 // Check if this an outlined function with thread id passed as argument. 1653 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1654 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1655 // If value loaded in entry block, cache it and use it everywhere in 1656 // function. 1657 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 1658 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1659 Elem.second.ThreadID = ThreadID; 1660 } 1661 return ThreadID; 1662 } 1663 } 1664 } 1665 1666 // This is not an outlined function region - need to call __kmpc_int32 1667 // kmpc_global_thread_num(ident_t *loc). 1668 // Generate thread id value and cache this value for use across the 1669 // function. 1670 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1671 if (!Elem.second.ServiceInsertPt) 1672 setLocThreadIdInsertPt(CGF); 1673 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1674 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1675 llvm::CallInst *Call = CGF.Builder.CreateCall( 1676 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1677 emitUpdateLocation(CGF, Loc)); 1678 Call->setCallingConv(CGF.getRuntimeCC()); 1679 Elem.second.ThreadID = Call; 1680 return Call; 1681 } 1682 1683 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1684 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1685 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1686 clearLocThreadIdInsertPt(CGF); 1687 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1688 } 1689 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1690 for(auto *D : FunctionUDRMap[CGF.CurFn]) 1691 UDRMap.erase(D); 1692 FunctionUDRMap.erase(CGF.CurFn); 1693 } 1694 auto I = FunctionUDMMap.find(CGF.CurFn); 1695 if (I != FunctionUDMMap.end()) { 1696 for(auto *D : I->second) 1697 UDMMap.erase(D); 1698 FunctionUDMMap.erase(I); 1699 } 1700 } 1701 1702 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1703 return IdentTy->getPointerTo(); 1704 } 1705 1706 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1707 if (!Kmpc_MicroTy) { 1708 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1709 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1710 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1711 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1712 } 1713 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1714 } 1715 1716 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1717 llvm::FunctionCallee RTLFn = nullptr; 1718 switch (static_cast<OpenMPRTLFunction>(Function)) { 1719 case OMPRTL__kmpc_fork_call: { 1720 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1721 // microtask, ...); 1722 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1723 getKmpc_MicroPointerTy()}; 1724 auto *FnTy = 1725 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1726 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1727 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1728 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1729 llvm::LLVMContext &Ctx = F->getContext(); 1730 llvm::MDBuilder MDB(Ctx); 1731 // Annotate the callback behavior of the __kmpc_fork_call: 1732 // - The callback callee is argument number 2 (microtask). 1733 // - The first two arguments of the callback callee are unknown (-1). 1734 // - All variadic arguments to the __kmpc_fork_call are passed to the 1735 // callback callee. 1736 F->addMetadata( 1737 llvm::LLVMContext::MD_callback, 1738 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1739 2, {-1, -1}, 1740 /* VarArgsArePassed */ true)})); 1741 } 1742 } 1743 break; 1744 } 1745 case OMPRTL__kmpc_global_thread_num: { 1746 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1747 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1748 auto *FnTy = 1749 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1750 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1751 break; 1752 } 1753 case OMPRTL__kmpc_threadprivate_cached: { 1754 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1755 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1756 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1757 CGM.VoidPtrTy, CGM.SizeTy, 1758 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1759 auto *FnTy = 1760 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1761 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1762 break; 1763 } 1764 case OMPRTL__kmpc_critical: { 1765 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1766 // kmp_critical_name *crit); 1767 llvm::Type *TypeParams[] = { 1768 getIdentTyPointerTy(), CGM.Int32Ty, 1769 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1770 auto *FnTy = 1771 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1772 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1773 break; 1774 } 1775 case OMPRTL__kmpc_critical_with_hint: { 1776 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1777 // kmp_critical_name *crit, uintptr_t hint); 1778 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1779 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1780 CGM.IntPtrTy}; 1781 auto *FnTy = 1782 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1783 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1784 break; 1785 } 1786 case OMPRTL__kmpc_threadprivate_register: { 1787 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1788 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1789 // typedef void *(*kmpc_ctor)(void *); 1790 auto *KmpcCtorTy = 1791 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1792 /*isVarArg*/ false)->getPointerTo(); 1793 // typedef void *(*kmpc_cctor)(void *, void *); 1794 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1795 auto *KmpcCopyCtorTy = 1796 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1797 /*isVarArg*/ false) 1798 ->getPointerTo(); 1799 // typedef void (*kmpc_dtor)(void *); 1800 auto *KmpcDtorTy = 1801 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1802 ->getPointerTo(); 1803 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1804 KmpcCopyCtorTy, KmpcDtorTy}; 1805 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1806 /*isVarArg*/ false); 1807 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1808 break; 1809 } 1810 case OMPRTL__kmpc_end_critical: { 1811 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1812 // kmp_critical_name *crit); 1813 llvm::Type *TypeParams[] = { 1814 getIdentTyPointerTy(), CGM.Int32Ty, 1815 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1816 auto *FnTy = 1817 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1818 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1819 break; 1820 } 1821 case OMPRTL__kmpc_cancel_barrier: { 1822 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1823 // global_tid); 1824 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1825 auto *FnTy = 1826 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1827 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1828 break; 1829 } 1830 case OMPRTL__kmpc_barrier: { 1831 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1832 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1833 auto *FnTy = 1834 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1835 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1836 break; 1837 } 1838 case OMPRTL__kmpc_for_static_fini: { 1839 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1840 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1841 auto *FnTy = 1842 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1843 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1844 break; 1845 } 1846 case OMPRTL__kmpc_push_num_threads: { 1847 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1848 // kmp_int32 num_threads) 1849 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1850 CGM.Int32Ty}; 1851 auto *FnTy = 1852 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1853 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1854 break; 1855 } 1856 case OMPRTL__kmpc_serialized_parallel: { 1857 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1858 // global_tid); 1859 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1860 auto *FnTy = 1861 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1862 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1863 break; 1864 } 1865 case OMPRTL__kmpc_end_serialized_parallel: { 1866 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1867 // global_tid); 1868 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1869 auto *FnTy = 1870 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1871 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1872 break; 1873 } 1874 case OMPRTL__kmpc_flush: { 1875 // Build void __kmpc_flush(ident_t *loc); 1876 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1877 auto *FnTy = 1878 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1879 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1880 break; 1881 } 1882 case OMPRTL__kmpc_master: { 1883 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1884 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1885 auto *FnTy = 1886 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1887 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 1888 break; 1889 } 1890 case OMPRTL__kmpc_end_master: { 1891 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 1892 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1893 auto *FnTy = 1894 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1895 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 1896 break; 1897 } 1898 case OMPRTL__kmpc_omp_taskyield: { 1899 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 1900 // int end_part); 1901 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1902 auto *FnTy = 1903 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1904 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 1905 break; 1906 } 1907 case OMPRTL__kmpc_single: { 1908 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 1909 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1910 auto *FnTy = 1911 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1912 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 1913 break; 1914 } 1915 case OMPRTL__kmpc_end_single: { 1916 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 1917 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1918 auto *FnTy = 1919 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1920 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 1921 break; 1922 } 1923 case OMPRTL__kmpc_omp_task_alloc: { 1924 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 1925 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1926 // kmp_routine_entry_t *task_entry); 1927 assert(KmpRoutineEntryPtrTy != nullptr && 1928 "Type kmp_routine_entry_t must be created."); 1929 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1930 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 1931 // Return void * and then cast to particular kmp_task_t type. 1932 auto *FnTy = 1933 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1934 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 1935 break; 1936 } 1937 case OMPRTL__kmpc_omp_target_task_alloc: { 1938 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 1939 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1940 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 1941 assert(KmpRoutineEntryPtrTy != nullptr && 1942 "Type kmp_routine_entry_t must be created."); 1943 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1944 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 1945 CGM.Int64Ty}; 1946 // Return void * and then cast to particular kmp_task_t type. 1947 auto *FnTy = 1948 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1949 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 1950 break; 1951 } 1952 case OMPRTL__kmpc_omp_task: { 1953 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 1954 // *new_task); 1955 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1956 CGM.VoidPtrTy}; 1957 auto *FnTy = 1958 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1959 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 1960 break; 1961 } 1962 case OMPRTL__kmpc_copyprivate: { 1963 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 1964 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 1965 // kmp_int32 didit); 1966 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1967 auto *CpyFnTy = 1968 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 1969 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 1970 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 1971 CGM.Int32Ty}; 1972 auto *FnTy = 1973 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1974 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 1975 break; 1976 } 1977 case OMPRTL__kmpc_reduce: { 1978 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 1979 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 1980 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 1981 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1982 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 1983 /*isVarArg=*/false); 1984 llvm::Type *TypeParams[] = { 1985 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 1986 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 1987 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1988 auto *FnTy = 1989 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1990 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 1991 break; 1992 } 1993 case OMPRTL__kmpc_reduce_nowait: { 1994 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 1995 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 1996 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 1997 // *lck); 1998 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1999 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2000 /*isVarArg=*/false); 2001 llvm::Type *TypeParams[] = { 2002 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2003 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2004 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2005 auto *FnTy = 2006 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2007 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2008 break; 2009 } 2010 case OMPRTL__kmpc_end_reduce: { 2011 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2012 // kmp_critical_name *lck); 2013 llvm::Type *TypeParams[] = { 2014 getIdentTyPointerTy(), CGM.Int32Ty, 2015 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2016 auto *FnTy = 2017 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2018 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2019 break; 2020 } 2021 case OMPRTL__kmpc_end_reduce_nowait: { 2022 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2023 // kmp_critical_name *lck); 2024 llvm::Type *TypeParams[] = { 2025 getIdentTyPointerTy(), CGM.Int32Ty, 2026 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2027 auto *FnTy = 2028 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2029 RTLFn = 2030 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2031 break; 2032 } 2033 case OMPRTL__kmpc_omp_task_begin_if0: { 2034 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2035 // *new_task); 2036 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2037 CGM.VoidPtrTy}; 2038 auto *FnTy = 2039 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2040 RTLFn = 2041 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2042 break; 2043 } 2044 case OMPRTL__kmpc_omp_task_complete_if0: { 2045 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2046 // *new_task); 2047 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2048 CGM.VoidPtrTy}; 2049 auto *FnTy = 2050 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2051 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2052 /*Name=*/"__kmpc_omp_task_complete_if0"); 2053 break; 2054 } 2055 case OMPRTL__kmpc_ordered: { 2056 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2057 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2058 auto *FnTy = 2059 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2060 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2061 break; 2062 } 2063 case OMPRTL__kmpc_end_ordered: { 2064 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2065 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2066 auto *FnTy = 2067 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2068 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2069 break; 2070 } 2071 case OMPRTL__kmpc_omp_taskwait: { 2072 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2073 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2074 auto *FnTy = 2075 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2076 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2077 break; 2078 } 2079 case OMPRTL__kmpc_taskgroup: { 2080 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2081 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2082 auto *FnTy = 2083 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2084 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2085 break; 2086 } 2087 case OMPRTL__kmpc_end_taskgroup: { 2088 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2089 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2090 auto *FnTy = 2091 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2092 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2093 break; 2094 } 2095 case OMPRTL__kmpc_push_proc_bind: { 2096 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2097 // int proc_bind) 2098 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2099 auto *FnTy = 2100 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2101 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2102 break; 2103 } 2104 case OMPRTL__kmpc_omp_task_with_deps: { 2105 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2106 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2107 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2108 llvm::Type *TypeParams[] = { 2109 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2110 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2111 auto *FnTy = 2112 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2113 RTLFn = 2114 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2115 break; 2116 } 2117 case OMPRTL__kmpc_omp_wait_deps: { 2118 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2119 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2120 // kmp_depend_info_t *noalias_dep_list); 2121 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2122 CGM.Int32Ty, CGM.VoidPtrTy, 2123 CGM.Int32Ty, CGM.VoidPtrTy}; 2124 auto *FnTy = 2125 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2126 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2127 break; 2128 } 2129 case OMPRTL__kmpc_cancellationpoint: { 2130 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2131 // global_tid, kmp_int32 cncl_kind) 2132 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2133 auto *FnTy = 2134 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2135 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2136 break; 2137 } 2138 case OMPRTL__kmpc_cancel: { 2139 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2140 // kmp_int32 cncl_kind) 2141 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2142 auto *FnTy = 2143 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2144 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2145 break; 2146 } 2147 case OMPRTL__kmpc_push_num_teams: { 2148 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2149 // kmp_int32 num_teams, kmp_int32 num_threads) 2150 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2151 CGM.Int32Ty}; 2152 auto *FnTy = 2153 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2154 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2155 break; 2156 } 2157 case OMPRTL__kmpc_fork_teams: { 2158 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2159 // microtask, ...); 2160 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2161 getKmpc_MicroPointerTy()}; 2162 auto *FnTy = 2163 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2164 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2165 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2166 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2167 llvm::LLVMContext &Ctx = F->getContext(); 2168 llvm::MDBuilder MDB(Ctx); 2169 // Annotate the callback behavior of the __kmpc_fork_teams: 2170 // - The callback callee is argument number 2 (microtask). 2171 // - The first two arguments of the callback callee are unknown (-1). 2172 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2173 // callback callee. 2174 F->addMetadata( 2175 llvm::LLVMContext::MD_callback, 2176 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2177 2, {-1, -1}, 2178 /* VarArgsArePassed */ true)})); 2179 } 2180 } 2181 break; 2182 } 2183 case OMPRTL__kmpc_taskloop: { 2184 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2185 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2186 // sched, kmp_uint64 grainsize, void *task_dup); 2187 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2188 CGM.IntTy, 2189 CGM.VoidPtrTy, 2190 CGM.IntTy, 2191 CGM.Int64Ty->getPointerTo(), 2192 CGM.Int64Ty->getPointerTo(), 2193 CGM.Int64Ty, 2194 CGM.IntTy, 2195 CGM.IntTy, 2196 CGM.Int64Ty, 2197 CGM.VoidPtrTy}; 2198 auto *FnTy = 2199 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2200 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2201 break; 2202 } 2203 case OMPRTL__kmpc_doacross_init: { 2204 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2205 // num_dims, struct kmp_dim *dims); 2206 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2207 CGM.Int32Ty, 2208 CGM.Int32Ty, 2209 CGM.VoidPtrTy}; 2210 auto *FnTy = 2211 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2212 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2213 break; 2214 } 2215 case OMPRTL__kmpc_doacross_fini: { 2216 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2217 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2218 auto *FnTy = 2219 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2220 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2221 break; 2222 } 2223 case OMPRTL__kmpc_doacross_post: { 2224 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2225 // *vec); 2226 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2227 CGM.Int64Ty->getPointerTo()}; 2228 auto *FnTy = 2229 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2230 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2231 break; 2232 } 2233 case OMPRTL__kmpc_doacross_wait: { 2234 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2235 // *vec); 2236 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2237 CGM.Int64Ty->getPointerTo()}; 2238 auto *FnTy = 2239 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2240 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2241 break; 2242 } 2243 case OMPRTL__kmpc_task_reduction_init: { 2244 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2245 // *data); 2246 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2247 auto *FnTy = 2248 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2249 RTLFn = 2250 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2251 break; 2252 } 2253 case OMPRTL__kmpc_task_reduction_get_th_data: { 2254 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2255 // *d); 2256 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2257 auto *FnTy = 2258 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2259 RTLFn = CGM.CreateRuntimeFunction( 2260 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2261 break; 2262 } 2263 case OMPRTL__kmpc_alloc: { 2264 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2265 // al); omp_allocator_handle_t type is void *. 2266 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2267 auto *FnTy = 2268 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2269 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2270 break; 2271 } 2272 case OMPRTL__kmpc_free: { 2273 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2274 // al); omp_allocator_handle_t type is void *. 2275 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2276 auto *FnTy = 2277 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2278 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2279 break; 2280 } 2281 case OMPRTL__kmpc_push_target_tripcount: { 2282 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2283 // size); 2284 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2285 llvm::FunctionType *FnTy = 2286 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2287 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2288 break; 2289 } 2290 case OMPRTL__tgt_target: { 2291 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2292 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2293 // *arg_types); 2294 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2295 CGM.VoidPtrTy, 2296 CGM.Int32Ty, 2297 CGM.VoidPtrPtrTy, 2298 CGM.VoidPtrPtrTy, 2299 CGM.Int64Ty->getPointerTo(), 2300 CGM.Int64Ty->getPointerTo()}; 2301 auto *FnTy = 2302 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2303 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2304 break; 2305 } 2306 case OMPRTL__tgt_target_nowait: { 2307 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2308 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2309 // int64_t *arg_types); 2310 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2311 CGM.VoidPtrTy, 2312 CGM.Int32Ty, 2313 CGM.VoidPtrPtrTy, 2314 CGM.VoidPtrPtrTy, 2315 CGM.Int64Ty->getPointerTo(), 2316 CGM.Int64Ty->getPointerTo()}; 2317 auto *FnTy = 2318 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2319 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2320 break; 2321 } 2322 case OMPRTL__tgt_target_teams: { 2323 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2324 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2325 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2326 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2327 CGM.VoidPtrTy, 2328 CGM.Int32Ty, 2329 CGM.VoidPtrPtrTy, 2330 CGM.VoidPtrPtrTy, 2331 CGM.Int64Ty->getPointerTo(), 2332 CGM.Int64Ty->getPointerTo(), 2333 CGM.Int32Ty, 2334 CGM.Int32Ty}; 2335 auto *FnTy = 2336 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2337 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2338 break; 2339 } 2340 case OMPRTL__tgt_target_teams_nowait: { 2341 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2342 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2343 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2344 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2345 CGM.VoidPtrTy, 2346 CGM.Int32Ty, 2347 CGM.VoidPtrPtrTy, 2348 CGM.VoidPtrPtrTy, 2349 CGM.Int64Ty->getPointerTo(), 2350 CGM.Int64Ty->getPointerTo(), 2351 CGM.Int32Ty, 2352 CGM.Int32Ty}; 2353 auto *FnTy = 2354 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2355 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2356 break; 2357 } 2358 case OMPRTL__tgt_register_requires: { 2359 // Build void __tgt_register_requires(int64_t flags); 2360 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2361 auto *FnTy = 2362 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2363 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2364 break; 2365 } 2366 case OMPRTL__tgt_register_lib: { 2367 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 2368 QualType ParamTy = 2369 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2370 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2371 auto *FnTy = 2372 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2373 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 2374 break; 2375 } 2376 case OMPRTL__tgt_unregister_lib: { 2377 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 2378 QualType ParamTy = 2379 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2380 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2381 auto *FnTy = 2382 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2383 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 2384 break; 2385 } 2386 case OMPRTL__tgt_target_data_begin: { 2387 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2388 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2389 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2390 CGM.Int32Ty, 2391 CGM.VoidPtrPtrTy, 2392 CGM.VoidPtrPtrTy, 2393 CGM.Int64Ty->getPointerTo(), 2394 CGM.Int64Ty->getPointerTo()}; 2395 auto *FnTy = 2396 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2397 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2398 break; 2399 } 2400 case OMPRTL__tgt_target_data_begin_nowait: { 2401 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2402 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2403 // *arg_types); 2404 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2405 CGM.Int32Ty, 2406 CGM.VoidPtrPtrTy, 2407 CGM.VoidPtrPtrTy, 2408 CGM.Int64Ty->getPointerTo(), 2409 CGM.Int64Ty->getPointerTo()}; 2410 auto *FnTy = 2411 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2412 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2413 break; 2414 } 2415 case OMPRTL__tgt_target_data_end: { 2416 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2417 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2418 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2419 CGM.Int32Ty, 2420 CGM.VoidPtrPtrTy, 2421 CGM.VoidPtrPtrTy, 2422 CGM.Int64Ty->getPointerTo(), 2423 CGM.Int64Ty->getPointerTo()}; 2424 auto *FnTy = 2425 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2426 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2427 break; 2428 } 2429 case OMPRTL__tgt_target_data_end_nowait: { 2430 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2431 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2432 // *arg_types); 2433 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2434 CGM.Int32Ty, 2435 CGM.VoidPtrPtrTy, 2436 CGM.VoidPtrPtrTy, 2437 CGM.Int64Ty->getPointerTo(), 2438 CGM.Int64Ty->getPointerTo()}; 2439 auto *FnTy = 2440 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2441 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2442 break; 2443 } 2444 case OMPRTL__tgt_target_data_update: { 2445 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2446 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2447 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2448 CGM.Int32Ty, 2449 CGM.VoidPtrPtrTy, 2450 CGM.VoidPtrPtrTy, 2451 CGM.Int64Ty->getPointerTo(), 2452 CGM.Int64Ty->getPointerTo()}; 2453 auto *FnTy = 2454 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2455 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2456 break; 2457 } 2458 case OMPRTL__tgt_target_data_update_nowait: { 2459 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2460 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2461 // *arg_types); 2462 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2463 CGM.Int32Ty, 2464 CGM.VoidPtrPtrTy, 2465 CGM.VoidPtrPtrTy, 2466 CGM.Int64Ty->getPointerTo(), 2467 CGM.Int64Ty->getPointerTo()}; 2468 auto *FnTy = 2469 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2470 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2471 break; 2472 } 2473 case OMPRTL__tgt_mapper_num_components: { 2474 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2475 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2476 auto *FnTy = 2477 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2478 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2479 break; 2480 } 2481 case OMPRTL__tgt_push_mapper_component: { 2482 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2483 // *base, void *begin, int64_t size, int64_t type); 2484 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2485 CGM.Int64Ty, CGM.Int64Ty}; 2486 auto *FnTy = 2487 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2488 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2489 break; 2490 } 2491 } 2492 assert(RTLFn && "Unable to find OpenMP runtime function"); 2493 return RTLFn; 2494 } 2495 2496 llvm::FunctionCallee 2497 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2498 assert((IVSize == 32 || IVSize == 64) && 2499 "IV size is not compatible with the omp runtime"); 2500 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2501 : "__kmpc_for_static_init_4u") 2502 : (IVSigned ? "__kmpc_for_static_init_8" 2503 : "__kmpc_for_static_init_8u"); 2504 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2505 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2506 llvm::Type *TypeParams[] = { 2507 getIdentTyPointerTy(), // loc 2508 CGM.Int32Ty, // tid 2509 CGM.Int32Ty, // schedtype 2510 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2511 PtrTy, // p_lower 2512 PtrTy, // p_upper 2513 PtrTy, // p_stride 2514 ITy, // incr 2515 ITy // chunk 2516 }; 2517 auto *FnTy = 2518 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2519 return CGM.CreateRuntimeFunction(FnTy, Name); 2520 } 2521 2522 llvm::FunctionCallee 2523 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2524 assert((IVSize == 32 || IVSize == 64) && 2525 "IV size is not compatible with the omp runtime"); 2526 StringRef Name = 2527 IVSize == 32 2528 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2529 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2530 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2531 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2532 CGM.Int32Ty, // tid 2533 CGM.Int32Ty, // schedtype 2534 ITy, // lower 2535 ITy, // upper 2536 ITy, // stride 2537 ITy // chunk 2538 }; 2539 auto *FnTy = 2540 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2541 return CGM.CreateRuntimeFunction(FnTy, Name); 2542 } 2543 2544 llvm::FunctionCallee 2545 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2546 assert((IVSize == 32 || IVSize == 64) && 2547 "IV size is not compatible with the omp runtime"); 2548 StringRef Name = 2549 IVSize == 32 2550 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2551 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2552 llvm::Type *TypeParams[] = { 2553 getIdentTyPointerTy(), // loc 2554 CGM.Int32Ty, // tid 2555 }; 2556 auto *FnTy = 2557 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2558 return CGM.CreateRuntimeFunction(FnTy, Name); 2559 } 2560 2561 llvm::FunctionCallee 2562 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2563 assert((IVSize == 32 || IVSize == 64) && 2564 "IV size is not compatible with the omp runtime"); 2565 StringRef Name = 2566 IVSize == 32 2567 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2568 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2569 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2570 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2571 llvm::Type *TypeParams[] = { 2572 getIdentTyPointerTy(), // loc 2573 CGM.Int32Ty, // tid 2574 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2575 PtrTy, // p_lower 2576 PtrTy, // p_upper 2577 PtrTy // p_stride 2578 }; 2579 auto *FnTy = 2580 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2581 return CGM.CreateRuntimeFunction(FnTy, Name); 2582 } 2583 2584 /// Obtain information that uniquely identifies a target entry. This 2585 /// consists of the file and device IDs as well as line number associated with 2586 /// the relevant entry source location. 2587 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2588 unsigned &DeviceID, unsigned &FileID, 2589 unsigned &LineNum) { 2590 SourceManager &SM = C.getSourceManager(); 2591 2592 // The loc should be always valid and have a file ID (the user cannot use 2593 // #pragma directives in macros) 2594 2595 assert(Loc.isValid() && "Source location is expected to be always valid."); 2596 2597 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2598 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2599 2600 llvm::sys::fs::UniqueID ID; 2601 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2602 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2603 << PLoc.getFilename() << EC.message(); 2604 2605 DeviceID = ID.getDevice(); 2606 FileID = ID.getFile(); 2607 LineNum = PLoc.getLine(); 2608 } 2609 2610 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2611 if (CGM.getLangOpts().OpenMPSimd) 2612 return Address::invalid(); 2613 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2614 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2615 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2616 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2617 HasRequiresUnifiedSharedMemory))) { 2618 SmallString<64> PtrName; 2619 { 2620 llvm::raw_svector_ostream OS(PtrName); 2621 OS << CGM.getMangledName(GlobalDecl(VD)); 2622 if (!VD->isExternallyVisible()) { 2623 unsigned DeviceID, FileID, Line; 2624 getTargetEntryUniqueInfo(CGM.getContext(), 2625 VD->getCanonicalDecl()->getBeginLoc(), 2626 DeviceID, FileID, Line); 2627 OS << llvm::format("_%x", FileID); 2628 } 2629 OS << "_decl_tgt_ref_ptr"; 2630 } 2631 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2632 if (!Ptr) { 2633 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2634 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2635 PtrName); 2636 2637 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2638 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2639 2640 if (!CGM.getLangOpts().OpenMPIsDevice) 2641 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2642 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2643 } 2644 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2645 } 2646 return Address::invalid(); 2647 } 2648 2649 llvm::Constant * 2650 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2651 assert(!CGM.getLangOpts().OpenMPUseTLS || 2652 !CGM.getContext().getTargetInfo().isTLSSupported()); 2653 // Lookup the entry, lazily creating it if necessary. 2654 std::string Suffix = getName({"cache", ""}); 2655 return getOrCreateInternalVariable( 2656 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2657 } 2658 2659 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2660 const VarDecl *VD, 2661 Address VDAddr, 2662 SourceLocation Loc) { 2663 if (CGM.getLangOpts().OpenMPUseTLS && 2664 CGM.getContext().getTargetInfo().isTLSSupported()) 2665 return VDAddr; 2666 2667 llvm::Type *VarTy = VDAddr.getElementType(); 2668 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2669 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2670 CGM.Int8PtrTy), 2671 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2672 getOrCreateThreadPrivateCache(VD)}; 2673 return Address(CGF.EmitRuntimeCall( 2674 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2675 VDAddr.getAlignment()); 2676 } 2677 2678 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2679 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2680 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2681 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2682 // library. 2683 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2684 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2685 OMPLoc); 2686 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2687 // to register constructor/destructor for variable. 2688 llvm::Value *Args[] = { 2689 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2690 Ctor, CopyCtor, Dtor}; 2691 CGF.EmitRuntimeCall( 2692 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2693 } 2694 2695 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2696 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2697 bool PerformInit, CodeGenFunction *CGF) { 2698 if (CGM.getLangOpts().OpenMPUseTLS && 2699 CGM.getContext().getTargetInfo().isTLSSupported()) 2700 return nullptr; 2701 2702 VD = VD->getDefinition(CGM.getContext()); 2703 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2704 QualType ASTTy = VD->getType(); 2705 2706 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2707 const Expr *Init = VD->getAnyInitializer(); 2708 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2709 // Generate function that re-emits the declaration's initializer into the 2710 // threadprivate copy of the variable VD 2711 CodeGenFunction CtorCGF(CGM); 2712 FunctionArgList Args; 2713 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2714 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2715 ImplicitParamDecl::Other); 2716 Args.push_back(&Dst); 2717 2718 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2719 CGM.getContext().VoidPtrTy, Args); 2720 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2721 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2722 llvm::Function *Fn = 2723 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2724 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2725 Args, Loc, Loc); 2726 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2727 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2728 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2729 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2730 Arg = CtorCGF.Builder.CreateElementBitCast( 2731 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2732 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2733 /*IsInitializer=*/true); 2734 ArgVal = CtorCGF.EmitLoadOfScalar( 2735 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2736 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2737 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2738 CtorCGF.FinishFunction(); 2739 Ctor = Fn; 2740 } 2741 if (VD->getType().isDestructedType() != QualType::DK_none) { 2742 // Generate function that emits destructor call for the threadprivate copy 2743 // of the variable VD 2744 CodeGenFunction DtorCGF(CGM); 2745 FunctionArgList Args; 2746 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2747 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2748 ImplicitParamDecl::Other); 2749 Args.push_back(&Dst); 2750 2751 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2752 CGM.getContext().VoidTy, Args); 2753 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2754 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2755 llvm::Function *Fn = 2756 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2757 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2758 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2759 Loc, Loc); 2760 // Create a scope with an artificial location for the body of this function. 2761 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2762 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2763 DtorCGF.GetAddrOfLocalVar(&Dst), 2764 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2765 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2766 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2767 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2768 DtorCGF.FinishFunction(); 2769 Dtor = Fn; 2770 } 2771 // Do not emit init function if it is not required. 2772 if (!Ctor && !Dtor) 2773 return nullptr; 2774 2775 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2776 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2777 /*isVarArg=*/false) 2778 ->getPointerTo(); 2779 // Copying constructor for the threadprivate variable. 2780 // Must be NULL - reserved by runtime, but currently it requires that this 2781 // parameter is always NULL. Otherwise it fires assertion. 2782 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2783 if (Ctor == nullptr) { 2784 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2785 /*isVarArg=*/false) 2786 ->getPointerTo(); 2787 Ctor = llvm::Constant::getNullValue(CtorTy); 2788 } 2789 if (Dtor == nullptr) { 2790 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2791 /*isVarArg=*/false) 2792 ->getPointerTo(); 2793 Dtor = llvm::Constant::getNullValue(DtorTy); 2794 } 2795 if (!CGF) { 2796 auto *InitFunctionTy = 2797 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2798 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2799 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2800 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2801 CodeGenFunction InitCGF(CGM); 2802 FunctionArgList ArgList; 2803 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2804 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2805 Loc, Loc); 2806 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2807 InitCGF.FinishFunction(); 2808 return InitFunction; 2809 } 2810 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2811 } 2812 return nullptr; 2813 } 2814 2815 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2816 llvm::GlobalVariable *Addr, 2817 bool PerformInit) { 2818 if (CGM.getLangOpts().OMPTargetTriples.empty()) 2819 return false; 2820 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2821 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2822 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2823 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2824 HasRequiresUnifiedSharedMemory)) 2825 return CGM.getLangOpts().OpenMPIsDevice; 2826 VD = VD->getDefinition(CGM.getContext()); 2827 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2828 return CGM.getLangOpts().OpenMPIsDevice; 2829 2830 QualType ASTTy = VD->getType(); 2831 2832 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2833 // Produce the unique prefix to identify the new target regions. We use 2834 // the source location of the variable declaration which we know to not 2835 // conflict with any target region. 2836 unsigned DeviceID; 2837 unsigned FileID; 2838 unsigned Line; 2839 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2840 SmallString<128> Buffer, Out; 2841 { 2842 llvm::raw_svector_ostream OS(Buffer); 2843 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2844 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2845 } 2846 2847 const Expr *Init = VD->getAnyInitializer(); 2848 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2849 llvm::Constant *Ctor; 2850 llvm::Constant *ID; 2851 if (CGM.getLangOpts().OpenMPIsDevice) { 2852 // Generate function that re-emits the declaration's initializer into 2853 // the threadprivate copy of the variable VD 2854 CodeGenFunction CtorCGF(CGM); 2855 2856 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2857 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2858 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2859 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2860 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2861 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2862 FunctionArgList(), Loc, Loc); 2863 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2864 CtorCGF.EmitAnyExprToMem(Init, 2865 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2866 Init->getType().getQualifiers(), 2867 /*IsInitializer=*/true); 2868 CtorCGF.FinishFunction(); 2869 Ctor = Fn; 2870 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2871 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2872 } else { 2873 Ctor = new llvm::GlobalVariable( 2874 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2875 llvm::GlobalValue::PrivateLinkage, 2876 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2877 ID = Ctor; 2878 } 2879 2880 // Register the information for the entry associated with the constructor. 2881 Out.clear(); 2882 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2883 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2884 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2885 } 2886 if (VD->getType().isDestructedType() != QualType::DK_none) { 2887 llvm::Constant *Dtor; 2888 llvm::Constant *ID; 2889 if (CGM.getLangOpts().OpenMPIsDevice) { 2890 // Generate function that emits destructor call for the threadprivate 2891 // copy of the variable VD 2892 CodeGenFunction DtorCGF(CGM); 2893 2894 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2895 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2896 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2897 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2898 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2899 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2900 FunctionArgList(), Loc, Loc); 2901 // Create a scope with an artificial location for the body of this 2902 // function. 2903 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2904 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 2905 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2906 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2907 DtorCGF.FinishFunction(); 2908 Dtor = Fn; 2909 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2910 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 2911 } else { 2912 Dtor = new llvm::GlobalVariable( 2913 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2914 llvm::GlobalValue::PrivateLinkage, 2915 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 2916 ID = Dtor; 2917 } 2918 // Register the information for the entry associated with the destructor. 2919 Out.clear(); 2920 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2921 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2922 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2923 } 2924 return CGM.getLangOpts().OpenMPIsDevice; 2925 } 2926 2927 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2928 QualType VarType, 2929 StringRef Name) { 2930 std::string Suffix = getName({"artificial", ""}); 2931 std::string CacheSuffix = getName({"cache", ""}); 2932 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2933 llvm::Value *GAddr = 2934 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2935 llvm::Value *Args[] = { 2936 emitUpdateLocation(CGF, SourceLocation()), 2937 getThreadID(CGF, SourceLocation()), 2938 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2939 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2940 /*isSigned=*/false), 2941 getOrCreateInternalVariable( 2942 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2943 return Address( 2944 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 2945 CGF.EmitRuntimeCall( 2946 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2947 VarLVType->getPointerTo(/*AddrSpace=*/0)), 2948 CGM.getPointerAlign()); 2949 } 2950 2951 void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, 2952 const RegionCodeGenTy &ThenGen, 2953 const RegionCodeGenTy &ElseGen) { 2954 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 2955 2956 // If the condition constant folds and can be elided, try to avoid emitting 2957 // the condition and the dead arm of the if/else. 2958 bool CondConstant; 2959 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 2960 if (CondConstant) 2961 ThenGen(CGF); 2962 else 2963 ElseGen(CGF); 2964 return; 2965 } 2966 2967 // Otherwise, the condition did not fold, or we couldn't elide it. Just 2968 // emit the conditional branch. 2969 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 2970 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 2971 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 2972 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 2973 2974 // Emit the 'then' code. 2975 CGF.EmitBlock(ThenBlock); 2976 ThenGen(CGF); 2977 CGF.EmitBranch(ContBlock); 2978 // Emit the 'else' code if present. 2979 // There is no need to emit line number for unconditional branch. 2980 (void)ApplyDebugLocation::CreateEmpty(CGF); 2981 CGF.EmitBlock(ElseBlock); 2982 ElseGen(CGF); 2983 // There is no need to emit line number for unconditional branch. 2984 (void)ApplyDebugLocation::CreateEmpty(CGF); 2985 CGF.EmitBranch(ContBlock); 2986 // Emit the continuation block for code after the if. 2987 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 2988 } 2989 2990 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 2991 llvm::Function *OutlinedFn, 2992 ArrayRef<llvm::Value *> CapturedVars, 2993 const Expr *IfCond) { 2994 if (!CGF.HaveInsertPoint()) 2995 return; 2996 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 2997 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 2998 PrePostActionTy &) { 2999 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3000 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3001 llvm::Value *Args[] = { 3002 RTLoc, 3003 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3004 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3005 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3006 RealArgs.append(std::begin(Args), std::end(Args)); 3007 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3008 3009 llvm::FunctionCallee RTLFn = 3010 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3011 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3012 }; 3013 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3014 PrePostActionTy &) { 3015 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3016 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3017 // Build calls: 3018 // __kmpc_serialized_parallel(&Loc, GTid); 3019 llvm::Value *Args[] = {RTLoc, ThreadID}; 3020 CGF.EmitRuntimeCall( 3021 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3022 3023 // OutlinedFn(>id, &zero, CapturedStruct); 3024 Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3025 /*Name*/ ".zero.addr"); 3026 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); 3027 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3028 // ThreadId for serialized parallels is 0. 3029 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 3030 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 3031 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3032 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3033 3034 // __kmpc_end_serialized_parallel(&Loc, GTid); 3035 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3036 CGF.EmitRuntimeCall( 3037 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3038 EndArgs); 3039 }; 3040 if (IfCond) { 3041 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 3042 } else { 3043 RegionCodeGenTy ThenRCG(ThenGen); 3044 ThenRCG(CGF); 3045 } 3046 } 3047 3048 // If we're inside an (outlined) parallel region, use the region info's 3049 // thread-ID variable (it is passed in a first argument of the outlined function 3050 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3051 // regular serial code region, get thread ID by calling kmp_int32 3052 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3053 // return the address of that temp. 3054 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3055 SourceLocation Loc) { 3056 if (auto *OMPRegionInfo = 3057 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3058 if (OMPRegionInfo->getThreadIDVariable()) 3059 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); 3060 3061 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3062 QualType Int32Ty = 3063 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3064 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3065 CGF.EmitStoreOfScalar(ThreadID, 3066 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3067 3068 return ThreadIDTemp; 3069 } 3070 3071 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3072 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3073 SmallString<256> Buffer; 3074 llvm::raw_svector_ostream Out(Buffer); 3075 Out << Name; 3076 StringRef RuntimeName = Out.str(); 3077 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3078 if (Elem.second) { 3079 assert(Elem.second->getType()->getPointerElementType() == Ty && 3080 "OMP internal variable has different type than requested"); 3081 return &*Elem.second; 3082 } 3083 3084 return Elem.second = new llvm::GlobalVariable( 3085 CGM.getModule(), Ty, /*IsConstant*/ false, 3086 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3087 Elem.first(), /*InsertBefore=*/nullptr, 3088 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3089 } 3090 3091 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3092 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3093 std::string Name = getName({Prefix, "var"}); 3094 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3095 } 3096 3097 namespace { 3098 /// Common pre(post)-action for different OpenMP constructs. 3099 class CommonActionTy final : public PrePostActionTy { 3100 llvm::FunctionCallee EnterCallee; 3101 ArrayRef<llvm::Value *> EnterArgs; 3102 llvm::FunctionCallee ExitCallee; 3103 ArrayRef<llvm::Value *> ExitArgs; 3104 bool Conditional; 3105 llvm::BasicBlock *ContBlock = nullptr; 3106 3107 public: 3108 CommonActionTy(llvm::FunctionCallee EnterCallee, 3109 ArrayRef<llvm::Value *> EnterArgs, 3110 llvm::FunctionCallee ExitCallee, 3111 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3112 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3113 ExitArgs(ExitArgs), Conditional(Conditional) {} 3114 void Enter(CodeGenFunction &CGF) override { 3115 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3116 if (Conditional) { 3117 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3118 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3119 ContBlock = CGF.createBasicBlock("omp_if.end"); 3120 // Generate the branch (If-stmt) 3121 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3122 CGF.EmitBlock(ThenBlock); 3123 } 3124 } 3125 void Done(CodeGenFunction &CGF) { 3126 // Emit the rest of blocks/branches 3127 CGF.EmitBranch(ContBlock); 3128 CGF.EmitBlock(ContBlock, true); 3129 } 3130 void Exit(CodeGenFunction &CGF) override { 3131 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3132 } 3133 }; 3134 } // anonymous namespace 3135 3136 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3137 StringRef CriticalName, 3138 const RegionCodeGenTy &CriticalOpGen, 3139 SourceLocation Loc, const Expr *Hint) { 3140 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3141 // CriticalOpGen(); 3142 // __kmpc_end_critical(ident_t *, gtid, Lock); 3143 // Prepare arguments and build a call to __kmpc_critical 3144 if (!CGF.HaveInsertPoint()) 3145 return; 3146 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3147 getCriticalRegionLock(CriticalName)}; 3148 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3149 std::end(Args)); 3150 if (Hint) { 3151 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3152 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3153 } 3154 CommonActionTy Action( 3155 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3156 : OMPRTL__kmpc_critical), 3157 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3158 CriticalOpGen.setAction(Action); 3159 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3160 } 3161 3162 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3163 const RegionCodeGenTy &MasterOpGen, 3164 SourceLocation Loc) { 3165 if (!CGF.HaveInsertPoint()) 3166 return; 3167 // if(__kmpc_master(ident_t *, gtid)) { 3168 // MasterOpGen(); 3169 // __kmpc_end_master(ident_t *, gtid); 3170 // } 3171 // Prepare arguments and build a call to __kmpc_master 3172 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3173 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3174 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3175 /*Conditional=*/true); 3176 MasterOpGen.setAction(Action); 3177 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3178 Action.Done(CGF); 3179 } 3180 3181 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3182 SourceLocation Loc) { 3183 if (!CGF.HaveInsertPoint()) 3184 return; 3185 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3186 llvm::Value *Args[] = { 3187 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3188 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3189 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3190 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3191 Region->emitUntiedSwitch(CGF); 3192 } 3193 3194 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3195 const RegionCodeGenTy &TaskgroupOpGen, 3196 SourceLocation Loc) { 3197 if (!CGF.HaveInsertPoint()) 3198 return; 3199 // __kmpc_taskgroup(ident_t *, gtid); 3200 // TaskgroupOpGen(); 3201 // __kmpc_end_taskgroup(ident_t *, gtid); 3202 // Prepare arguments and build a call to __kmpc_taskgroup 3203 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3204 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3205 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3206 Args); 3207 TaskgroupOpGen.setAction(Action); 3208 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3209 } 3210 3211 /// Given an array of pointers to variables, project the address of a 3212 /// given variable. 3213 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3214 unsigned Index, const VarDecl *Var) { 3215 // Pull out the pointer to the variable. 3216 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3217 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3218 3219 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3220 Addr = CGF.Builder.CreateElementBitCast( 3221 Addr, CGF.ConvertTypeForMem(Var->getType())); 3222 return Addr; 3223 } 3224 3225 static llvm::Value *emitCopyprivateCopyFunction( 3226 CodeGenModule &CGM, llvm::Type *ArgsType, 3227 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3228 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3229 SourceLocation Loc) { 3230 ASTContext &C = CGM.getContext(); 3231 // void copy_func(void *LHSArg, void *RHSArg); 3232 FunctionArgList Args; 3233 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3234 ImplicitParamDecl::Other); 3235 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3236 ImplicitParamDecl::Other); 3237 Args.push_back(&LHSArg); 3238 Args.push_back(&RHSArg); 3239 const auto &CGFI = 3240 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3241 std::string Name = 3242 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3243 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3244 llvm::GlobalValue::InternalLinkage, Name, 3245 &CGM.getModule()); 3246 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3247 Fn->setDoesNotRecurse(); 3248 CodeGenFunction CGF(CGM); 3249 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3250 // Dest = (void*[n])(LHSArg); 3251 // Src = (void*[n])(RHSArg); 3252 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3253 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3254 ArgsType), CGF.getPointerAlign()); 3255 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3256 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3257 ArgsType), CGF.getPointerAlign()); 3258 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3259 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3260 // ... 3261 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3262 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3263 const auto *DestVar = 3264 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3265 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3266 3267 const auto *SrcVar = 3268 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3269 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3270 3271 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3272 QualType Type = VD->getType(); 3273 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3274 } 3275 CGF.FinishFunction(); 3276 return Fn; 3277 } 3278 3279 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3280 const RegionCodeGenTy &SingleOpGen, 3281 SourceLocation Loc, 3282 ArrayRef<const Expr *> CopyprivateVars, 3283 ArrayRef<const Expr *> SrcExprs, 3284 ArrayRef<const Expr *> DstExprs, 3285 ArrayRef<const Expr *> AssignmentOps) { 3286 if (!CGF.HaveInsertPoint()) 3287 return; 3288 assert(CopyprivateVars.size() == SrcExprs.size() && 3289 CopyprivateVars.size() == DstExprs.size() && 3290 CopyprivateVars.size() == AssignmentOps.size()); 3291 ASTContext &C = CGM.getContext(); 3292 // int32 did_it = 0; 3293 // if(__kmpc_single(ident_t *, gtid)) { 3294 // SingleOpGen(); 3295 // __kmpc_end_single(ident_t *, gtid); 3296 // did_it = 1; 3297 // } 3298 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3299 // <copy_func>, did_it); 3300 3301 Address DidIt = Address::invalid(); 3302 if (!CopyprivateVars.empty()) { 3303 // int32 did_it = 0; 3304 QualType KmpInt32Ty = 3305 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3306 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3307 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3308 } 3309 // Prepare arguments and build a call to __kmpc_single 3310 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3311 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3312 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3313 /*Conditional=*/true); 3314 SingleOpGen.setAction(Action); 3315 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3316 if (DidIt.isValid()) { 3317 // did_it = 1; 3318 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3319 } 3320 Action.Done(CGF); 3321 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3322 // <copy_func>, did_it); 3323 if (DidIt.isValid()) { 3324 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3325 QualType CopyprivateArrayTy = 3326 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 3327 /*IndexTypeQuals=*/0); 3328 // Create a list of all private variables for copyprivate. 3329 Address CopyprivateList = 3330 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3331 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3332 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3333 CGF.Builder.CreateStore( 3334 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3335 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy), 3336 Elem); 3337 } 3338 // Build function that copies private values from single region to all other 3339 // threads in the corresponding parallel region. 3340 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3341 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3342 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3343 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3344 Address CL = 3345 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3346 CGF.VoidPtrTy); 3347 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3348 llvm::Value *Args[] = { 3349 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3350 getThreadID(CGF, Loc), // i32 <gtid> 3351 BufSize, // size_t <buf_size> 3352 CL.getPointer(), // void *<copyprivate list> 3353 CpyFn, // void (*) (void *, void *) <copy_func> 3354 DidItVal // i32 did_it 3355 }; 3356 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3357 } 3358 } 3359 3360 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3361 const RegionCodeGenTy &OrderedOpGen, 3362 SourceLocation Loc, bool IsThreads) { 3363 if (!CGF.HaveInsertPoint()) 3364 return; 3365 // __kmpc_ordered(ident_t *, gtid); 3366 // OrderedOpGen(); 3367 // __kmpc_end_ordered(ident_t *, gtid); 3368 // Prepare arguments and build a call to __kmpc_ordered 3369 if (IsThreads) { 3370 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3371 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3372 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3373 Args); 3374 OrderedOpGen.setAction(Action); 3375 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3376 return; 3377 } 3378 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3379 } 3380 3381 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3382 unsigned Flags; 3383 if (Kind == OMPD_for) 3384 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3385 else if (Kind == OMPD_sections) 3386 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3387 else if (Kind == OMPD_single) 3388 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3389 else if (Kind == OMPD_barrier) 3390 Flags = OMP_IDENT_BARRIER_EXPL; 3391 else 3392 Flags = OMP_IDENT_BARRIER_IMPL; 3393 return Flags; 3394 } 3395 3396 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3397 CodeGenFunction &CGF, const OMPLoopDirective &S, 3398 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3399 // Check if the loop directive is actually a doacross loop directive. In this 3400 // case choose static, 1 schedule. 3401 if (llvm::any_of( 3402 S.getClausesOfKind<OMPOrderedClause>(), 3403 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3404 ScheduleKind = OMPC_SCHEDULE_static; 3405 // Chunk size is 1 in this case. 3406 llvm::APInt ChunkSize(32, 1); 3407 ChunkExpr = IntegerLiteral::Create( 3408 CGF.getContext(), ChunkSize, 3409 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3410 SourceLocation()); 3411 } 3412 } 3413 3414 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3415 OpenMPDirectiveKind Kind, bool EmitChecks, 3416 bool ForceSimpleCall) { 3417 if (!CGF.HaveInsertPoint()) 3418 return; 3419 // Build call __kmpc_cancel_barrier(loc, thread_id); 3420 // Build call __kmpc_barrier(loc, thread_id); 3421 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3422 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3423 // thread_id); 3424 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3425 getThreadID(CGF, Loc)}; 3426 if (auto *OMPRegionInfo = 3427 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 3428 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3429 llvm::Value *Result = CGF.EmitRuntimeCall( 3430 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3431 if (EmitChecks) { 3432 // if (__kmpc_cancel_barrier()) { 3433 // exit from construct; 3434 // } 3435 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3436 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3437 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3438 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3439 CGF.EmitBlock(ExitBB); 3440 // exit from construct; 3441 CodeGenFunction::JumpDest CancelDestination = 3442 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3443 CGF.EmitBranchThroughCleanup(CancelDestination); 3444 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3445 } 3446 return; 3447 } 3448 } 3449 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3450 } 3451 3452 /// Map the OpenMP loop schedule to the runtime enumeration. 3453 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3454 bool Chunked, bool Ordered) { 3455 switch (ScheduleKind) { 3456 case OMPC_SCHEDULE_static: 3457 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3458 : (Ordered ? OMP_ord_static : OMP_sch_static); 3459 case OMPC_SCHEDULE_dynamic: 3460 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3461 case OMPC_SCHEDULE_guided: 3462 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3463 case OMPC_SCHEDULE_runtime: 3464 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3465 case OMPC_SCHEDULE_auto: 3466 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3467 case OMPC_SCHEDULE_unknown: 3468 assert(!Chunked && "chunk was specified but schedule kind not known"); 3469 return Ordered ? OMP_ord_static : OMP_sch_static; 3470 } 3471 llvm_unreachable("Unexpected runtime schedule"); 3472 } 3473 3474 /// Map the OpenMP distribute schedule to the runtime enumeration. 3475 static OpenMPSchedType 3476 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3477 // only static is allowed for dist_schedule 3478 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3479 } 3480 3481 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3482 bool Chunked) const { 3483 OpenMPSchedType Schedule = 3484 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3485 return Schedule == OMP_sch_static; 3486 } 3487 3488 bool CGOpenMPRuntime::isStaticNonchunked( 3489 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3490 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3491 return Schedule == OMP_dist_sch_static; 3492 } 3493 3494 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3495 bool Chunked) const { 3496 OpenMPSchedType Schedule = 3497 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3498 return Schedule == OMP_sch_static_chunked; 3499 } 3500 3501 bool CGOpenMPRuntime::isStaticChunked( 3502 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3503 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3504 return Schedule == OMP_dist_sch_static_chunked; 3505 } 3506 3507 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3508 OpenMPSchedType Schedule = 3509 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3510 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3511 return Schedule != OMP_sch_static; 3512 } 3513 3514 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3515 OpenMPScheduleClauseModifier M1, 3516 OpenMPScheduleClauseModifier M2) { 3517 int Modifier = 0; 3518 switch (M1) { 3519 case OMPC_SCHEDULE_MODIFIER_monotonic: 3520 Modifier = OMP_sch_modifier_monotonic; 3521 break; 3522 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3523 Modifier = OMP_sch_modifier_nonmonotonic; 3524 break; 3525 case OMPC_SCHEDULE_MODIFIER_simd: 3526 if (Schedule == OMP_sch_static_chunked) 3527 Schedule = OMP_sch_static_balanced_chunked; 3528 break; 3529 case OMPC_SCHEDULE_MODIFIER_last: 3530 case OMPC_SCHEDULE_MODIFIER_unknown: 3531 break; 3532 } 3533 switch (M2) { 3534 case OMPC_SCHEDULE_MODIFIER_monotonic: 3535 Modifier = OMP_sch_modifier_monotonic; 3536 break; 3537 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3538 Modifier = OMP_sch_modifier_nonmonotonic; 3539 break; 3540 case OMPC_SCHEDULE_MODIFIER_simd: 3541 if (Schedule == OMP_sch_static_chunked) 3542 Schedule = OMP_sch_static_balanced_chunked; 3543 break; 3544 case OMPC_SCHEDULE_MODIFIER_last: 3545 case OMPC_SCHEDULE_MODIFIER_unknown: 3546 break; 3547 } 3548 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3549 // If the static schedule kind is specified or if the ordered clause is 3550 // specified, and if the nonmonotonic modifier is not specified, the effect is 3551 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3552 // modifier is specified, the effect is as if the nonmonotonic modifier is 3553 // specified. 3554 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3555 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3556 Schedule == OMP_sch_static_balanced_chunked || 3557 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static)) 3558 Modifier = OMP_sch_modifier_nonmonotonic; 3559 } 3560 return Schedule | Modifier; 3561 } 3562 3563 void CGOpenMPRuntime::emitForDispatchInit( 3564 CodeGenFunction &CGF, SourceLocation Loc, 3565 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3566 bool Ordered, const DispatchRTInput &DispatchValues) { 3567 if (!CGF.HaveInsertPoint()) 3568 return; 3569 OpenMPSchedType Schedule = getRuntimeSchedule( 3570 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3571 assert(Ordered || 3572 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3573 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3574 Schedule != OMP_sch_static_balanced_chunked)); 3575 // Call __kmpc_dispatch_init( 3576 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3577 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3578 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3579 3580 // If the Chunk was not specified in the clause - use default value 1. 3581 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3582 : CGF.Builder.getIntN(IVSize, 1); 3583 llvm::Value *Args[] = { 3584 emitUpdateLocation(CGF, Loc), 3585 getThreadID(CGF, Loc), 3586 CGF.Builder.getInt32(addMonoNonMonoModifier( 3587 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3588 DispatchValues.LB, // Lower 3589 DispatchValues.UB, // Upper 3590 CGF.Builder.getIntN(IVSize, 1), // Stride 3591 Chunk // Chunk 3592 }; 3593 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3594 } 3595 3596 static void emitForStaticInitCall( 3597 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3598 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3599 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3600 const CGOpenMPRuntime::StaticRTInput &Values) { 3601 if (!CGF.HaveInsertPoint()) 3602 return; 3603 3604 assert(!Values.Ordered); 3605 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3606 Schedule == OMP_sch_static_balanced_chunked || 3607 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3608 Schedule == OMP_dist_sch_static || 3609 Schedule == OMP_dist_sch_static_chunked); 3610 3611 // Call __kmpc_for_static_init( 3612 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3613 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3614 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3615 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3616 llvm::Value *Chunk = Values.Chunk; 3617 if (Chunk == nullptr) { 3618 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3619 Schedule == OMP_dist_sch_static) && 3620 "expected static non-chunked schedule"); 3621 // If the Chunk was not specified in the clause - use default value 1. 3622 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3623 } else { 3624 assert((Schedule == OMP_sch_static_chunked || 3625 Schedule == OMP_sch_static_balanced_chunked || 3626 Schedule == OMP_ord_static_chunked || 3627 Schedule == OMP_dist_sch_static_chunked) && 3628 "expected static chunked schedule"); 3629 } 3630 llvm::Value *Args[] = { 3631 UpdateLocation, 3632 ThreadId, 3633 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3634 M2)), // Schedule type 3635 Values.IL.getPointer(), // &isLastIter 3636 Values.LB.getPointer(), // &LB 3637 Values.UB.getPointer(), // &UB 3638 Values.ST.getPointer(), // &Stride 3639 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3640 Chunk // Chunk 3641 }; 3642 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3643 } 3644 3645 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3646 SourceLocation Loc, 3647 OpenMPDirectiveKind DKind, 3648 const OpenMPScheduleTy &ScheduleKind, 3649 const StaticRTInput &Values) { 3650 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3651 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3652 assert(isOpenMPWorksharingDirective(DKind) && 3653 "Expected loop-based or sections-based directive."); 3654 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3655 isOpenMPLoopDirective(DKind) 3656 ? OMP_IDENT_WORK_LOOP 3657 : OMP_IDENT_WORK_SECTIONS); 3658 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3659 llvm::FunctionCallee StaticInitFunction = 3660 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3661 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3662 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3663 } 3664 3665 void CGOpenMPRuntime::emitDistributeStaticInit( 3666 CodeGenFunction &CGF, SourceLocation Loc, 3667 OpenMPDistScheduleClauseKind SchedKind, 3668 const CGOpenMPRuntime::StaticRTInput &Values) { 3669 OpenMPSchedType ScheduleNum = 3670 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3671 llvm::Value *UpdatedLocation = 3672 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3673 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3674 llvm::FunctionCallee StaticInitFunction = 3675 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3676 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3677 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3678 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3679 } 3680 3681 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3682 SourceLocation Loc, 3683 OpenMPDirectiveKind DKind) { 3684 if (!CGF.HaveInsertPoint()) 3685 return; 3686 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3687 llvm::Value *Args[] = { 3688 emitUpdateLocation(CGF, Loc, 3689 isOpenMPDistributeDirective(DKind) 3690 ? OMP_IDENT_WORK_DISTRIBUTE 3691 : isOpenMPLoopDirective(DKind) 3692 ? OMP_IDENT_WORK_LOOP 3693 : OMP_IDENT_WORK_SECTIONS), 3694 getThreadID(CGF, Loc)}; 3695 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3696 Args); 3697 } 3698 3699 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3700 SourceLocation Loc, 3701 unsigned IVSize, 3702 bool IVSigned) { 3703 if (!CGF.HaveInsertPoint()) 3704 return; 3705 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3706 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3707 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3708 } 3709 3710 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3711 SourceLocation Loc, unsigned IVSize, 3712 bool IVSigned, Address IL, 3713 Address LB, Address UB, 3714 Address ST) { 3715 // Call __kmpc_dispatch_next( 3716 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3717 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3718 // kmp_int[32|64] *p_stride); 3719 llvm::Value *Args[] = { 3720 emitUpdateLocation(CGF, Loc), 3721 getThreadID(CGF, Loc), 3722 IL.getPointer(), // &isLastIter 3723 LB.getPointer(), // &Lower 3724 UB.getPointer(), // &Upper 3725 ST.getPointer() // &Stride 3726 }; 3727 llvm::Value *Call = 3728 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3729 return CGF.EmitScalarConversion( 3730 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3731 CGF.getContext().BoolTy, Loc); 3732 } 3733 3734 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3735 llvm::Value *NumThreads, 3736 SourceLocation Loc) { 3737 if (!CGF.HaveInsertPoint()) 3738 return; 3739 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3740 llvm::Value *Args[] = { 3741 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3742 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3743 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3744 Args); 3745 } 3746 3747 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3748 OpenMPProcBindClauseKind ProcBind, 3749 SourceLocation Loc) { 3750 if (!CGF.HaveInsertPoint()) 3751 return; 3752 // Constants for proc bind value accepted by the runtime. 3753 enum ProcBindTy { 3754 ProcBindFalse = 0, 3755 ProcBindTrue, 3756 ProcBindMaster, 3757 ProcBindClose, 3758 ProcBindSpread, 3759 ProcBindIntel, 3760 ProcBindDefault 3761 } RuntimeProcBind; 3762 switch (ProcBind) { 3763 case OMPC_PROC_BIND_master: 3764 RuntimeProcBind = ProcBindMaster; 3765 break; 3766 case OMPC_PROC_BIND_close: 3767 RuntimeProcBind = ProcBindClose; 3768 break; 3769 case OMPC_PROC_BIND_spread: 3770 RuntimeProcBind = ProcBindSpread; 3771 break; 3772 case OMPC_PROC_BIND_unknown: 3773 llvm_unreachable("Unsupported proc_bind value."); 3774 } 3775 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3776 llvm::Value *Args[] = { 3777 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3778 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 3779 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3780 } 3781 3782 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3783 SourceLocation Loc) { 3784 if (!CGF.HaveInsertPoint()) 3785 return; 3786 // Build call void __kmpc_flush(ident_t *loc) 3787 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3788 emitUpdateLocation(CGF, Loc)); 3789 } 3790 3791 namespace { 3792 /// Indexes of fields for type kmp_task_t. 3793 enum KmpTaskTFields { 3794 /// List of shared variables. 3795 KmpTaskTShareds, 3796 /// Task routine. 3797 KmpTaskTRoutine, 3798 /// Partition id for the untied tasks. 3799 KmpTaskTPartId, 3800 /// Function with call of destructors for private variables. 3801 Data1, 3802 /// Task priority. 3803 Data2, 3804 /// (Taskloops only) Lower bound. 3805 KmpTaskTLowerBound, 3806 /// (Taskloops only) Upper bound. 3807 KmpTaskTUpperBound, 3808 /// (Taskloops only) Stride. 3809 KmpTaskTStride, 3810 /// (Taskloops only) Is last iteration flag. 3811 KmpTaskTLastIter, 3812 /// (Taskloops only) Reduction data. 3813 KmpTaskTReductions, 3814 }; 3815 } // anonymous namespace 3816 3817 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3818 return OffloadEntriesTargetRegion.empty() && 3819 OffloadEntriesDeviceGlobalVar.empty(); 3820 } 3821 3822 /// Initialize target region entry. 3823 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3824 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3825 StringRef ParentName, unsigned LineNum, 3826 unsigned Order) { 3827 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3828 "only required for the device " 3829 "code generation."); 3830 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3831 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3832 OMPTargetRegionEntryTargetRegion); 3833 ++OffloadingEntriesNum; 3834 } 3835 3836 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3837 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3838 StringRef ParentName, unsigned LineNum, 3839 llvm::Constant *Addr, llvm::Constant *ID, 3840 OMPTargetRegionEntryKind Flags) { 3841 // If we are emitting code for a target, the entry is already initialized, 3842 // only has to be registered. 3843 if (CGM.getLangOpts().OpenMPIsDevice) { 3844 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3845 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3846 DiagnosticsEngine::Error, 3847 "Unable to find target region on line '%0' in the device code."); 3848 CGM.getDiags().Report(DiagID) << LineNum; 3849 return; 3850 } 3851 auto &Entry = 3852 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3853 assert(Entry.isValid() && "Entry not initialized!"); 3854 Entry.setAddress(Addr); 3855 Entry.setID(ID); 3856 Entry.setFlags(Flags); 3857 } else { 3858 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3859 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3860 ++OffloadingEntriesNum; 3861 } 3862 } 3863 3864 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3865 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3866 unsigned LineNum) const { 3867 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3868 if (PerDevice == OffloadEntriesTargetRegion.end()) 3869 return false; 3870 auto PerFile = PerDevice->second.find(FileID); 3871 if (PerFile == PerDevice->second.end()) 3872 return false; 3873 auto PerParentName = PerFile->second.find(ParentName); 3874 if (PerParentName == PerFile->second.end()) 3875 return false; 3876 auto PerLine = PerParentName->second.find(LineNum); 3877 if (PerLine == PerParentName->second.end()) 3878 return false; 3879 // Fail if this entry is already registered. 3880 if (PerLine->second.getAddress() || PerLine->second.getID()) 3881 return false; 3882 return true; 3883 } 3884 3885 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3886 const OffloadTargetRegionEntryInfoActTy &Action) { 3887 // Scan all target region entries and perform the provided action. 3888 for (const auto &D : OffloadEntriesTargetRegion) 3889 for (const auto &F : D.second) 3890 for (const auto &P : F.second) 3891 for (const auto &L : P.second) 3892 Action(D.first, F.first, P.first(), L.first, L.second); 3893 } 3894 3895 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3896 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3897 OMPTargetGlobalVarEntryKind Flags, 3898 unsigned Order) { 3899 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3900 "only required for the device " 3901 "code generation."); 3902 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3903 ++OffloadingEntriesNum; 3904 } 3905 3906 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3907 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3908 CharUnits VarSize, 3909 OMPTargetGlobalVarEntryKind Flags, 3910 llvm::GlobalValue::LinkageTypes Linkage) { 3911 if (CGM.getLangOpts().OpenMPIsDevice) { 3912 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3913 assert(Entry.isValid() && Entry.getFlags() == Flags && 3914 "Entry not initialized!"); 3915 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3916 "Resetting with the new address."); 3917 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3918 if (Entry.getVarSize().isZero()) { 3919 Entry.setVarSize(VarSize); 3920 Entry.setLinkage(Linkage); 3921 } 3922 return; 3923 } 3924 Entry.setVarSize(VarSize); 3925 Entry.setLinkage(Linkage); 3926 Entry.setAddress(Addr); 3927 } else { 3928 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3929 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3930 assert(Entry.isValid() && Entry.getFlags() == Flags && 3931 "Entry not initialized!"); 3932 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3933 "Resetting with the new address."); 3934 if (Entry.getVarSize().isZero()) { 3935 Entry.setVarSize(VarSize); 3936 Entry.setLinkage(Linkage); 3937 } 3938 return; 3939 } 3940 OffloadEntriesDeviceGlobalVar.try_emplace( 3941 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3942 ++OffloadingEntriesNum; 3943 } 3944 } 3945 3946 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3947 actOnDeviceGlobalVarEntriesInfo( 3948 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 3949 // Scan all target region entries and perform the provided action. 3950 for (const auto &E : OffloadEntriesDeviceGlobalVar) 3951 Action(E.getKey(), E.getValue()); 3952 } 3953 3954 llvm::Function * 3955 CGOpenMPRuntime::createOffloadingBinaryDescriptorRegistration() { 3956 // If we don't have entries or if we are emitting code for the device, we 3957 // don't need to do anything. 3958 if (CGM.getLangOpts().OpenMPIsDevice || OffloadEntriesInfoManager.empty()) 3959 return nullptr; 3960 3961 llvm::Module &M = CGM.getModule(); 3962 ASTContext &C = CGM.getContext(); 3963 3964 // Get list of devices we care about 3965 const std::vector<llvm::Triple> &Devices = CGM.getLangOpts().OMPTargetTriples; 3966 3967 // We should be creating an offloading descriptor only if there are devices 3968 // specified. 3969 assert(!Devices.empty() && "No OpenMP offloading devices??"); 3970 3971 // Create the external variables that will point to the begin and end of the 3972 // host entries section. These will be defined by the linker. 3973 llvm::Type *OffloadEntryTy = 3974 CGM.getTypes().ConvertTypeForMem(getTgtOffloadEntryQTy()); 3975 auto *HostEntriesBegin = new llvm::GlobalVariable( 3976 M, OffloadEntryTy, /*isConstant=*/true, 3977 llvm::GlobalValue::ExternalLinkage, /*Initializer=*/nullptr, 3978 "__start_omp_offloading_entries"); 3979 HostEntriesBegin->setVisibility(llvm::GlobalValue::HiddenVisibility); 3980 auto *HostEntriesEnd = new llvm::GlobalVariable( 3981 M, OffloadEntryTy, /*isConstant=*/true, 3982 llvm::GlobalValue::ExternalLinkage, 3983 /*Initializer=*/nullptr, "__stop_omp_offloading_entries"); 3984 HostEntriesEnd->setVisibility(llvm::GlobalValue::HiddenVisibility); 3985 3986 // Create all device images 3987 auto *DeviceImageTy = cast<llvm::StructType>( 3988 CGM.getTypes().ConvertTypeForMem(getTgtDeviceImageQTy())); 3989 ConstantInitBuilder DeviceImagesBuilder(CGM); 3990 ConstantArrayBuilder DeviceImagesEntries = 3991 DeviceImagesBuilder.beginArray(DeviceImageTy); 3992 3993 for (const llvm::Triple &Device : Devices) { 3994 StringRef T = Device.getTriple(); 3995 std::string BeginName = getName({"omp_offloading", "img_start", ""}); 3996 auto *ImgBegin = new llvm::GlobalVariable( 3997 M, CGM.Int8Ty, /*isConstant=*/true, 3998 llvm::GlobalValue::ExternalWeakLinkage, 3999 /*Initializer=*/nullptr, Twine(BeginName).concat(T)); 4000 std::string EndName = getName({"omp_offloading", "img_end", ""}); 4001 auto *ImgEnd = new llvm::GlobalVariable( 4002 M, CGM.Int8Ty, /*isConstant=*/true, 4003 llvm::GlobalValue::ExternalWeakLinkage, 4004 /*Initializer=*/nullptr, Twine(EndName).concat(T)); 4005 4006 llvm::Constant *Data[] = {ImgBegin, ImgEnd, HostEntriesBegin, 4007 HostEntriesEnd}; 4008 createConstantGlobalStructAndAddToParent(CGM, getTgtDeviceImageQTy(), Data, 4009 DeviceImagesEntries); 4010 } 4011 4012 // Create device images global array. 4013 std::string ImagesName = getName({"omp_offloading", "device_images"}); 4014 llvm::GlobalVariable *DeviceImages = 4015 DeviceImagesEntries.finishAndCreateGlobal(ImagesName, 4016 CGM.getPointerAlign(), 4017 /*isConstant=*/true); 4018 DeviceImages->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4019 4020 // This is a Zero array to be used in the creation of the constant expressions 4021 llvm::Constant *Index[] = {llvm::Constant::getNullValue(CGM.Int32Ty), 4022 llvm::Constant::getNullValue(CGM.Int32Ty)}; 4023 4024 // Create the target region descriptor. 4025 llvm::Constant *Data[] = { 4026 llvm::ConstantInt::get(CGM.Int32Ty, Devices.size()), 4027 llvm::ConstantExpr::getGetElementPtr(DeviceImages->getValueType(), 4028 DeviceImages, Index), 4029 HostEntriesBegin, HostEntriesEnd}; 4030 std::string Descriptor = getName({"omp_offloading", "descriptor"}); 4031 llvm::GlobalVariable *Desc = createGlobalStruct( 4032 CGM, getTgtBinaryDescriptorQTy(), /*IsConstant=*/true, Data, Descriptor); 4033 4034 // Emit code to register or unregister the descriptor at execution 4035 // startup or closing, respectively. 4036 4037 llvm::Function *UnRegFn; 4038 { 4039 FunctionArgList Args; 4040 ImplicitParamDecl DummyPtr(C, C.VoidPtrTy, ImplicitParamDecl::Other); 4041 Args.push_back(&DummyPtr); 4042 4043 CodeGenFunction CGF(CGM); 4044 // Disable debug info for global (de-)initializer because they are not part 4045 // of some particular construct. 4046 CGF.disableDebugInfo(); 4047 const auto &FI = 4048 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4049 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 4050 std::string UnregName = getName({"omp_offloading", "descriptor_unreg"}); 4051 UnRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, UnregName, FI); 4052 CGF.StartFunction(GlobalDecl(), C.VoidTy, UnRegFn, FI, Args); 4053 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_unregister_lib), 4054 Desc); 4055 CGF.FinishFunction(); 4056 } 4057 llvm::Function *RegFn; 4058 { 4059 CodeGenFunction CGF(CGM); 4060 // Disable debug info for global (de-)initializer because they are not part 4061 // of some particular construct. 4062 CGF.disableDebugInfo(); 4063 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 4064 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 4065 4066 // Encode offload target triples into the registration function name. It 4067 // will serve as a comdat key for the registration/unregistration code for 4068 // this particular combination of offloading targets. 4069 SmallVector<StringRef, 4U> RegFnNameParts(Devices.size() + 2U); 4070 RegFnNameParts[0] = "omp_offloading"; 4071 RegFnNameParts[1] = "descriptor_reg"; 4072 llvm::transform(Devices, std::next(RegFnNameParts.begin(), 2), 4073 [](const llvm::Triple &T) -> const std::string& { 4074 return T.getTriple(); 4075 }); 4076 llvm::sort(std::next(RegFnNameParts.begin(), 2), RegFnNameParts.end()); 4077 std::string Descriptor = getName(RegFnNameParts); 4078 RegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, Descriptor, FI); 4079 CGF.StartFunction(GlobalDecl(), C.VoidTy, RegFn, FI, FunctionArgList()); 4080 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_lib), Desc); 4081 // Create a variable to drive the registration and unregistration of the 4082 // descriptor, so we can reuse the logic that emits Ctors and Dtors. 4083 ImplicitParamDecl RegUnregVar(C, C.getTranslationUnitDecl(), 4084 SourceLocation(), nullptr, C.CharTy, 4085 ImplicitParamDecl::Other); 4086 CGM.getCXXABI().registerGlobalDtor(CGF, RegUnregVar, UnRegFn, Desc); 4087 CGF.FinishFunction(); 4088 } 4089 if (CGM.supportsCOMDAT()) { 4090 // It is sufficient to call registration function only once, so create a 4091 // COMDAT group for registration/unregistration functions and associated 4092 // data. That would reduce startup time and code size. Registration 4093 // function serves as a COMDAT group key. 4094 llvm::Comdat *ComdatKey = M.getOrInsertComdat(RegFn->getName()); 4095 RegFn->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage); 4096 RegFn->setVisibility(llvm::GlobalValue::HiddenVisibility); 4097 RegFn->setComdat(ComdatKey); 4098 UnRegFn->setComdat(ComdatKey); 4099 DeviceImages->setComdat(ComdatKey); 4100 Desc->setComdat(ComdatKey); 4101 } 4102 return RegFn; 4103 } 4104 4105 void CGOpenMPRuntime::createOffloadEntry( 4106 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4107 llvm::GlobalValue::LinkageTypes Linkage) { 4108 StringRef Name = Addr->getName(); 4109 llvm::Module &M = CGM.getModule(); 4110 llvm::LLVMContext &C = M.getContext(); 4111 4112 // Create constant string with the name. 4113 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4114 4115 std::string StringName = getName({"omp_offloading", "entry_name"}); 4116 auto *Str = new llvm::GlobalVariable( 4117 M, StrPtrInit->getType(), /*isConstant=*/true, 4118 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4119 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4120 4121 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4122 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4123 llvm::ConstantInt::get(CGM.SizeTy, Size), 4124 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4125 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4126 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4127 llvm::GlobalVariable *Entry = createGlobalStruct( 4128 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4129 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4130 4131 // The entry has to be created in the section the linker expects it to be. 4132 Entry->setSection("omp_offloading_entries"); 4133 } 4134 4135 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4136 // Emit the offloading entries and metadata so that the device codegen side 4137 // can easily figure out what to emit. The produced metadata looks like 4138 // this: 4139 // 4140 // !omp_offload.info = !{!1, ...} 4141 // 4142 // Right now we only generate metadata for function that contain target 4143 // regions. 4144 4145 // If we do not have entries, we don't need to do anything. 4146 if (OffloadEntriesInfoManager.empty()) 4147 return; 4148 4149 llvm::Module &M = CGM.getModule(); 4150 llvm::LLVMContext &C = M.getContext(); 4151 SmallVector<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 16> 4152 OrderedEntries(OffloadEntriesInfoManager.size()); 4153 llvm::SmallVector<StringRef, 16> ParentFunctions( 4154 OffloadEntriesInfoManager.size()); 4155 4156 // Auxiliary methods to create metadata values and strings. 4157 auto &&GetMDInt = [this](unsigned V) { 4158 return llvm::ConstantAsMetadata::get( 4159 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4160 }; 4161 4162 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4163 4164 // Create the offloading info metadata node. 4165 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4166 4167 // Create function that emits metadata for each target region entry; 4168 auto &&TargetRegionMetadataEmitter = 4169 [&C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, &GetMDString]( 4170 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4171 unsigned Line, 4172 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4173 // Generate metadata for target regions. Each entry of this metadata 4174 // contains: 4175 // - Entry 0 -> Kind of this type of metadata (0). 4176 // - Entry 1 -> Device ID of the file where the entry was identified. 4177 // - Entry 2 -> File ID of the file where the entry was identified. 4178 // - Entry 3 -> Mangled name of the function where the entry was 4179 // identified. 4180 // - Entry 4 -> Line in the file where the entry was identified. 4181 // - Entry 5 -> Order the entry was created. 4182 // The first element of the metadata node is the kind. 4183 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4184 GetMDInt(FileID), GetMDString(ParentName), 4185 GetMDInt(Line), GetMDInt(E.getOrder())}; 4186 4187 // Save this entry in the right position of the ordered entries array. 4188 OrderedEntries[E.getOrder()] = &E; 4189 ParentFunctions[E.getOrder()] = ParentName; 4190 4191 // Add metadata to the named metadata node. 4192 MD->addOperand(llvm::MDNode::get(C, Ops)); 4193 }; 4194 4195 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4196 TargetRegionMetadataEmitter); 4197 4198 // Create function that emits metadata for each device global variable entry; 4199 auto &&DeviceGlobalVarMetadataEmitter = 4200 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4201 MD](StringRef MangledName, 4202 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4203 &E) { 4204 // Generate metadata for global variables. Each entry of this metadata 4205 // contains: 4206 // - Entry 0 -> Kind of this type of metadata (1). 4207 // - Entry 1 -> Mangled name of the variable. 4208 // - Entry 2 -> Declare target kind. 4209 // - Entry 3 -> Order the entry was created. 4210 // The first element of the metadata node is the kind. 4211 llvm::Metadata *Ops[] = { 4212 GetMDInt(E.getKind()), GetMDString(MangledName), 4213 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4214 4215 // Save this entry in the right position of the ordered entries array. 4216 OrderedEntries[E.getOrder()] = &E; 4217 4218 // Add metadata to the named metadata node. 4219 MD->addOperand(llvm::MDNode::get(C, Ops)); 4220 }; 4221 4222 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4223 DeviceGlobalVarMetadataEmitter); 4224 4225 for (const auto *E : OrderedEntries) { 4226 assert(E && "All ordered entries must exist!"); 4227 if (const auto *CE = 4228 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4229 E)) { 4230 if (!CE->getID() || !CE->getAddress()) { 4231 // Do not blame the entry if the parent funtion is not emitted. 4232 StringRef FnName = ParentFunctions[CE->getOrder()]; 4233 if (!CGM.GetGlobalValue(FnName)) 4234 continue; 4235 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4236 DiagnosticsEngine::Error, 4237 "Offloading entry for target region is incorrect: either the " 4238 "address or the ID is invalid."); 4239 CGM.getDiags().Report(DiagID); 4240 continue; 4241 } 4242 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4243 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4244 } else if (const auto *CE = 4245 dyn_cast<OffloadEntriesInfoManagerTy:: 4246 OffloadEntryInfoDeviceGlobalVar>(E)) { 4247 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4248 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4249 CE->getFlags()); 4250 switch (Flags) { 4251 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4252 if (CGM.getLangOpts().OpenMPIsDevice && 4253 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4254 continue; 4255 if (!CE->getAddress()) { 4256 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4257 DiagnosticsEngine::Error, 4258 "Offloading entry for declare target variable is incorrect: the " 4259 "address is invalid."); 4260 CGM.getDiags().Report(DiagID); 4261 continue; 4262 } 4263 // The vaiable has no definition - no need to add the entry. 4264 if (CE->getVarSize().isZero()) 4265 continue; 4266 break; 4267 } 4268 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4269 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4270 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4271 "Declaret target link address is set."); 4272 if (CGM.getLangOpts().OpenMPIsDevice) 4273 continue; 4274 if (!CE->getAddress()) { 4275 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4276 DiagnosticsEngine::Error, 4277 "Offloading entry for declare target variable is incorrect: the " 4278 "address is invalid."); 4279 CGM.getDiags().Report(DiagID); 4280 continue; 4281 } 4282 break; 4283 } 4284 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4285 CE->getVarSize().getQuantity(), Flags, 4286 CE->getLinkage()); 4287 } else { 4288 llvm_unreachable("Unsupported entry kind."); 4289 } 4290 } 4291 } 4292 4293 /// Loads all the offload entries information from the host IR 4294 /// metadata. 4295 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4296 // If we are in target mode, load the metadata from the host IR. This code has 4297 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4298 4299 if (!CGM.getLangOpts().OpenMPIsDevice) 4300 return; 4301 4302 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4303 return; 4304 4305 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4306 if (auto EC = Buf.getError()) { 4307 CGM.getDiags().Report(diag::err_cannot_open_file) 4308 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4309 return; 4310 } 4311 4312 llvm::LLVMContext C; 4313 auto ME = expectedToErrorOrAndEmitErrors( 4314 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4315 4316 if (auto EC = ME.getError()) { 4317 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4318 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4319 CGM.getDiags().Report(DiagID) 4320 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4321 return; 4322 } 4323 4324 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4325 if (!MD) 4326 return; 4327 4328 for (llvm::MDNode *MN : MD->operands()) { 4329 auto &&GetMDInt = [MN](unsigned Idx) { 4330 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4331 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4332 }; 4333 4334 auto &&GetMDString = [MN](unsigned Idx) { 4335 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4336 return V->getString(); 4337 }; 4338 4339 switch (GetMDInt(0)) { 4340 default: 4341 llvm_unreachable("Unexpected metadata!"); 4342 break; 4343 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4344 OffloadingEntryInfoTargetRegion: 4345 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4346 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4347 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4348 /*Order=*/GetMDInt(5)); 4349 break; 4350 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4351 OffloadingEntryInfoDeviceGlobalVar: 4352 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4353 /*MangledName=*/GetMDString(1), 4354 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4355 /*Flags=*/GetMDInt(2)), 4356 /*Order=*/GetMDInt(3)); 4357 break; 4358 } 4359 } 4360 } 4361 4362 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4363 if (!KmpRoutineEntryPtrTy) { 4364 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4365 ASTContext &C = CGM.getContext(); 4366 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4367 FunctionProtoType::ExtProtoInfo EPI; 4368 KmpRoutineEntryPtrQTy = C.getPointerType( 4369 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4370 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4371 } 4372 } 4373 4374 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4375 // Make sure the type of the entry is already created. This is the type we 4376 // have to create: 4377 // struct __tgt_offload_entry{ 4378 // void *addr; // Pointer to the offload entry info. 4379 // // (function or global) 4380 // char *name; // Name of the function or global. 4381 // size_t size; // Size of the entry info (0 if it a function). 4382 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4383 // int32_t reserved; // Reserved, to use by the runtime library. 4384 // }; 4385 if (TgtOffloadEntryQTy.isNull()) { 4386 ASTContext &C = CGM.getContext(); 4387 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4388 RD->startDefinition(); 4389 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4390 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4391 addFieldToRecordDecl(C, RD, C.getSizeType()); 4392 addFieldToRecordDecl( 4393 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4394 addFieldToRecordDecl( 4395 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4396 RD->completeDefinition(); 4397 RD->addAttr(PackedAttr::CreateImplicit(C)); 4398 TgtOffloadEntryQTy = C.getRecordType(RD); 4399 } 4400 return TgtOffloadEntryQTy; 4401 } 4402 4403 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 4404 // These are the types we need to build: 4405 // struct __tgt_device_image{ 4406 // void *ImageStart; // Pointer to the target code start. 4407 // void *ImageEnd; // Pointer to the target code end. 4408 // // We also add the host entries to the device image, as it may be useful 4409 // // for the target runtime to have access to that information. 4410 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 4411 // // the entries. 4412 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4413 // // entries (non inclusive). 4414 // }; 4415 if (TgtDeviceImageQTy.isNull()) { 4416 ASTContext &C = CGM.getContext(); 4417 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image"); 4418 RD->startDefinition(); 4419 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4420 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4421 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4422 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4423 RD->completeDefinition(); 4424 TgtDeviceImageQTy = C.getRecordType(RD); 4425 } 4426 return TgtDeviceImageQTy; 4427 } 4428 4429 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 4430 // struct __tgt_bin_desc{ 4431 // int32_t NumDevices; // Number of devices supported. 4432 // __tgt_device_image *DeviceImages; // Arrays of device images 4433 // // (one per device). 4434 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 4435 // // entries. 4436 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4437 // // entries (non inclusive). 4438 // }; 4439 if (TgtBinaryDescriptorQTy.isNull()) { 4440 ASTContext &C = CGM.getContext(); 4441 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc"); 4442 RD->startDefinition(); 4443 addFieldToRecordDecl( 4444 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4445 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 4446 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4447 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4448 RD->completeDefinition(); 4449 TgtBinaryDescriptorQTy = C.getRecordType(RD); 4450 } 4451 return TgtBinaryDescriptorQTy; 4452 } 4453 4454 namespace { 4455 struct PrivateHelpersTy { 4456 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4457 const VarDecl *PrivateElemInit) 4458 : Original(Original), PrivateCopy(PrivateCopy), 4459 PrivateElemInit(PrivateElemInit) {} 4460 const VarDecl *Original; 4461 const VarDecl *PrivateCopy; 4462 const VarDecl *PrivateElemInit; 4463 }; 4464 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4465 } // anonymous namespace 4466 4467 static RecordDecl * 4468 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4469 if (!Privates.empty()) { 4470 ASTContext &C = CGM.getContext(); 4471 // Build struct .kmp_privates_t. { 4472 // /* private vars */ 4473 // }; 4474 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4475 RD->startDefinition(); 4476 for (const auto &Pair : Privates) { 4477 const VarDecl *VD = Pair.second.Original; 4478 QualType Type = VD->getType().getNonReferenceType(); 4479 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4480 if (VD->hasAttrs()) { 4481 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4482 E(VD->getAttrs().end()); 4483 I != E; ++I) 4484 FD->addAttr(*I); 4485 } 4486 } 4487 RD->completeDefinition(); 4488 return RD; 4489 } 4490 return nullptr; 4491 } 4492 4493 static RecordDecl * 4494 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4495 QualType KmpInt32Ty, 4496 QualType KmpRoutineEntryPointerQTy) { 4497 ASTContext &C = CGM.getContext(); 4498 // Build struct kmp_task_t { 4499 // void * shareds; 4500 // kmp_routine_entry_t routine; 4501 // kmp_int32 part_id; 4502 // kmp_cmplrdata_t data1; 4503 // kmp_cmplrdata_t data2; 4504 // For taskloops additional fields: 4505 // kmp_uint64 lb; 4506 // kmp_uint64 ub; 4507 // kmp_int64 st; 4508 // kmp_int32 liter; 4509 // void * reductions; 4510 // }; 4511 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4512 UD->startDefinition(); 4513 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4514 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4515 UD->completeDefinition(); 4516 QualType KmpCmplrdataTy = C.getRecordType(UD); 4517 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4518 RD->startDefinition(); 4519 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4520 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4521 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4522 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4523 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4524 if (isOpenMPTaskLoopDirective(Kind)) { 4525 QualType KmpUInt64Ty = 4526 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4527 QualType KmpInt64Ty = 4528 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4529 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4530 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4531 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4532 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4533 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4534 } 4535 RD->completeDefinition(); 4536 return RD; 4537 } 4538 4539 static RecordDecl * 4540 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4541 ArrayRef<PrivateDataTy> Privates) { 4542 ASTContext &C = CGM.getContext(); 4543 // Build struct kmp_task_t_with_privates { 4544 // kmp_task_t task_data; 4545 // .kmp_privates_t. privates; 4546 // }; 4547 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4548 RD->startDefinition(); 4549 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4550 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4551 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4552 RD->completeDefinition(); 4553 return RD; 4554 } 4555 4556 /// Emit a proxy function which accepts kmp_task_t as the second 4557 /// argument. 4558 /// \code 4559 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4560 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4561 /// For taskloops: 4562 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4563 /// tt->reductions, tt->shareds); 4564 /// return 0; 4565 /// } 4566 /// \endcode 4567 static llvm::Function * 4568 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4569 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4570 QualType KmpTaskTWithPrivatesPtrQTy, 4571 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4572 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4573 llvm::Value *TaskPrivatesMap) { 4574 ASTContext &C = CGM.getContext(); 4575 FunctionArgList Args; 4576 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4577 ImplicitParamDecl::Other); 4578 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4579 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4580 ImplicitParamDecl::Other); 4581 Args.push_back(&GtidArg); 4582 Args.push_back(&TaskTypeArg); 4583 const auto &TaskEntryFnInfo = 4584 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4585 llvm::FunctionType *TaskEntryTy = 4586 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4587 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4588 auto *TaskEntry = llvm::Function::Create( 4589 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4590 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4591 TaskEntry->setDoesNotRecurse(); 4592 CodeGenFunction CGF(CGM); 4593 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4594 Loc, Loc); 4595 4596 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4597 // tt, 4598 // For taskloops: 4599 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4600 // tt->task_data.shareds); 4601 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4602 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4603 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4604 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4605 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4606 const auto *KmpTaskTWithPrivatesQTyRD = 4607 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4608 LValue Base = 4609 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4610 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4611 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4612 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4613 llvm::Value *PartidParam = PartIdLVal.getPointer(); 4614 4615 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4616 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4617 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4618 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4619 CGF.ConvertTypeForMem(SharedsPtrTy)); 4620 4621 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4622 llvm::Value *PrivatesParam; 4623 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4624 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4625 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4626 PrivatesLVal.getPointer(), CGF.VoidPtrTy); 4627 } else { 4628 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4629 } 4630 4631 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4632 TaskPrivatesMap, 4633 CGF.Builder 4634 .CreatePointerBitCastOrAddrSpaceCast( 4635 TDBase.getAddress(), CGF.VoidPtrTy) 4636 .getPointer()}; 4637 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4638 std::end(CommonArgs)); 4639 if (isOpenMPTaskLoopDirective(Kind)) { 4640 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4641 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4642 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4643 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4644 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4645 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4646 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4647 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4648 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4649 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4650 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4651 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4652 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4653 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4654 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4655 CallArgs.push_back(LBParam); 4656 CallArgs.push_back(UBParam); 4657 CallArgs.push_back(StParam); 4658 CallArgs.push_back(LIParam); 4659 CallArgs.push_back(RParam); 4660 } 4661 CallArgs.push_back(SharedsParam); 4662 4663 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4664 CallArgs); 4665 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4666 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4667 CGF.FinishFunction(); 4668 return TaskEntry; 4669 } 4670 4671 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4672 SourceLocation Loc, 4673 QualType KmpInt32Ty, 4674 QualType KmpTaskTWithPrivatesPtrQTy, 4675 QualType KmpTaskTWithPrivatesQTy) { 4676 ASTContext &C = CGM.getContext(); 4677 FunctionArgList Args; 4678 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4679 ImplicitParamDecl::Other); 4680 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4681 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4682 ImplicitParamDecl::Other); 4683 Args.push_back(&GtidArg); 4684 Args.push_back(&TaskTypeArg); 4685 const auto &DestructorFnInfo = 4686 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4687 llvm::FunctionType *DestructorFnTy = 4688 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4689 std::string Name = 4690 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4691 auto *DestructorFn = 4692 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4693 Name, &CGM.getModule()); 4694 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4695 DestructorFnInfo); 4696 DestructorFn->setDoesNotRecurse(); 4697 CodeGenFunction CGF(CGM); 4698 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4699 Args, Loc, Loc); 4700 4701 LValue Base = CGF.EmitLoadOfPointerLValue( 4702 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4703 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4704 const auto *KmpTaskTWithPrivatesQTyRD = 4705 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4706 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4707 Base = CGF.EmitLValueForField(Base, *FI); 4708 for (const auto *Field : 4709 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4710 if (QualType::DestructionKind DtorKind = 4711 Field->getType().isDestructedType()) { 4712 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4713 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); 4714 } 4715 } 4716 CGF.FinishFunction(); 4717 return DestructorFn; 4718 } 4719 4720 /// Emit a privates mapping function for correct handling of private and 4721 /// firstprivate variables. 4722 /// \code 4723 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4724 /// **noalias priv1,..., <tyn> **noalias privn) { 4725 /// *priv1 = &.privates.priv1; 4726 /// ...; 4727 /// *privn = &.privates.privn; 4728 /// } 4729 /// \endcode 4730 static llvm::Value * 4731 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4732 ArrayRef<const Expr *> PrivateVars, 4733 ArrayRef<const Expr *> FirstprivateVars, 4734 ArrayRef<const Expr *> LastprivateVars, 4735 QualType PrivatesQTy, 4736 ArrayRef<PrivateDataTy> Privates) { 4737 ASTContext &C = CGM.getContext(); 4738 FunctionArgList Args; 4739 ImplicitParamDecl TaskPrivatesArg( 4740 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4741 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4742 ImplicitParamDecl::Other); 4743 Args.push_back(&TaskPrivatesArg); 4744 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4745 unsigned Counter = 1; 4746 for (const Expr *E : PrivateVars) { 4747 Args.push_back(ImplicitParamDecl::Create( 4748 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4749 C.getPointerType(C.getPointerType(E->getType())) 4750 .withConst() 4751 .withRestrict(), 4752 ImplicitParamDecl::Other)); 4753 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4754 PrivateVarsPos[VD] = Counter; 4755 ++Counter; 4756 } 4757 for (const Expr *E : FirstprivateVars) { 4758 Args.push_back(ImplicitParamDecl::Create( 4759 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4760 C.getPointerType(C.getPointerType(E->getType())) 4761 .withConst() 4762 .withRestrict(), 4763 ImplicitParamDecl::Other)); 4764 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4765 PrivateVarsPos[VD] = Counter; 4766 ++Counter; 4767 } 4768 for (const Expr *E : LastprivateVars) { 4769 Args.push_back(ImplicitParamDecl::Create( 4770 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4771 C.getPointerType(C.getPointerType(E->getType())) 4772 .withConst() 4773 .withRestrict(), 4774 ImplicitParamDecl::Other)); 4775 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4776 PrivateVarsPos[VD] = Counter; 4777 ++Counter; 4778 } 4779 const auto &TaskPrivatesMapFnInfo = 4780 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4781 llvm::FunctionType *TaskPrivatesMapTy = 4782 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4783 std::string Name = 4784 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4785 auto *TaskPrivatesMap = llvm::Function::Create( 4786 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4787 &CGM.getModule()); 4788 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4789 TaskPrivatesMapFnInfo); 4790 if (CGM.getLangOpts().Optimize) { 4791 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4792 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4793 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4794 } 4795 CodeGenFunction CGF(CGM); 4796 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4797 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4798 4799 // *privi = &.privates.privi; 4800 LValue Base = CGF.EmitLoadOfPointerLValue( 4801 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4802 TaskPrivatesArg.getType()->castAs<PointerType>()); 4803 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4804 Counter = 0; 4805 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4806 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4807 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4808 LValue RefLVal = 4809 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4810 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4811 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>()); 4812 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal); 4813 ++Counter; 4814 } 4815 CGF.FinishFunction(); 4816 return TaskPrivatesMap; 4817 } 4818 4819 /// Emit initialization for private variables in task-based directives. 4820 static void emitPrivatesInit(CodeGenFunction &CGF, 4821 const OMPExecutableDirective &D, 4822 Address KmpTaskSharedsPtr, LValue TDBase, 4823 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4824 QualType SharedsTy, QualType SharedsPtrTy, 4825 const OMPTaskDataTy &Data, 4826 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4827 ASTContext &C = CGF.getContext(); 4828 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4829 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4830 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4831 ? OMPD_taskloop 4832 : OMPD_task; 4833 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4834 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4835 LValue SrcBase; 4836 bool IsTargetTask = 4837 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4838 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4839 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4840 // PointersArray and SizesArray. The original variables for these arrays are 4841 // not captured and we get their addresses explicitly. 4842 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4843 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4844 SrcBase = CGF.MakeAddrLValue( 4845 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4846 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4847 SharedsTy); 4848 } 4849 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4850 for (const PrivateDataTy &Pair : Privates) { 4851 const VarDecl *VD = Pair.second.PrivateCopy; 4852 const Expr *Init = VD->getAnyInitializer(); 4853 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4854 !CGF.isTrivialInitializer(Init)))) { 4855 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4856 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4857 const VarDecl *OriginalVD = Pair.second.Original; 4858 // Check if the variable is the target-based BasePointersArray, 4859 // PointersArray or SizesArray. 4860 LValue SharedRefLValue; 4861 QualType Type = PrivateLValue.getType(); 4862 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4863 if (IsTargetTask && !SharedField) { 4864 assert(isa<ImplicitParamDecl>(OriginalVD) && 4865 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4866 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4867 ->getNumParams() == 0 && 4868 isa<TranslationUnitDecl>( 4869 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4870 ->getDeclContext()) && 4871 "Expected artificial target data variable."); 4872 SharedRefLValue = 4873 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4874 } else { 4875 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4876 SharedRefLValue = CGF.MakeAddrLValue( 4877 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), 4878 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4879 SharedRefLValue.getTBAAInfo()); 4880 } 4881 if (Type->isArrayType()) { 4882 // Initialize firstprivate array. 4883 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4884 // Perform simple memcpy. 4885 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4886 } else { 4887 // Initialize firstprivate array using element-by-element 4888 // initialization. 4889 CGF.EmitOMPAggregateAssign( 4890 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type, 4891 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4892 Address SrcElement) { 4893 // Clean up any temporaries needed by the initialization. 4894 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4895 InitScope.addPrivate( 4896 Elem, [SrcElement]() -> Address { return SrcElement; }); 4897 (void)InitScope.Privatize(); 4898 // Emit initialization for single element. 4899 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4900 CGF, &CapturesInfo); 4901 CGF.EmitAnyExprToMem(Init, DestElement, 4902 Init->getType().getQualifiers(), 4903 /*IsInitializer=*/false); 4904 }); 4905 } 4906 } else { 4907 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4908 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address { 4909 return SharedRefLValue.getAddress(); 4910 }); 4911 (void)InitScope.Privatize(); 4912 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4913 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4914 /*capturedByInit=*/false); 4915 } 4916 } else { 4917 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4918 } 4919 } 4920 ++FI; 4921 } 4922 } 4923 4924 /// Check if duplication function is required for taskloops. 4925 static bool checkInitIsRequired(CodeGenFunction &CGF, 4926 ArrayRef<PrivateDataTy> Privates) { 4927 bool InitRequired = false; 4928 for (const PrivateDataTy &Pair : Privates) { 4929 const VarDecl *VD = Pair.second.PrivateCopy; 4930 const Expr *Init = VD->getAnyInitializer(); 4931 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4932 !CGF.isTrivialInitializer(Init)); 4933 if (InitRequired) 4934 break; 4935 } 4936 return InitRequired; 4937 } 4938 4939 4940 /// Emit task_dup function (for initialization of 4941 /// private/firstprivate/lastprivate vars and last_iter flag) 4942 /// \code 4943 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4944 /// lastpriv) { 4945 /// // setup lastprivate flag 4946 /// task_dst->last = lastpriv; 4947 /// // could be constructor calls here... 4948 /// } 4949 /// \endcode 4950 static llvm::Value * 4951 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4952 const OMPExecutableDirective &D, 4953 QualType KmpTaskTWithPrivatesPtrQTy, 4954 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4955 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4956 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4957 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4958 ASTContext &C = CGM.getContext(); 4959 FunctionArgList Args; 4960 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4961 KmpTaskTWithPrivatesPtrQTy, 4962 ImplicitParamDecl::Other); 4963 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4964 KmpTaskTWithPrivatesPtrQTy, 4965 ImplicitParamDecl::Other); 4966 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4967 ImplicitParamDecl::Other); 4968 Args.push_back(&DstArg); 4969 Args.push_back(&SrcArg); 4970 Args.push_back(&LastprivArg); 4971 const auto &TaskDupFnInfo = 4972 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4973 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4974 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4975 auto *TaskDup = llvm::Function::Create( 4976 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4977 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4978 TaskDup->setDoesNotRecurse(); 4979 CodeGenFunction CGF(CGM); 4980 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4981 Loc); 4982 4983 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4984 CGF.GetAddrOfLocalVar(&DstArg), 4985 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4986 // task_dst->liter = lastpriv; 4987 if (WithLastIter) { 4988 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4989 LValue Base = CGF.EmitLValueForField( 4990 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4991 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4992 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4993 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4994 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4995 } 4996 4997 // Emit initial values for private copies (if any). 4998 assert(!Privates.empty()); 4999 Address KmpTaskSharedsPtr = Address::invalid(); 5000 if (!Data.FirstprivateVars.empty()) { 5001 LValue TDBase = CGF.EmitLoadOfPointerLValue( 5002 CGF.GetAddrOfLocalVar(&SrcArg), 5003 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 5004 LValue Base = CGF.EmitLValueForField( 5005 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5006 KmpTaskSharedsPtr = Address( 5007 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 5008 Base, *std::next(KmpTaskTQTyRD->field_begin(), 5009 KmpTaskTShareds)), 5010 Loc), 5011 CGF.getNaturalTypeAlignment(SharedsTy)); 5012 } 5013 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 5014 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 5015 CGF.FinishFunction(); 5016 return TaskDup; 5017 } 5018 5019 /// Checks if destructor function is required to be generated. 5020 /// \return true if cleanups are required, false otherwise. 5021 static bool 5022 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 5023 bool NeedsCleanup = false; 5024 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 5025 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 5026 for (const FieldDecl *FD : PrivateRD->fields()) { 5027 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 5028 if (NeedsCleanup) 5029 break; 5030 } 5031 return NeedsCleanup; 5032 } 5033 5034 CGOpenMPRuntime::TaskResultTy 5035 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 5036 const OMPExecutableDirective &D, 5037 llvm::Function *TaskFunction, QualType SharedsTy, 5038 Address Shareds, const OMPTaskDataTy &Data) { 5039 ASTContext &C = CGM.getContext(); 5040 llvm::SmallVector<PrivateDataTy, 4> Privates; 5041 // Aggregate privates and sort them by the alignment. 5042 auto I = Data.PrivateCopies.begin(); 5043 for (const Expr *E : Data.PrivateVars) { 5044 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5045 Privates.emplace_back( 5046 C.getDeclAlign(VD), 5047 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5048 /*PrivateElemInit=*/nullptr)); 5049 ++I; 5050 } 5051 I = Data.FirstprivateCopies.begin(); 5052 auto IElemInitRef = Data.FirstprivateInits.begin(); 5053 for (const Expr *E : Data.FirstprivateVars) { 5054 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5055 Privates.emplace_back( 5056 C.getDeclAlign(VD), 5057 PrivateHelpersTy( 5058 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5059 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 5060 ++I; 5061 ++IElemInitRef; 5062 } 5063 I = Data.LastprivateCopies.begin(); 5064 for (const Expr *E : Data.LastprivateVars) { 5065 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5066 Privates.emplace_back( 5067 C.getDeclAlign(VD), 5068 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5069 /*PrivateElemInit=*/nullptr)); 5070 ++I; 5071 } 5072 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 5073 return L.first > R.first; 5074 }); 5075 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 5076 // Build type kmp_routine_entry_t (if not built yet). 5077 emitKmpRoutineEntryT(KmpInt32Ty); 5078 // Build type kmp_task_t (if not built yet). 5079 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5080 if (SavedKmpTaskloopTQTy.isNull()) { 5081 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5082 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5083 } 5084 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5085 } else { 5086 assert((D.getDirectiveKind() == OMPD_task || 5087 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5088 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5089 "Expected taskloop, task or target directive"); 5090 if (SavedKmpTaskTQTy.isNull()) { 5091 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5092 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5093 } 5094 KmpTaskTQTy = SavedKmpTaskTQTy; 5095 } 5096 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5097 // Build particular struct kmp_task_t for the given task. 5098 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5099 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5100 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5101 QualType KmpTaskTWithPrivatesPtrQTy = 5102 C.getPointerType(KmpTaskTWithPrivatesQTy); 5103 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5104 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5105 KmpTaskTWithPrivatesTy->getPointerTo(); 5106 llvm::Value *KmpTaskTWithPrivatesTySize = 5107 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5108 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5109 5110 // Emit initial values for private copies (if any). 5111 llvm::Value *TaskPrivatesMap = nullptr; 5112 llvm::Type *TaskPrivatesMapTy = 5113 std::next(TaskFunction->arg_begin(), 3)->getType(); 5114 if (!Privates.empty()) { 5115 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5116 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5117 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5118 FI->getType(), Privates); 5119 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5120 TaskPrivatesMap, TaskPrivatesMapTy); 5121 } else { 5122 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5123 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5124 } 5125 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5126 // kmp_task_t *tt); 5127 llvm::Function *TaskEntry = emitProxyTaskFunction( 5128 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5129 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5130 TaskPrivatesMap); 5131 5132 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5133 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5134 // kmp_routine_entry_t *task_entry); 5135 // Task flags. Format is taken from 5136 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5137 // description of kmp_tasking_flags struct. 5138 enum { 5139 TiedFlag = 0x1, 5140 FinalFlag = 0x2, 5141 DestructorsFlag = 0x8, 5142 PriorityFlag = 0x20 5143 }; 5144 unsigned Flags = Data.Tied ? TiedFlag : 0; 5145 bool NeedsCleanup = false; 5146 if (!Privates.empty()) { 5147 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5148 if (NeedsCleanup) 5149 Flags = Flags | DestructorsFlag; 5150 } 5151 if (Data.Priority.getInt()) 5152 Flags = Flags | PriorityFlag; 5153 llvm::Value *TaskFlags = 5154 Data.Final.getPointer() 5155 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5156 CGF.Builder.getInt32(FinalFlag), 5157 CGF.Builder.getInt32(/*C=*/0)) 5158 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5159 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5160 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5161 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5162 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5163 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5164 TaskEntry, KmpRoutineEntryPtrTy)}; 5165 llvm::Value *NewTask; 5166 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5167 // Check if we have any device clause associated with the directive. 5168 const Expr *Device = nullptr; 5169 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5170 Device = C->getDevice(); 5171 // Emit device ID if any otherwise use default value. 5172 llvm::Value *DeviceID; 5173 if (Device) 5174 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5175 CGF.Int64Ty, /*isSigned=*/true); 5176 else 5177 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5178 AllocArgs.push_back(DeviceID); 5179 NewTask = CGF.EmitRuntimeCall( 5180 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5181 } else { 5182 NewTask = CGF.EmitRuntimeCall( 5183 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5184 } 5185 llvm::Value *NewTaskNewTaskTTy = 5186 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5187 NewTask, KmpTaskTWithPrivatesPtrTy); 5188 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5189 KmpTaskTWithPrivatesQTy); 5190 LValue TDBase = 5191 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5192 // Fill the data in the resulting kmp_task_t record. 5193 // Copy shareds if there are any. 5194 Address KmpTaskSharedsPtr = Address::invalid(); 5195 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5196 KmpTaskSharedsPtr = 5197 Address(CGF.EmitLoadOfScalar( 5198 CGF.EmitLValueForField( 5199 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5200 KmpTaskTShareds)), 5201 Loc), 5202 CGF.getNaturalTypeAlignment(SharedsTy)); 5203 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5204 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5205 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5206 } 5207 // Emit initial values for private copies (if any). 5208 TaskResultTy Result; 5209 if (!Privates.empty()) { 5210 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5211 SharedsTy, SharedsPtrTy, Data, Privates, 5212 /*ForDup=*/false); 5213 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5214 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5215 Result.TaskDupFn = emitTaskDupFunction( 5216 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5217 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5218 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5219 } 5220 } 5221 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5222 enum { Priority = 0, Destructors = 1 }; 5223 // Provide pointer to function with destructors for privates. 5224 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5225 const RecordDecl *KmpCmplrdataUD = 5226 (*FI)->getType()->getAsUnionType()->getDecl(); 5227 if (NeedsCleanup) { 5228 llvm::Value *DestructorFn = emitDestructorsFunction( 5229 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5230 KmpTaskTWithPrivatesQTy); 5231 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5232 LValue DestructorsLV = CGF.EmitLValueForField( 5233 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5234 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5235 DestructorFn, KmpRoutineEntryPtrTy), 5236 DestructorsLV); 5237 } 5238 // Set priority. 5239 if (Data.Priority.getInt()) { 5240 LValue Data2LV = CGF.EmitLValueForField( 5241 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5242 LValue PriorityLV = CGF.EmitLValueForField( 5243 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5244 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5245 } 5246 Result.NewTask = NewTask; 5247 Result.TaskEntry = TaskEntry; 5248 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5249 Result.TDBase = TDBase; 5250 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5251 return Result; 5252 } 5253 5254 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5255 const OMPExecutableDirective &D, 5256 llvm::Function *TaskFunction, 5257 QualType SharedsTy, Address Shareds, 5258 const Expr *IfCond, 5259 const OMPTaskDataTy &Data) { 5260 if (!CGF.HaveInsertPoint()) 5261 return; 5262 5263 TaskResultTy Result = 5264 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5265 llvm::Value *NewTask = Result.NewTask; 5266 llvm::Function *TaskEntry = Result.TaskEntry; 5267 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5268 LValue TDBase = Result.TDBase; 5269 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5270 ASTContext &C = CGM.getContext(); 5271 // Process list of dependences. 5272 Address DependenciesArray = Address::invalid(); 5273 unsigned NumDependencies = Data.Dependences.size(); 5274 if (NumDependencies) { 5275 // Dependence kind for RTL. 5276 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5277 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5278 RecordDecl *KmpDependInfoRD; 5279 QualType FlagsTy = 5280 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5281 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5282 if (KmpDependInfoTy.isNull()) { 5283 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5284 KmpDependInfoRD->startDefinition(); 5285 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5286 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5287 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5288 KmpDependInfoRD->completeDefinition(); 5289 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5290 } else { 5291 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5292 } 5293 // Define type kmp_depend_info[<Dependences.size()>]; 5294 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5295 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5296 ArrayType::Normal, /*IndexTypeQuals=*/0); 5297 // kmp_depend_info[<Dependences.size()>] deps; 5298 DependenciesArray = 5299 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5300 for (unsigned I = 0; I < NumDependencies; ++I) { 5301 const Expr *E = Data.Dependences[I].second; 5302 LValue Addr = CGF.EmitLValue(E); 5303 llvm::Value *Size; 5304 QualType Ty = E->getType(); 5305 if (const auto *ASE = 5306 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5307 LValue UpAddrLVal = 5308 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5309 llvm::Value *UpAddr = 5310 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1); 5311 llvm::Value *LowIntPtr = 5312 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy); 5313 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5314 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5315 } else { 5316 Size = CGF.getTypeSize(Ty); 5317 } 5318 LValue Base = CGF.MakeAddrLValue( 5319 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5320 KmpDependInfoTy); 5321 // deps[i].base_addr = &<Dependences[i].second>; 5322 LValue BaseAddrLVal = CGF.EmitLValueForField( 5323 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5324 CGF.EmitStoreOfScalar( 5325 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy), 5326 BaseAddrLVal); 5327 // deps[i].len = sizeof(<Dependences[i].second>); 5328 LValue LenLVal = CGF.EmitLValueForField( 5329 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5330 CGF.EmitStoreOfScalar(Size, LenLVal); 5331 // deps[i].flags = <Dependences[i].first>; 5332 RTLDependenceKindTy DepKind; 5333 switch (Data.Dependences[I].first) { 5334 case OMPC_DEPEND_in: 5335 DepKind = DepIn; 5336 break; 5337 // Out and InOut dependencies must use the same code. 5338 case OMPC_DEPEND_out: 5339 case OMPC_DEPEND_inout: 5340 DepKind = DepInOut; 5341 break; 5342 case OMPC_DEPEND_mutexinoutset: 5343 DepKind = DepMutexInOutSet; 5344 break; 5345 case OMPC_DEPEND_source: 5346 case OMPC_DEPEND_sink: 5347 case OMPC_DEPEND_unknown: 5348 llvm_unreachable("Unknown task dependence type"); 5349 } 5350 LValue FlagsLVal = CGF.EmitLValueForField( 5351 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5352 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5353 FlagsLVal); 5354 } 5355 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5356 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5357 } 5358 5359 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5360 // libcall. 5361 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5362 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5363 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5364 // list is not empty 5365 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5366 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5367 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5368 llvm::Value *DepTaskArgs[7]; 5369 if (NumDependencies) { 5370 DepTaskArgs[0] = UpLoc; 5371 DepTaskArgs[1] = ThreadID; 5372 DepTaskArgs[2] = NewTask; 5373 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5374 DepTaskArgs[4] = DependenciesArray.getPointer(); 5375 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5376 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5377 } 5378 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5379 &TaskArgs, 5380 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5381 if (!Data.Tied) { 5382 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5383 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5384 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5385 } 5386 if (NumDependencies) { 5387 CGF.EmitRuntimeCall( 5388 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5389 } else { 5390 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5391 TaskArgs); 5392 } 5393 // Check if parent region is untied and build return for untied task; 5394 if (auto *Region = 5395 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5396 Region->emitUntiedSwitch(CGF); 5397 }; 5398 5399 llvm::Value *DepWaitTaskArgs[6]; 5400 if (NumDependencies) { 5401 DepWaitTaskArgs[0] = UpLoc; 5402 DepWaitTaskArgs[1] = ThreadID; 5403 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5404 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5405 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5406 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5407 } 5408 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5409 NumDependencies, &DepWaitTaskArgs, 5410 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5411 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5412 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5413 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5414 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5415 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5416 // is specified. 5417 if (NumDependencies) 5418 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5419 DepWaitTaskArgs); 5420 // Call proxy_task_entry(gtid, new_task); 5421 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5422 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5423 Action.Enter(CGF); 5424 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5425 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5426 OutlinedFnArgs); 5427 }; 5428 5429 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5430 // kmp_task_t *new_task); 5431 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5432 // kmp_task_t *new_task); 5433 RegionCodeGenTy RCG(CodeGen); 5434 CommonActionTy Action( 5435 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5436 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5437 RCG.setAction(Action); 5438 RCG(CGF); 5439 }; 5440 5441 if (IfCond) { 5442 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5443 } else { 5444 RegionCodeGenTy ThenRCG(ThenCodeGen); 5445 ThenRCG(CGF); 5446 } 5447 } 5448 5449 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5450 const OMPLoopDirective &D, 5451 llvm::Function *TaskFunction, 5452 QualType SharedsTy, Address Shareds, 5453 const Expr *IfCond, 5454 const OMPTaskDataTy &Data) { 5455 if (!CGF.HaveInsertPoint()) 5456 return; 5457 TaskResultTy Result = 5458 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5459 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5460 // libcall. 5461 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5462 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5463 // sched, kmp_uint64 grainsize, void *task_dup); 5464 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5465 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5466 llvm::Value *IfVal; 5467 if (IfCond) { 5468 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5469 /*isSigned=*/true); 5470 } else { 5471 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5472 } 5473 5474 LValue LBLVal = CGF.EmitLValueForField( 5475 Result.TDBase, 5476 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5477 const auto *LBVar = 5478 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5479 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(), 5480 /*IsInitializer=*/true); 5481 LValue UBLVal = CGF.EmitLValueForField( 5482 Result.TDBase, 5483 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5484 const auto *UBVar = 5485 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5486 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(), 5487 /*IsInitializer=*/true); 5488 LValue StLVal = CGF.EmitLValueForField( 5489 Result.TDBase, 5490 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5491 const auto *StVar = 5492 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5493 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(), 5494 /*IsInitializer=*/true); 5495 // Store reductions address. 5496 LValue RedLVal = CGF.EmitLValueForField( 5497 Result.TDBase, 5498 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5499 if (Data.Reductions) { 5500 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5501 } else { 5502 CGF.EmitNullInitialization(RedLVal.getAddress(), 5503 CGF.getContext().VoidPtrTy); 5504 } 5505 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5506 llvm::Value *TaskArgs[] = { 5507 UpLoc, 5508 ThreadID, 5509 Result.NewTask, 5510 IfVal, 5511 LBLVal.getPointer(), 5512 UBLVal.getPointer(), 5513 CGF.EmitLoadOfScalar(StLVal, Loc), 5514 llvm::ConstantInt::getSigned( 5515 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5516 llvm::ConstantInt::getSigned( 5517 CGF.IntTy, Data.Schedule.getPointer() 5518 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5519 : NoSchedule), 5520 Data.Schedule.getPointer() 5521 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5522 /*isSigned=*/false) 5523 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5524 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5525 Result.TaskDupFn, CGF.VoidPtrTy) 5526 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5527 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5528 } 5529 5530 /// Emit reduction operation for each element of array (required for 5531 /// array sections) LHS op = RHS. 5532 /// \param Type Type of array. 5533 /// \param LHSVar Variable on the left side of the reduction operation 5534 /// (references element of array in original variable). 5535 /// \param RHSVar Variable on the right side of the reduction operation 5536 /// (references element of array in original variable). 5537 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5538 /// RHSVar. 5539 static void EmitOMPAggregateReduction( 5540 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5541 const VarDecl *RHSVar, 5542 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5543 const Expr *, const Expr *)> &RedOpGen, 5544 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5545 const Expr *UpExpr = nullptr) { 5546 // Perform element-by-element initialization. 5547 QualType ElementTy; 5548 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5549 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5550 5551 // Drill down to the base element type on both arrays. 5552 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5553 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5554 5555 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5556 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5557 // Cast from pointer to array type to pointer to single element. 5558 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5559 // The basic structure here is a while-do loop. 5560 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5561 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5562 llvm::Value *IsEmpty = 5563 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5564 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5565 5566 // Enter the loop body, making that address the current address. 5567 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5568 CGF.EmitBlock(BodyBB); 5569 5570 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5571 5572 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5573 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5574 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5575 Address RHSElementCurrent = 5576 Address(RHSElementPHI, 5577 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5578 5579 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5580 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5581 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5582 Address LHSElementCurrent = 5583 Address(LHSElementPHI, 5584 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5585 5586 // Emit copy. 5587 CodeGenFunction::OMPPrivateScope Scope(CGF); 5588 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5589 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5590 Scope.Privatize(); 5591 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5592 Scope.ForceCleanup(); 5593 5594 // Shift the address forward by one element. 5595 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5596 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5597 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5598 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5599 // Check whether we've reached the end. 5600 llvm::Value *Done = 5601 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5602 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5603 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5604 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5605 5606 // Done. 5607 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5608 } 5609 5610 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5611 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5612 /// UDR combiner function. 5613 static void emitReductionCombiner(CodeGenFunction &CGF, 5614 const Expr *ReductionOp) { 5615 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5616 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5617 if (const auto *DRE = 5618 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5619 if (const auto *DRD = 5620 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5621 std::pair<llvm::Function *, llvm::Function *> Reduction = 5622 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5623 RValue Func = RValue::get(Reduction.first); 5624 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5625 CGF.EmitIgnoredExpr(ReductionOp); 5626 return; 5627 } 5628 CGF.EmitIgnoredExpr(ReductionOp); 5629 } 5630 5631 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5632 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5633 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5634 ArrayRef<const Expr *> ReductionOps) { 5635 ASTContext &C = CGM.getContext(); 5636 5637 // void reduction_func(void *LHSArg, void *RHSArg); 5638 FunctionArgList Args; 5639 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5640 ImplicitParamDecl::Other); 5641 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5642 ImplicitParamDecl::Other); 5643 Args.push_back(&LHSArg); 5644 Args.push_back(&RHSArg); 5645 const auto &CGFI = 5646 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5647 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5648 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5649 llvm::GlobalValue::InternalLinkage, Name, 5650 &CGM.getModule()); 5651 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5652 Fn->setDoesNotRecurse(); 5653 CodeGenFunction CGF(CGM); 5654 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5655 5656 // Dst = (void*[n])(LHSArg); 5657 // Src = (void*[n])(RHSArg); 5658 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5659 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5660 ArgsType), CGF.getPointerAlign()); 5661 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5662 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5663 ArgsType), CGF.getPointerAlign()); 5664 5665 // ... 5666 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5667 // ... 5668 CodeGenFunction::OMPPrivateScope Scope(CGF); 5669 auto IPriv = Privates.begin(); 5670 unsigned Idx = 0; 5671 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5672 const auto *RHSVar = 5673 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5674 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5675 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5676 }); 5677 const auto *LHSVar = 5678 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5679 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5680 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5681 }); 5682 QualType PrivTy = (*IPriv)->getType(); 5683 if (PrivTy->isVariablyModifiedType()) { 5684 // Get array size and emit VLA type. 5685 ++Idx; 5686 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5687 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5688 const VariableArrayType *VLA = 5689 CGF.getContext().getAsVariableArrayType(PrivTy); 5690 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5691 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5692 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5693 CGF.EmitVariablyModifiedType(PrivTy); 5694 } 5695 } 5696 Scope.Privatize(); 5697 IPriv = Privates.begin(); 5698 auto ILHS = LHSExprs.begin(); 5699 auto IRHS = RHSExprs.begin(); 5700 for (const Expr *E : ReductionOps) { 5701 if ((*IPriv)->getType()->isArrayType()) { 5702 // Emit reduction for array section. 5703 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5704 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5705 EmitOMPAggregateReduction( 5706 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5707 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5708 emitReductionCombiner(CGF, E); 5709 }); 5710 } else { 5711 // Emit reduction for array subscript or single variable. 5712 emitReductionCombiner(CGF, E); 5713 } 5714 ++IPriv; 5715 ++ILHS; 5716 ++IRHS; 5717 } 5718 Scope.ForceCleanup(); 5719 CGF.FinishFunction(); 5720 return Fn; 5721 } 5722 5723 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5724 const Expr *ReductionOp, 5725 const Expr *PrivateRef, 5726 const DeclRefExpr *LHS, 5727 const DeclRefExpr *RHS) { 5728 if (PrivateRef->getType()->isArrayType()) { 5729 // Emit reduction for array section. 5730 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5731 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5732 EmitOMPAggregateReduction( 5733 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5734 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5735 emitReductionCombiner(CGF, ReductionOp); 5736 }); 5737 } else { 5738 // Emit reduction for array subscript or single variable. 5739 emitReductionCombiner(CGF, ReductionOp); 5740 } 5741 } 5742 5743 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5744 ArrayRef<const Expr *> Privates, 5745 ArrayRef<const Expr *> LHSExprs, 5746 ArrayRef<const Expr *> RHSExprs, 5747 ArrayRef<const Expr *> ReductionOps, 5748 ReductionOptionsTy Options) { 5749 if (!CGF.HaveInsertPoint()) 5750 return; 5751 5752 bool WithNowait = Options.WithNowait; 5753 bool SimpleReduction = Options.SimpleReduction; 5754 5755 // Next code should be emitted for reduction: 5756 // 5757 // static kmp_critical_name lock = { 0 }; 5758 // 5759 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5760 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5761 // ... 5762 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5763 // *(Type<n>-1*)rhs[<n>-1]); 5764 // } 5765 // 5766 // ... 5767 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5768 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5769 // RedList, reduce_func, &<lock>)) { 5770 // case 1: 5771 // ... 5772 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5773 // ... 5774 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5775 // break; 5776 // case 2: 5777 // ... 5778 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5779 // ... 5780 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5781 // break; 5782 // default:; 5783 // } 5784 // 5785 // if SimpleReduction is true, only the next code is generated: 5786 // ... 5787 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5788 // ... 5789 5790 ASTContext &C = CGM.getContext(); 5791 5792 if (SimpleReduction) { 5793 CodeGenFunction::RunCleanupsScope Scope(CGF); 5794 auto IPriv = Privates.begin(); 5795 auto ILHS = LHSExprs.begin(); 5796 auto IRHS = RHSExprs.begin(); 5797 for (const Expr *E : ReductionOps) { 5798 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5799 cast<DeclRefExpr>(*IRHS)); 5800 ++IPriv; 5801 ++ILHS; 5802 ++IRHS; 5803 } 5804 return; 5805 } 5806 5807 // 1. Build a list of reduction variables. 5808 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5809 auto Size = RHSExprs.size(); 5810 for (const Expr *E : Privates) { 5811 if (E->getType()->isVariablyModifiedType()) 5812 // Reserve place for array size. 5813 ++Size; 5814 } 5815 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5816 QualType ReductionArrayTy = 5817 C.getConstantArrayType(C.VoidPtrTy, ArraySize, ArrayType::Normal, 5818 /*IndexTypeQuals=*/0); 5819 Address ReductionList = 5820 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5821 auto IPriv = Privates.begin(); 5822 unsigned Idx = 0; 5823 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5824 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5825 CGF.Builder.CreateStore( 5826 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5827 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), 5828 Elem); 5829 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5830 // Store array size. 5831 ++Idx; 5832 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5833 llvm::Value *Size = CGF.Builder.CreateIntCast( 5834 CGF.getVLASize( 5835 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5836 .NumElts, 5837 CGF.SizeTy, /*isSigned=*/false); 5838 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5839 Elem); 5840 } 5841 } 5842 5843 // 2. Emit reduce_func(). 5844 llvm::Function *ReductionFn = emitReductionFunction( 5845 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5846 LHSExprs, RHSExprs, ReductionOps); 5847 5848 // 3. Create static kmp_critical_name lock = { 0 }; 5849 std::string Name = getName({"reduction"}); 5850 llvm::Value *Lock = getCriticalRegionLock(Name); 5851 5852 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5853 // RedList, reduce_func, &<lock>); 5854 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5855 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5856 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5857 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5858 ReductionList.getPointer(), CGF.VoidPtrTy); 5859 llvm::Value *Args[] = { 5860 IdentTLoc, // ident_t *<loc> 5861 ThreadId, // i32 <gtid> 5862 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5863 ReductionArrayTySize, // size_type sizeof(RedList) 5864 RL, // void *RedList 5865 ReductionFn, // void (*) (void *, void *) <reduce_func> 5866 Lock // kmp_critical_name *&<lock> 5867 }; 5868 llvm::Value *Res = CGF.EmitRuntimeCall( 5869 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5870 : OMPRTL__kmpc_reduce), 5871 Args); 5872 5873 // 5. Build switch(res) 5874 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5875 llvm::SwitchInst *SwInst = 5876 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5877 5878 // 6. Build case 1: 5879 // ... 5880 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5881 // ... 5882 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5883 // break; 5884 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5885 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5886 CGF.EmitBlock(Case1BB); 5887 5888 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5889 llvm::Value *EndArgs[] = { 5890 IdentTLoc, // ident_t *<loc> 5891 ThreadId, // i32 <gtid> 5892 Lock // kmp_critical_name *&<lock> 5893 }; 5894 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5895 CodeGenFunction &CGF, PrePostActionTy &Action) { 5896 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5897 auto IPriv = Privates.begin(); 5898 auto ILHS = LHSExprs.begin(); 5899 auto IRHS = RHSExprs.begin(); 5900 for (const Expr *E : ReductionOps) { 5901 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5902 cast<DeclRefExpr>(*IRHS)); 5903 ++IPriv; 5904 ++ILHS; 5905 ++IRHS; 5906 } 5907 }; 5908 RegionCodeGenTy RCG(CodeGen); 5909 CommonActionTy Action( 5910 nullptr, llvm::None, 5911 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5912 : OMPRTL__kmpc_end_reduce), 5913 EndArgs); 5914 RCG.setAction(Action); 5915 RCG(CGF); 5916 5917 CGF.EmitBranch(DefaultBB); 5918 5919 // 7. Build case 2: 5920 // ... 5921 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5922 // ... 5923 // break; 5924 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5925 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5926 CGF.EmitBlock(Case2BB); 5927 5928 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5929 CodeGenFunction &CGF, PrePostActionTy &Action) { 5930 auto ILHS = LHSExprs.begin(); 5931 auto IRHS = RHSExprs.begin(); 5932 auto IPriv = Privates.begin(); 5933 for (const Expr *E : ReductionOps) { 5934 const Expr *XExpr = nullptr; 5935 const Expr *EExpr = nullptr; 5936 const Expr *UpExpr = nullptr; 5937 BinaryOperatorKind BO = BO_Comma; 5938 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5939 if (BO->getOpcode() == BO_Assign) { 5940 XExpr = BO->getLHS(); 5941 UpExpr = BO->getRHS(); 5942 } 5943 } 5944 // Try to emit update expression as a simple atomic. 5945 const Expr *RHSExpr = UpExpr; 5946 if (RHSExpr) { 5947 // Analyze RHS part of the whole expression. 5948 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5949 RHSExpr->IgnoreParenImpCasts())) { 5950 // If this is a conditional operator, analyze its condition for 5951 // min/max reduction operator. 5952 RHSExpr = ACO->getCond(); 5953 } 5954 if (const auto *BORHS = 5955 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5956 EExpr = BORHS->getRHS(); 5957 BO = BORHS->getOpcode(); 5958 } 5959 } 5960 if (XExpr) { 5961 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5962 auto &&AtomicRedGen = [BO, VD, 5963 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5964 const Expr *EExpr, const Expr *UpExpr) { 5965 LValue X = CGF.EmitLValue(XExpr); 5966 RValue E; 5967 if (EExpr) 5968 E = CGF.EmitAnyExpr(EExpr); 5969 CGF.EmitOMPAtomicSimpleUpdateExpr( 5970 X, E, BO, /*IsXLHSInRHSPart=*/true, 5971 llvm::AtomicOrdering::Monotonic, Loc, 5972 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5973 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5974 PrivateScope.addPrivate( 5975 VD, [&CGF, VD, XRValue, Loc]() { 5976 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5977 CGF.emitOMPSimpleStore( 5978 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5979 VD->getType().getNonReferenceType(), Loc); 5980 return LHSTemp; 5981 }); 5982 (void)PrivateScope.Privatize(); 5983 return CGF.EmitAnyExpr(UpExpr); 5984 }); 5985 }; 5986 if ((*IPriv)->getType()->isArrayType()) { 5987 // Emit atomic reduction for array section. 5988 const auto *RHSVar = 5989 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5990 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5991 AtomicRedGen, XExpr, EExpr, UpExpr); 5992 } else { 5993 // Emit atomic reduction for array subscript or single variable. 5994 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5995 } 5996 } else { 5997 // Emit as a critical region. 5998 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5999 const Expr *, const Expr *) { 6000 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6001 std::string Name = RT.getName({"atomic_reduction"}); 6002 RT.emitCriticalRegion( 6003 CGF, Name, 6004 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 6005 Action.Enter(CGF); 6006 emitReductionCombiner(CGF, E); 6007 }, 6008 Loc); 6009 }; 6010 if ((*IPriv)->getType()->isArrayType()) { 6011 const auto *LHSVar = 6012 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 6013 const auto *RHSVar = 6014 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 6015 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 6016 CritRedGen); 6017 } else { 6018 CritRedGen(CGF, nullptr, nullptr, nullptr); 6019 } 6020 } 6021 ++ILHS; 6022 ++IRHS; 6023 ++IPriv; 6024 } 6025 }; 6026 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 6027 if (!WithNowait) { 6028 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 6029 llvm::Value *EndArgs[] = { 6030 IdentTLoc, // ident_t *<loc> 6031 ThreadId, // i32 <gtid> 6032 Lock // kmp_critical_name *&<lock> 6033 }; 6034 CommonActionTy Action(nullptr, llvm::None, 6035 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 6036 EndArgs); 6037 AtomicRCG.setAction(Action); 6038 AtomicRCG(CGF); 6039 } else { 6040 AtomicRCG(CGF); 6041 } 6042 6043 CGF.EmitBranch(DefaultBB); 6044 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 6045 } 6046 6047 /// Generates unique name for artificial threadprivate variables. 6048 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 6049 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 6050 const Expr *Ref) { 6051 SmallString<256> Buffer; 6052 llvm::raw_svector_ostream Out(Buffer); 6053 const clang::DeclRefExpr *DE; 6054 const VarDecl *D = ::getBaseDecl(Ref, DE); 6055 if (!D) 6056 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 6057 D = D->getCanonicalDecl(); 6058 std::string Name = CGM.getOpenMPRuntime().getName( 6059 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 6060 Out << Prefix << Name << "_" 6061 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 6062 return Out.str(); 6063 } 6064 6065 /// Emits reduction initializer function: 6066 /// \code 6067 /// void @.red_init(void* %arg) { 6068 /// %0 = bitcast void* %arg to <type>* 6069 /// store <type> <init>, <type>* %0 6070 /// ret void 6071 /// } 6072 /// \endcode 6073 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6074 SourceLocation Loc, 6075 ReductionCodeGen &RCG, unsigned N) { 6076 ASTContext &C = CGM.getContext(); 6077 FunctionArgList Args; 6078 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6079 ImplicitParamDecl::Other); 6080 Args.emplace_back(&Param); 6081 const auto &FnInfo = 6082 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6083 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6084 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6085 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6086 Name, &CGM.getModule()); 6087 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6088 Fn->setDoesNotRecurse(); 6089 CodeGenFunction CGF(CGM); 6090 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6091 Address PrivateAddr = CGF.EmitLoadOfPointer( 6092 CGF.GetAddrOfLocalVar(&Param), 6093 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6094 llvm::Value *Size = nullptr; 6095 // If the size of the reduction item is non-constant, load it from global 6096 // threadprivate variable. 6097 if (RCG.getSizes(N).second) { 6098 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6099 CGF, CGM.getContext().getSizeType(), 6100 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6101 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6102 CGM.getContext().getSizeType(), Loc); 6103 } 6104 RCG.emitAggregateType(CGF, N, Size); 6105 LValue SharedLVal; 6106 // If initializer uses initializer from declare reduction construct, emit a 6107 // pointer to the address of the original reduction item (reuired by reduction 6108 // initializer) 6109 if (RCG.usesReductionInitializer(N)) { 6110 Address SharedAddr = 6111 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6112 CGF, CGM.getContext().VoidPtrTy, 6113 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6114 SharedAddr = CGF.EmitLoadOfPointer( 6115 SharedAddr, 6116 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6117 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6118 } else { 6119 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6120 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6121 CGM.getContext().VoidPtrTy); 6122 } 6123 // Emit the initializer: 6124 // %0 = bitcast void* %arg to <type>* 6125 // store <type> <init>, <type>* %0 6126 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6127 [](CodeGenFunction &) { return false; }); 6128 CGF.FinishFunction(); 6129 return Fn; 6130 } 6131 6132 /// Emits reduction combiner function: 6133 /// \code 6134 /// void @.red_comb(void* %arg0, void* %arg1) { 6135 /// %lhs = bitcast void* %arg0 to <type>* 6136 /// %rhs = bitcast void* %arg1 to <type>* 6137 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6138 /// store <type> %2, <type>* %lhs 6139 /// ret void 6140 /// } 6141 /// \endcode 6142 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6143 SourceLocation Loc, 6144 ReductionCodeGen &RCG, unsigned N, 6145 const Expr *ReductionOp, 6146 const Expr *LHS, const Expr *RHS, 6147 const Expr *PrivateRef) { 6148 ASTContext &C = CGM.getContext(); 6149 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6150 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6151 FunctionArgList Args; 6152 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6153 C.VoidPtrTy, ImplicitParamDecl::Other); 6154 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6155 ImplicitParamDecl::Other); 6156 Args.emplace_back(&ParamInOut); 6157 Args.emplace_back(&ParamIn); 6158 const auto &FnInfo = 6159 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6160 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6161 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6162 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6163 Name, &CGM.getModule()); 6164 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6165 Fn->setDoesNotRecurse(); 6166 CodeGenFunction CGF(CGM); 6167 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6168 llvm::Value *Size = nullptr; 6169 // If the size of the reduction item is non-constant, load it from global 6170 // threadprivate variable. 6171 if (RCG.getSizes(N).second) { 6172 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6173 CGF, CGM.getContext().getSizeType(), 6174 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6175 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6176 CGM.getContext().getSizeType(), Loc); 6177 } 6178 RCG.emitAggregateType(CGF, N, Size); 6179 // Remap lhs and rhs variables to the addresses of the function arguments. 6180 // %lhs = bitcast void* %arg0 to <type>* 6181 // %rhs = bitcast void* %arg1 to <type>* 6182 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6183 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6184 // Pull out the pointer to the variable. 6185 Address PtrAddr = CGF.EmitLoadOfPointer( 6186 CGF.GetAddrOfLocalVar(&ParamInOut), 6187 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6188 return CGF.Builder.CreateElementBitCast( 6189 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6190 }); 6191 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6192 // Pull out the pointer to the variable. 6193 Address PtrAddr = CGF.EmitLoadOfPointer( 6194 CGF.GetAddrOfLocalVar(&ParamIn), 6195 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6196 return CGF.Builder.CreateElementBitCast( 6197 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6198 }); 6199 PrivateScope.Privatize(); 6200 // Emit the combiner body: 6201 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6202 // store <type> %2, <type>* %lhs 6203 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6204 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6205 cast<DeclRefExpr>(RHS)); 6206 CGF.FinishFunction(); 6207 return Fn; 6208 } 6209 6210 /// Emits reduction finalizer function: 6211 /// \code 6212 /// void @.red_fini(void* %arg) { 6213 /// %0 = bitcast void* %arg to <type>* 6214 /// <destroy>(<type>* %0) 6215 /// ret void 6216 /// } 6217 /// \endcode 6218 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6219 SourceLocation Loc, 6220 ReductionCodeGen &RCG, unsigned N) { 6221 if (!RCG.needCleanups(N)) 6222 return nullptr; 6223 ASTContext &C = CGM.getContext(); 6224 FunctionArgList Args; 6225 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6226 ImplicitParamDecl::Other); 6227 Args.emplace_back(&Param); 6228 const auto &FnInfo = 6229 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6230 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6231 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6232 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6233 Name, &CGM.getModule()); 6234 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6235 Fn->setDoesNotRecurse(); 6236 CodeGenFunction CGF(CGM); 6237 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6238 Address PrivateAddr = CGF.EmitLoadOfPointer( 6239 CGF.GetAddrOfLocalVar(&Param), 6240 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6241 llvm::Value *Size = nullptr; 6242 // If the size of the reduction item is non-constant, load it from global 6243 // threadprivate variable. 6244 if (RCG.getSizes(N).second) { 6245 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6246 CGF, CGM.getContext().getSizeType(), 6247 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6248 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6249 CGM.getContext().getSizeType(), Loc); 6250 } 6251 RCG.emitAggregateType(CGF, N, Size); 6252 // Emit the finalizer body: 6253 // <destroy>(<type>* %0) 6254 RCG.emitCleanups(CGF, N, PrivateAddr); 6255 CGF.FinishFunction(); 6256 return Fn; 6257 } 6258 6259 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6260 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6261 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6262 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6263 return nullptr; 6264 6265 // Build typedef struct: 6266 // kmp_task_red_input { 6267 // void *reduce_shar; // shared reduction item 6268 // size_t reduce_size; // size of data item 6269 // void *reduce_init; // data initialization routine 6270 // void *reduce_fini; // data finalization routine 6271 // void *reduce_comb; // data combiner routine 6272 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6273 // } kmp_task_red_input_t; 6274 ASTContext &C = CGM.getContext(); 6275 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6276 RD->startDefinition(); 6277 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6278 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6279 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6280 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6281 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6282 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6283 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6284 RD->completeDefinition(); 6285 QualType RDType = C.getRecordType(RD); 6286 unsigned Size = Data.ReductionVars.size(); 6287 llvm::APInt ArraySize(/*numBits=*/64, Size); 6288 QualType ArrayRDType = C.getConstantArrayType( 6289 RDType, ArraySize, ArrayType::Normal, /*IndexTypeQuals=*/0); 6290 // kmp_task_red_input_t .rd_input.[Size]; 6291 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6292 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6293 Data.ReductionOps); 6294 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6295 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6296 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6297 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6298 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6299 TaskRedInput.getPointer(), Idxs, 6300 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6301 ".rd_input.gep."); 6302 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6303 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6304 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6305 RCG.emitSharedLValue(CGF, Cnt); 6306 llvm::Value *CastedShared = 6307 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer()); 6308 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6309 RCG.emitAggregateType(CGF, Cnt); 6310 llvm::Value *SizeValInChars; 6311 llvm::Value *SizeVal; 6312 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6313 // We use delayed creation/initialization for VLAs, array sections and 6314 // custom reduction initializations. It is required because runtime does not 6315 // provide the way to pass the sizes of VLAs/array sections to 6316 // initializer/combiner/finalizer functions and does not pass the pointer to 6317 // original reduction item to the initializer. Instead threadprivate global 6318 // variables are used to store these values and use them in the functions. 6319 bool DelayedCreation = !!SizeVal; 6320 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6321 /*isSigned=*/false); 6322 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6323 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6324 // ElemLVal.reduce_init = init; 6325 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6326 llvm::Value *InitAddr = 6327 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6328 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6329 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6330 // ElemLVal.reduce_fini = fini; 6331 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6332 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6333 llvm::Value *FiniAddr = Fini 6334 ? CGF.EmitCastToVoidPtr(Fini) 6335 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6336 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6337 // ElemLVal.reduce_comb = comb; 6338 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6339 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6340 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6341 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6342 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6343 // ElemLVal.flags = 0; 6344 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6345 if (DelayedCreation) { 6346 CGF.EmitStoreOfScalar( 6347 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6348 FlagsLVal); 6349 } else 6350 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType()); 6351 } 6352 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6353 // *data); 6354 llvm::Value *Args[] = { 6355 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6356 /*isSigned=*/true), 6357 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6358 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6359 CGM.VoidPtrTy)}; 6360 return CGF.EmitRuntimeCall( 6361 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6362 } 6363 6364 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6365 SourceLocation Loc, 6366 ReductionCodeGen &RCG, 6367 unsigned N) { 6368 auto Sizes = RCG.getSizes(N); 6369 // Emit threadprivate global variable if the type is non-constant 6370 // (Sizes.second = nullptr). 6371 if (Sizes.second) { 6372 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6373 /*isSigned=*/false); 6374 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6375 CGF, CGM.getContext().getSizeType(), 6376 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6377 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6378 } 6379 // Store address of the original reduction item if custom initializer is used. 6380 if (RCG.usesReductionInitializer(N)) { 6381 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6382 CGF, CGM.getContext().VoidPtrTy, 6383 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6384 CGF.Builder.CreateStore( 6385 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6386 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy), 6387 SharedAddr, /*IsVolatile=*/false); 6388 } 6389 } 6390 6391 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6392 SourceLocation Loc, 6393 llvm::Value *ReductionsPtr, 6394 LValue SharedLVal) { 6395 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6396 // *d); 6397 llvm::Value *Args[] = { 6398 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6399 /*isSigned=*/true), 6400 ReductionsPtr, 6401 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(), 6402 CGM.VoidPtrTy)}; 6403 return Address( 6404 CGF.EmitRuntimeCall( 6405 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6406 SharedLVal.getAlignment()); 6407 } 6408 6409 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6410 SourceLocation Loc) { 6411 if (!CGF.HaveInsertPoint()) 6412 return; 6413 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6414 // global_tid); 6415 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6416 // Ignore return result until untied tasks are supported. 6417 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6418 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6419 Region->emitUntiedSwitch(CGF); 6420 } 6421 6422 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6423 OpenMPDirectiveKind InnerKind, 6424 const RegionCodeGenTy &CodeGen, 6425 bool HasCancel) { 6426 if (!CGF.HaveInsertPoint()) 6427 return; 6428 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6429 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6430 } 6431 6432 namespace { 6433 enum RTCancelKind { 6434 CancelNoreq = 0, 6435 CancelParallel = 1, 6436 CancelLoop = 2, 6437 CancelSections = 3, 6438 CancelTaskgroup = 4 6439 }; 6440 } // anonymous namespace 6441 6442 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6443 RTCancelKind CancelKind = CancelNoreq; 6444 if (CancelRegion == OMPD_parallel) 6445 CancelKind = CancelParallel; 6446 else if (CancelRegion == OMPD_for) 6447 CancelKind = CancelLoop; 6448 else if (CancelRegion == OMPD_sections) 6449 CancelKind = CancelSections; 6450 else { 6451 assert(CancelRegion == OMPD_taskgroup); 6452 CancelKind = CancelTaskgroup; 6453 } 6454 return CancelKind; 6455 } 6456 6457 void CGOpenMPRuntime::emitCancellationPointCall( 6458 CodeGenFunction &CGF, SourceLocation Loc, 6459 OpenMPDirectiveKind CancelRegion) { 6460 if (!CGF.HaveInsertPoint()) 6461 return; 6462 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6463 // global_tid, kmp_int32 cncl_kind); 6464 if (auto *OMPRegionInfo = 6465 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6466 // For 'cancellation point taskgroup', the task region info may not have a 6467 // cancel. This may instead happen in another adjacent task. 6468 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6469 llvm::Value *Args[] = { 6470 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6471 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6472 // Ignore return result until untied tasks are supported. 6473 llvm::Value *Result = CGF.EmitRuntimeCall( 6474 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6475 // if (__kmpc_cancellationpoint()) { 6476 // exit from construct; 6477 // } 6478 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6479 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6480 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6481 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6482 CGF.EmitBlock(ExitBB); 6483 // exit from construct; 6484 CodeGenFunction::JumpDest CancelDest = 6485 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6486 CGF.EmitBranchThroughCleanup(CancelDest); 6487 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6488 } 6489 } 6490 } 6491 6492 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6493 const Expr *IfCond, 6494 OpenMPDirectiveKind CancelRegion) { 6495 if (!CGF.HaveInsertPoint()) 6496 return; 6497 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6498 // kmp_int32 cncl_kind); 6499 if (auto *OMPRegionInfo = 6500 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6501 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6502 PrePostActionTy &) { 6503 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6504 llvm::Value *Args[] = { 6505 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6506 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6507 // Ignore return result until untied tasks are supported. 6508 llvm::Value *Result = CGF.EmitRuntimeCall( 6509 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6510 // if (__kmpc_cancel()) { 6511 // exit from construct; 6512 // } 6513 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6514 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6515 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6516 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6517 CGF.EmitBlock(ExitBB); 6518 // exit from construct; 6519 CodeGenFunction::JumpDest CancelDest = 6520 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6521 CGF.EmitBranchThroughCleanup(CancelDest); 6522 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6523 }; 6524 if (IfCond) { 6525 emitOMPIfClause(CGF, IfCond, ThenGen, 6526 [](CodeGenFunction &, PrePostActionTy &) {}); 6527 } else { 6528 RegionCodeGenTy ThenRCG(ThenGen); 6529 ThenRCG(CGF); 6530 } 6531 } 6532 } 6533 6534 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6535 const OMPExecutableDirective &D, StringRef ParentName, 6536 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6537 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6538 assert(!ParentName.empty() && "Invalid target region parent name!"); 6539 HasEmittedTargetRegion = true; 6540 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6541 IsOffloadEntry, CodeGen); 6542 } 6543 6544 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6545 const OMPExecutableDirective &D, StringRef ParentName, 6546 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6547 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6548 // Create a unique name for the entry function using the source location 6549 // information of the current target region. The name will be something like: 6550 // 6551 // __omp_offloading_DD_FFFF_PP_lBB 6552 // 6553 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6554 // mangled name of the function that encloses the target region and BB is the 6555 // line number of the target region. 6556 6557 unsigned DeviceID; 6558 unsigned FileID; 6559 unsigned Line; 6560 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6561 Line); 6562 SmallString<64> EntryFnName; 6563 { 6564 llvm::raw_svector_ostream OS(EntryFnName); 6565 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6566 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6567 } 6568 6569 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6570 6571 CodeGenFunction CGF(CGM, true); 6572 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6573 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6574 6575 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 6576 6577 // If this target outline function is not an offload entry, we don't need to 6578 // register it. 6579 if (!IsOffloadEntry) 6580 return; 6581 6582 // The target region ID is used by the runtime library to identify the current 6583 // target region, so it only has to be unique and not necessarily point to 6584 // anything. It could be the pointer to the outlined function that implements 6585 // the target region, but we aren't using that so that the compiler doesn't 6586 // need to keep that, and could therefore inline the host function if proven 6587 // worthwhile during optimization. In the other hand, if emitting code for the 6588 // device, the ID has to be the function address so that it can retrieved from 6589 // the offloading entry and launched by the runtime library. We also mark the 6590 // outlined function to have external linkage in case we are emitting code for 6591 // the device, because these functions will be entry points to the device. 6592 6593 if (CGM.getLangOpts().OpenMPIsDevice) { 6594 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6595 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6596 OutlinedFn->setDSOLocal(false); 6597 } else { 6598 std::string Name = getName({EntryFnName, "region_id"}); 6599 OutlinedFnID = new llvm::GlobalVariable( 6600 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6601 llvm::GlobalValue::WeakAnyLinkage, 6602 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6603 } 6604 6605 // Register the information for the entry associated with this target region. 6606 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6607 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6608 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6609 } 6610 6611 /// Checks if the expression is constant or does not have non-trivial function 6612 /// calls. 6613 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6614 // We can skip constant expressions. 6615 // We can skip expressions with trivial calls or simple expressions. 6616 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6617 !E->hasNonTrivialCall(Ctx)) && 6618 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6619 } 6620 6621 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6622 const Stmt *Body) { 6623 const Stmt *Child = Body->IgnoreContainers(); 6624 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6625 Child = nullptr; 6626 for (const Stmt *S : C->body()) { 6627 if (const auto *E = dyn_cast<Expr>(S)) { 6628 if (isTrivial(Ctx, E)) 6629 continue; 6630 } 6631 // Some of the statements can be ignored. 6632 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6633 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6634 continue; 6635 // Analyze declarations. 6636 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6637 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6638 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6639 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6640 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6641 isa<UsingDirectiveDecl>(D) || 6642 isa<OMPDeclareReductionDecl>(D) || 6643 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6644 return true; 6645 const auto *VD = dyn_cast<VarDecl>(D); 6646 if (!VD) 6647 return false; 6648 return VD->isConstexpr() || 6649 ((VD->getType().isTrivialType(Ctx) || 6650 VD->getType()->isReferenceType()) && 6651 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6652 })) 6653 continue; 6654 } 6655 // Found multiple children - cannot get the one child only. 6656 if (Child) 6657 return nullptr; 6658 Child = S; 6659 } 6660 if (Child) 6661 Child = Child->IgnoreContainers(); 6662 } 6663 return Child; 6664 } 6665 6666 /// Emit the number of teams for a target directive. Inspect the num_teams 6667 /// clause associated with a teams construct combined or closely nested 6668 /// with the target directive. 6669 /// 6670 /// Emit a team of size one for directives such as 'target parallel' that 6671 /// have no associated teams construct. 6672 /// 6673 /// Otherwise, return nullptr. 6674 static llvm::Value * 6675 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6676 const OMPExecutableDirective &D) { 6677 assert(!CGF.getLangOpts().OpenMPIsDevice && 6678 "Clauses associated with the teams directive expected to be emitted " 6679 "only for the host!"); 6680 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6681 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6682 "Expected target-based executable directive."); 6683 CGBuilderTy &Bld = CGF.Builder; 6684 switch (DirectiveKind) { 6685 case OMPD_target: { 6686 const auto *CS = D.getInnermostCapturedStmt(); 6687 const auto *Body = 6688 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6689 const Stmt *ChildStmt = 6690 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6691 if (const auto *NestedDir = 6692 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6693 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6694 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6695 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6696 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6697 const Expr *NumTeams = 6698 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6699 llvm::Value *NumTeamsVal = 6700 CGF.EmitScalarExpr(NumTeams, 6701 /*IgnoreResultAssign*/ true); 6702 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6703 /*isSigned=*/true); 6704 } 6705 return Bld.getInt32(0); 6706 } 6707 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6708 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6709 return Bld.getInt32(1); 6710 return Bld.getInt32(0); 6711 } 6712 return nullptr; 6713 } 6714 case OMPD_target_teams: 6715 case OMPD_target_teams_distribute: 6716 case OMPD_target_teams_distribute_simd: 6717 case OMPD_target_teams_distribute_parallel_for: 6718 case OMPD_target_teams_distribute_parallel_for_simd: { 6719 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6720 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6721 const Expr *NumTeams = 6722 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6723 llvm::Value *NumTeamsVal = 6724 CGF.EmitScalarExpr(NumTeams, 6725 /*IgnoreResultAssign*/ true); 6726 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6727 /*isSigned=*/true); 6728 } 6729 return Bld.getInt32(0); 6730 } 6731 case OMPD_target_parallel: 6732 case OMPD_target_parallel_for: 6733 case OMPD_target_parallel_for_simd: 6734 case OMPD_target_simd: 6735 return Bld.getInt32(1); 6736 case OMPD_parallel: 6737 case OMPD_for: 6738 case OMPD_parallel_for: 6739 case OMPD_parallel_sections: 6740 case OMPD_for_simd: 6741 case OMPD_parallel_for_simd: 6742 case OMPD_cancel: 6743 case OMPD_cancellation_point: 6744 case OMPD_ordered: 6745 case OMPD_threadprivate: 6746 case OMPD_allocate: 6747 case OMPD_task: 6748 case OMPD_simd: 6749 case OMPD_sections: 6750 case OMPD_section: 6751 case OMPD_single: 6752 case OMPD_master: 6753 case OMPD_critical: 6754 case OMPD_taskyield: 6755 case OMPD_barrier: 6756 case OMPD_taskwait: 6757 case OMPD_taskgroup: 6758 case OMPD_atomic: 6759 case OMPD_flush: 6760 case OMPD_teams: 6761 case OMPD_target_data: 6762 case OMPD_target_exit_data: 6763 case OMPD_target_enter_data: 6764 case OMPD_distribute: 6765 case OMPD_distribute_simd: 6766 case OMPD_distribute_parallel_for: 6767 case OMPD_distribute_parallel_for_simd: 6768 case OMPD_teams_distribute: 6769 case OMPD_teams_distribute_simd: 6770 case OMPD_teams_distribute_parallel_for: 6771 case OMPD_teams_distribute_parallel_for_simd: 6772 case OMPD_target_update: 6773 case OMPD_declare_simd: 6774 case OMPD_declare_variant: 6775 case OMPD_declare_target: 6776 case OMPD_end_declare_target: 6777 case OMPD_declare_reduction: 6778 case OMPD_declare_mapper: 6779 case OMPD_taskloop: 6780 case OMPD_taskloop_simd: 6781 case OMPD_requires: 6782 case OMPD_unknown: 6783 break; 6784 } 6785 llvm_unreachable("Unexpected directive kind."); 6786 } 6787 6788 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6789 llvm::Value *DefaultThreadLimitVal) { 6790 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6791 CGF.getContext(), CS->getCapturedStmt()); 6792 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6793 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6794 llvm::Value *NumThreads = nullptr; 6795 llvm::Value *CondVal = nullptr; 6796 // Handle if clause. If if clause present, the number of threads is 6797 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6798 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6799 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6800 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6801 const OMPIfClause *IfClause = nullptr; 6802 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6803 if (C->getNameModifier() == OMPD_unknown || 6804 C->getNameModifier() == OMPD_parallel) { 6805 IfClause = C; 6806 break; 6807 } 6808 } 6809 if (IfClause) { 6810 const Expr *Cond = IfClause->getCondition(); 6811 bool Result; 6812 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6813 if (!Result) 6814 return CGF.Builder.getInt32(1); 6815 } else { 6816 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6817 if (const auto *PreInit = 6818 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6819 for (const auto *I : PreInit->decls()) { 6820 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6821 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6822 } else { 6823 CodeGenFunction::AutoVarEmission Emission = 6824 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6825 CGF.EmitAutoVarCleanups(Emission); 6826 } 6827 } 6828 } 6829 CondVal = CGF.EvaluateExprAsBool(Cond); 6830 } 6831 } 6832 } 6833 // Check the value of num_threads clause iff if clause was not specified 6834 // or is not evaluated to false. 6835 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6836 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6837 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6838 const auto *NumThreadsClause = 6839 Dir->getSingleClause<OMPNumThreadsClause>(); 6840 CodeGenFunction::LexicalScope Scope( 6841 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6842 if (const auto *PreInit = 6843 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6844 for (const auto *I : PreInit->decls()) { 6845 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6846 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6847 } else { 6848 CodeGenFunction::AutoVarEmission Emission = 6849 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6850 CGF.EmitAutoVarCleanups(Emission); 6851 } 6852 } 6853 } 6854 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6855 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6856 /*isSigned=*/false); 6857 if (DefaultThreadLimitVal) 6858 NumThreads = CGF.Builder.CreateSelect( 6859 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6860 DefaultThreadLimitVal, NumThreads); 6861 } else { 6862 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6863 : CGF.Builder.getInt32(0); 6864 } 6865 // Process condition of the if clause. 6866 if (CondVal) { 6867 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6868 CGF.Builder.getInt32(1)); 6869 } 6870 return NumThreads; 6871 } 6872 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6873 return CGF.Builder.getInt32(1); 6874 return DefaultThreadLimitVal; 6875 } 6876 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6877 : CGF.Builder.getInt32(0); 6878 } 6879 6880 /// Emit the number of threads for a target directive. Inspect the 6881 /// thread_limit clause associated with a teams construct combined or closely 6882 /// nested with the target directive. 6883 /// 6884 /// Emit the num_threads clause for directives such as 'target parallel' that 6885 /// have no associated teams construct. 6886 /// 6887 /// Otherwise, return nullptr. 6888 static llvm::Value * 6889 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6890 const OMPExecutableDirective &D) { 6891 assert(!CGF.getLangOpts().OpenMPIsDevice && 6892 "Clauses associated with the teams directive expected to be emitted " 6893 "only for the host!"); 6894 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6895 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6896 "Expected target-based executable directive."); 6897 CGBuilderTy &Bld = CGF.Builder; 6898 llvm::Value *ThreadLimitVal = nullptr; 6899 llvm::Value *NumThreadsVal = nullptr; 6900 switch (DirectiveKind) { 6901 case OMPD_target: { 6902 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6903 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6904 return NumThreads; 6905 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6906 CGF.getContext(), CS->getCapturedStmt()); 6907 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6908 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6909 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6910 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6911 const auto *ThreadLimitClause = 6912 Dir->getSingleClause<OMPThreadLimitClause>(); 6913 CodeGenFunction::LexicalScope Scope( 6914 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6915 if (const auto *PreInit = 6916 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6917 for (const auto *I : PreInit->decls()) { 6918 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6919 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6920 } else { 6921 CodeGenFunction::AutoVarEmission Emission = 6922 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6923 CGF.EmitAutoVarCleanups(Emission); 6924 } 6925 } 6926 } 6927 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6928 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6929 ThreadLimitVal = 6930 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6931 } 6932 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6933 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6934 CS = Dir->getInnermostCapturedStmt(); 6935 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6936 CGF.getContext(), CS->getCapturedStmt()); 6937 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6938 } 6939 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6940 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6941 CS = Dir->getInnermostCapturedStmt(); 6942 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6943 return NumThreads; 6944 } 6945 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6946 return Bld.getInt32(1); 6947 } 6948 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6949 } 6950 case OMPD_target_teams: { 6951 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6952 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6953 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6954 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6955 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6956 ThreadLimitVal = 6957 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6958 } 6959 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6960 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6961 return NumThreads; 6962 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6963 CGF.getContext(), CS->getCapturedStmt()); 6964 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6965 if (Dir->getDirectiveKind() == OMPD_distribute) { 6966 CS = Dir->getInnermostCapturedStmt(); 6967 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6968 return NumThreads; 6969 } 6970 } 6971 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6972 } 6973 case OMPD_target_teams_distribute: 6974 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6975 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6976 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6977 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6978 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6979 ThreadLimitVal = 6980 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6981 } 6982 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6983 case OMPD_target_parallel: 6984 case OMPD_target_parallel_for: 6985 case OMPD_target_parallel_for_simd: 6986 case OMPD_target_teams_distribute_parallel_for: 6987 case OMPD_target_teams_distribute_parallel_for_simd: { 6988 llvm::Value *CondVal = nullptr; 6989 // Handle if clause. If if clause present, the number of threads is 6990 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6991 if (D.hasClausesOfKind<OMPIfClause>()) { 6992 const OMPIfClause *IfClause = nullptr; 6993 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6994 if (C->getNameModifier() == OMPD_unknown || 6995 C->getNameModifier() == OMPD_parallel) { 6996 IfClause = C; 6997 break; 6998 } 6999 } 7000 if (IfClause) { 7001 const Expr *Cond = IfClause->getCondition(); 7002 bool Result; 7003 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 7004 if (!Result) 7005 return Bld.getInt32(1); 7006 } else { 7007 CodeGenFunction::RunCleanupsScope Scope(CGF); 7008 CondVal = CGF.EvaluateExprAsBool(Cond); 7009 } 7010 } 7011 } 7012 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 7013 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 7014 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 7015 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 7016 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 7017 ThreadLimitVal = 7018 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 7019 } 7020 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 7021 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 7022 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 7023 llvm::Value *NumThreads = CGF.EmitScalarExpr( 7024 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 7025 NumThreadsVal = 7026 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 7027 ThreadLimitVal = ThreadLimitVal 7028 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 7029 ThreadLimitVal), 7030 NumThreadsVal, ThreadLimitVal) 7031 : NumThreadsVal; 7032 } 7033 if (!ThreadLimitVal) 7034 ThreadLimitVal = Bld.getInt32(0); 7035 if (CondVal) 7036 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 7037 return ThreadLimitVal; 7038 } 7039 case OMPD_target_teams_distribute_simd: 7040 case OMPD_target_simd: 7041 return Bld.getInt32(1); 7042 case OMPD_parallel: 7043 case OMPD_for: 7044 case OMPD_parallel_for: 7045 case OMPD_parallel_sections: 7046 case OMPD_for_simd: 7047 case OMPD_parallel_for_simd: 7048 case OMPD_cancel: 7049 case OMPD_cancellation_point: 7050 case OMPD_ordered: 7051 case OMPD_threadprivate: 7052 case OMPD_allocate: 7053 case OMPD_task: 7054 case OMPD_simd: 7055 case OMPD_sections: 7056 case OMPD_section: 7057 case OMPD_single: 7058 case OMPD_master: 7059 case OMPD_critical: 7060 case OMPD_taskyield: 7061 case OMPD_barrier: 7062 case OMPD_taskwait: 7063 case OMPD_taskgroup: 7064 case OMPD_atomic: 7065 case OMPD_flush: 7066 case OMPD_teams: 7067 case OMPD_target_data: 7068 case OMPD_target_exit_data: 7069 case OMPD_target_enter_data: 7070 case OMPD_distribute: 7071 case OMPD_distribute_simd: 7072 case OMPD_distribute_parallel_for: 7073 case OMPD_distribute_parallel_for_simd: 7074 case OMPD_teams_distribute: 7075 case OMPD_teams_distribute_simd: 7076 case OMPD_teams_distribute_parallel_for: 7077 case OMPD_teams_distribute_parallel_for_simd: 7078 case OMPD_target_update: 7079 case OMPD_declare_simd: 7080 case OMPD_declare_variant: 7081 case OMPD_declare_target: 7082 case OMPD_end_declare_target: 7083 case OMPD_declare_reduction: 7084 case OMPD_declare_mapper: 7085 case OMPD_taskloop: 7086 case OMPD_taskloop_simd: 7087 case OMPD_requires: 7088 case OMPD_unknown: 7089 break; 7090 } 7091 llvm_unreachable("Unsupported directive kind."); 7092 } 7093 7094 namespace { 7095 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7096 7097 // Utility to handle information from clauses associated with a given 7098 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7099 // It provides a convenient interface to obtain the information and generate 7100 // code for that information. 7101 class MappableExprsHandler { 7102 public: 7103 /// Values for bit flags used to specify the mapping type for 7104 /// offloading. 7105 enum OpenMPOffloadMappingFlags : uint64_t { 7106 /// No flags 7107 OMP_MAP_NONE = 0x0, 7108 /// Allocate memory on the device and move data from host to device. 7109 OMP_MAP_TO = 0x01, 7110 /// Allocate memory on the device and move data from device to host. 7111 OMP_MAP_FROM = 0x02, 7112 /// Always perform the requested mapping action on the element, even 7113 /// if it was already mapped before. 7114 OMP_MAP_ALWAYS = 0x04, 7115 /// Delete the element from the device environment, ignoring the 7116 /// current reference count associated with the element. 7117 OMP_MAP_DELETE = 0x08, 7118 /// The element being mapped is a pointer-pointee pair; both the 7119 /// pointer and the pointee should be mapped. 7120 OMP_MAP_PTR_AND_OBJ = 0x10, 7121 /// This flags signals that the base address of an entry should be 7122 /// passed to the target kernel as an argument. 7123 OMP_MAP_TARGET_PARAM = 0x20, 7124 /// Signal that the runtime library has to return the device pointer 7125 /// in the current position for the data being mapped. Used when we have the 7126 /// use_device_ptr clause. 7127 OMP_MAP_RETURN_PARAM = 0x40, 7128 /// This flag signals that the reference being passed is a pointer to 7129 /// private data. 7130 OMP_MAP_PRIVATE = 0x80, 7131 /// Pass the element to the device by value. 7132 OMP_MAP_LITERAL = 0x100, 7133 /// Implicit map 7134 OMP_MAP_IMPLICIT = 0x200, 7135 /// Close is a hint to the runtime to allocate memory close to 7136 /// the target device. 7137 OMP_MAP_CLOSE = 0x400, 7138 /// The 16 MSBs of the flags indicate whether the entry is member of some 7139 /// struct/class. 7140 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7141 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7142 }; 7143 7144 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7145 static unsigned getFlagMemberOffset() { 7146 unsigned Offset = 0; 7147 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7148 Remain = Remain >> 1) 7149 Offset++; 7150 return Offset; 7151 } 7152 7153 /// Class that associates information with a base pointer to be passed to the 7154 /// runtime library. 7155 class BasePointerInfo { 7156 /// The base pointer. 7157 llvm::Value *Ptr = nullptr; 7158 /// The base declaration that refers to this device pointer, or null if 7159 /// there is none. 7160 const ValueDecl *DevPtrDecl = nullptr; 7161 7162 public: 7163 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7164 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7165 llvm::Value *operator*() const { return Ptr; } 7166 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7167 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7168 }; 7169 7170 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7171 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7172 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7173 7174 /// Map between a struct and the its lowest & highest elements which have been 7175 /// mapped. 7176 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7177 /// HE(FieldIndex, Pointer)} 7178 struct StructRangeInfoTy { 7179 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7180 0, Address::invalid()}; 7181 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7182 0, Address::invalid()}; 7183 Address Base = Address::invalid(); 7184 }; 7185 7186 private: 7187 /// Kind that defines how a device pointer has to be returned. 7188 struct MapInfo { 7189 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7190 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7191 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7192 bool ReturnDevicePointer = false; 7193 bool IsImplicit = false; 7194 7195 MapInfo() = default; 7196 MapInfo( 7197 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7198 OpenMPMapClauseKind MapType, 7199 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7200 bool ReturnDevicePointer, bool IsImplicit) 7201 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7202 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7203 }; 7204 7205 /// If use_device_ptr is used on a pointer which is a struct member and there 7206 /// is no map information about it, then emission of that entry is deferred 7207 /// until the whole struct has been processed. 7208 struct DeferredDevicePtrEntryTy { 7209 const Expr *IE = nullptr; 7210 const ValueDecl *VD = nullptr; 7211 7212 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7213 : IE(IE), VD(VD) {} 7214 }; 7215 7216 /// The target directive from where the mappable clauses were extracted. It 7217 /// is either a executable directive or a user-defined mapper directive. 7218 llvm::PointerUnion<const OMPExecutableDirective *, 7219 const OMPDeclareMapperDecl *> 7220 CurDir; 7221 7222 /// Function the directive is being generated for. 7223 CodeGenFunction &CGF; 7224 7225 /// Set of all first private variables in the current directive. 7226 /// bool data is set to true if the variable is implicitly marked as 7227 /// firstprivate, false otherwise. 7228 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7229 7230 /// Map between device pointer declarations and their expression components. 7231 /// The key value for declarations in 'this' is null. 7232 llvm::DenseMap< 7233 const ValueDecl *, 7234 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7235 DevPointersMap; 7236 7237 llvm::Value *getExprTypeSize(const Expr *E) const { 7238 QualType ExprTy = E->getType().getCanonicalType(); 7239 7240 // Reference types are ignored for mapping purposes. 7241 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7242 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7243 7244 // Given that an array section is considered a built-in type, we need to 7245 // do the calculation based on the length of the section instead of relying 7246 // on CGF.getTypeSize(E->getType()). 7247 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7248 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7249 OAE->getBase()->IgnoreParenImpCasts()) 7250 .getCanonicalType(); 7251 7252 // If there is no length associated with the expression, that means we 7253 // are using the whole length of the base. 7254 if (!OAE->getLength() && OAE->getColonLoc().isValid()) 7255 return CGF.getTypeSize(BaseTy); 7256 7257 llvm::Value *ElemSize; 7258 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7259 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7260 } else { 7261 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7262 assert(ATy && "Expecting array type if not a pointer type."); 7263 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7264 } 7265 7266 // If we don't have a length at this point, that is because we have an 7267 // array section with a single element. 7268 if (!OAE->getLength()) 7269 return ElemSize; 7270 7271 llvm::Value *LengthVal = CGF.EmitScalarExpr(OAE->getLength()); 7272 LengthVal = 7273 CGF.Builder.CreateIntCast(LengthVal, CGF.SizeTy, /*isSigned=*/false); 7274 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7275 } 7276 return CGF.getTypeSize(ExprTy); 7277 } 7278 7279 /// Return the corresponding bits for a given map clause modifier. Add 7280 /// a flag marking the map as a pointer if requested. Add a flag marking the 7281 /// map as the first one of a series of maps that relate to the same map 7282 /// expression. 7283 OpenMPOffloadMappingFlags getMapTypeBits( 7284 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7285 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7286 OpenMPOffloadMappingFlags Bits = 7287 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7288 switch (MapType) { 7289 case OMPC_MAP_alloc: 7290 case OMPC_MAP_release: 7291 // alloc and release is the default behavior in the runtime library, i.e. 7292 // if we don't pass any bits alloc/release that is what the runtime is 7293 // going to do. Therefore, we don't need to signal anything for these two 7294 // type modifiers. 7295 break; 7296 case OMPC_MAP_to: 7297 Bits |= OMP_MAP_TO; 7298 break; 7299 case OMPC_MAP_from: 7300 Bits |= OMP_MAP_FROM; 7301 break; 7302 case OMPC_MAP_tofrom: 7303 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7304 break; 7305 case OMPC_MAP_delete: 7306 Bits |= OMP_MAP_DELETE; 7307 break; 7308 case OMPC_MAP_unknown: 7309 llvm_unreachable("Unexpected map type!"); 7310 } 7311 if (AddPtrFlag) 7312 Bits |= OMP_MAP_PTR_AND_OBJ; 7313 if (AddIsTargetParamFlag) 7314 Bits |= OMP_MAP_TARGET_PARAM; 7315 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7316 != MapModifiers.end()) 7317 Bits |= OMP_MAP_ALWAYS; 7318 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7319 != MapModifiers.end()) 7320 Bits |= OMP_MAP_CLOSE; 7321 return Bits; 7322 } 7323 7324 /// Return true if the provided expression is a final array section. A 7325 /// final array section, is one whose length can't be proved to be one. 7326 bool isFinalArraySectionExpression(const Expr *E) const { 7327 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7328 7329 // It is not an array section and therefore not a unity-size one. 7330 if (!OASE) 7331 return false; 7332 7333 // An array section with no colon always refer to a single element. 7334 if (OASE->getColonLoc().isInvalid()) 7335 return false; 7336 7337 const Expr *Length = OASE->getLength(); 7338 7339 // If we don't have a length we have to check if the array has size 1 7340 // for this dimension. Also, we should always expect a length if the 7341 // base type is pointer. 7342 if (!Length) { 7343 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7344 OASE->getBase()->IgnoreParenImpCasts()) 7345 .getCanonicalType(); 7346 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7347 return ATy->getSize().getSExtValue() != 1; 7348 // If we don't have a constant dimension length, we have to consider 7349 // the current section as having any size, so it is not necessarily 7350 // unitary. If it happen to be unity size, that's user fault. 7351 return true; 7352 } 7353 7354 // Check if the length evaluates to 1. 7355 Expr::EvalResult Result; 7356 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7357 return true; // Can have more that size 1. 7358 7359 llvm::APSInt ConstLength = Result.Val.getInt(); 7360 return ConstLength.getSExtValue() != 1; 7361 } 7362 7363 /// Generate the base pointers, section pointers, sizes and map type 7364 /// bits for the provided map type, map modifier, and expression components. 7365 /// \a IsFirstComponent should be set to true if the provided set of 7366 /// components is the first associated with a capture. 7367 void generateInfoForComponentList( 7368 OpenMPMapClauseKind MapType, 7369 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7370 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7371 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7372 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7373 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7374 bool IsImplicit, 7375 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7376 OverlappedElements = llvm::None) const { 7377 // The following summarizes what has to be generated for each map and the 7378 // types below. The generated information is expressed in this order: 7379 // base pointer, section pointer, size, flags 7380 // (to add to the ones that come from the map type and modifier). 7381 // 7382 // double d; 7383 // int i[100]; 7384 // float *p; 7385 // 7386 // struct S1 { 7387 // int i; 7388 // float f[50]; 7389 // } 7390 // struct S2 { 7391 // int i; 7392 // float f[50]; 7393 // S1 s; 7394 // double *p; 7395 // struct S2 *ps; 7396 // } 7397 // S2 s; 7398 // S2 *ps; 7399 // 7400 // map(d) 7401 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7402 // 7403 // map(i) 7404 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7405 // 7406 // map(i[1:23]) 7407 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7408 // 7409 // map(p) 7410 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7411 // 7412 // map(p[1:24]) 7413 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7414 // 7415 // map(s) 7416 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7417 // 7418 // map(s.i) 7419 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7420 // 7421 // map(s.s.f) 7422 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7423 // 7424 // map(s.p) 7425 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7426 // 7427 // map(to: s.p[:22]) 7428 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7429 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7430 // &(s.p), &(s.p[0]), 22*sizeof(double), 7431 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7432 // (*) alloc space for struct members, only this is a target parameter 7433 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7434 // optimizes this entry out, same in the examples below) 7435 // (***) map the pointee (map: to) 7436 // 7437 // map(s.ps) 7438 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7439 // 7440 // map(from: s.ps->s.i) 7441 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7442 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7443 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7444 // 7445 // map(to: s.ps->ps) 7446 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7447 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7448 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7449 // 7450 // map(s.ps->ps->ps) 7451 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7452 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7453 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7454 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7455 // 7456 // map(to: s.ps->ps->s.f[:22]) 7457 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7458 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7459 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7460 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7461 // 7462 // map(ps) 7463 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7464 // 7465 // map(ps->i) 7466 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7467 // 7468 // map(ps->s.f) 7469 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7470 // 7471 // map(from: ps->p) 7472 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7473 // 7474 // map(to: ps->p[:22]) 7475 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7476 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7477 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7478 // 7479 // map(ps->ps) 7480 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7481 // 7482 // map(from: ps->ps->s.i) 7483 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7484 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7485 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7486 // 7487 // map(from: ps->ps->ps) 7488 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7489 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7490 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7491 // 7492 // map(ps->ps->ps->ps) 7493 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7494 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7495 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7496 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7497 // 7498 // map(to: ps->ps->ps->s.f[:22]) 7499 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7500 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7501 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7502 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7503 // 7504 // map(to: s.f[:22]) map(from: s.p[:33]) 7505 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7506 // sizeof(double*) (**), TARGET_PARAM 7507 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7508 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7509 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7510 // (*) allocate contiguous space needed to fit all mapped members even if 7511 // we allocate space for members not mapped (in this example, 7512 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7513 // them as well because they fall between &s.f[0] and &s.p) 7514 // 7515 // map(from: s.f[:22]) map(to: ps->p[:33]) 7516 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7517 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7518 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7519 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7520 // (*) the struct this entry pertains to is the 2nd element in the list of 7521 // arguments, hence MEMBER_OF(2) 7522 // 7523 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7524 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7525 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7526 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7527 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7528 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7529 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7530 // (*) the struct this entry pertains to is the 4th element in the list 7531 // of arguments, hence MEMBER_OF(4) 7532 7533 // Track if the map information being generated is the first for a capture. 7534 bool IsCaptureFirstInfo = IsFirstComponentList; 7535 // When the variable is on a declare target link or in a to clause with 7536 // unified memory, a reference is needed to hold the host/device address 7537 // of the variable. 7538 bool RequiresReference = false; 7539 7540 // Scan the components from the base to the complete expression. 7541 auto CI = Components.rbegin(); 7542 auto CE = Components.rend(); 7543 auto I = CI; 7544 7545 // Track if the map information being generated is the first for a list of 7546 // components. 7547 bool IsExpressionFirstInfo = true; 7548 Address BP = Address::invalid(); 7549 const Expr *AssocExpr = I->getAssociatedExpression(); 7550 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7551 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7552 7553 if (isa<MemberExpr>(AssocExpr)) { 7554 // The base is the 'this' pointer. The content of the pointer is going 7555 // to be the base of the field being mapped. 7556 BP = CGF.LoadCXXThisAddress(); 7557 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7558 (OASE && 7559 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7560 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); 7561 } else { 7562 // The base is the reference to the variable. 7563 // BP = &Var. 7564 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); 7565 if (const auto *VD = 7566 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7567 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7568 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7569 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7570 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7571 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7572 RequiresReference = true; 7573 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7574 } 7575 } 7576 } 7577 7578 // If the variable is a pointer and is being dereferenced (i.e. is not 7579 // the last component), the base has to be the pointer itself, not its 7580 // reference. References are ignored for mapping purposes. 7581 QualType Ty = 7582 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7583 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7584 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7585 7586 // We do not need to generate individual map information for the 7587 // pointer, it can be associated with the combined storage. 7588 ++I; 7589 } 7590 } 7591 7592 // Track whether a component of the list should be marked as MEMBER_OF some 7593 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7594 // in a component list should be marked as MEMBER_OF, all subsequent entries 7595 // do not belong to the base struct. E.g. 7596 // struct S2 s; 7597 // s.ps->ps->ps->f[:] 7598 // (1) (2) (3) (4) 7599 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7600 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7601 // is the pointee of ps(2) which is not member of struct s, so it should not 7602 // be marked as such (it is still PTR_AND_OBJ). 7603 // The variable is initialized to false so that PTR_AND_OBJ entries which 7604 // are not struct members are not considered (e.g. array of pointers to 7605 // data). 7606 bool ShouldBeMemberOf = false; 7607 7608 // Variable keeping track of whether or not we have encountered a component 7609 // in the component list which is a member expression. Useful when we have a 7610 // pointer or a final array section, in which case it is the previous 7611 // component in the list which tells us whether we have a member expression. 7612 // E.g. X.f[:] 7613 // While processing the final array section "[:]" it is "f" which tells us 7614 // whether we are dealing with a member of a declared struct. 7615 const MemberExpr *EncounteredME = nullptr; 7616 7617 for (; I != CE; ++I) { 7618 // If the current component is member of a struct (parent struct) mark it. 7619 if (!EncounteredME) { 7620 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7621 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7622 // as MEMBER_OF the parent struct. 7623 if (EncounteredME) 7624 ShouldBeMemberOf = true; 7625 } 7626 7627 auto Next = std::next(I); 7628 7629 // We need to generate the addresses and sizes if this is the last 7630 // component, if the component is a pointer or if it is an array section 7631 // whose length can't be proved to be one. If this is a pointer, it 7632 // becomes the base address for the following components. 7633 7634 // A final array section, is one whose length can't be proved to be one. 7635 bool IsFinalArraySection = 7636 isFinalArraySectionExpression(I->getAssociatedExpression()); 7637 7638 // Get information on whether the element is a pointer. Have to do a 7639 // special treatment for array sections given that they are built-in 7640 // types. 7641 const auto *OASE = 7642 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7643 bool IsPointer = 7644 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7645 .getCanonicalType() 7646 ->isAnyPointerType()) || 7647 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7648 7649 if (Next == CE || IsPointer || IsFinalArraySection) { 7650 // If this is not the last component, we expect the pointer to be 7651 // associated with an array expression or member expression. 7652 assert((Next == CE || 7653 isa<MemberExpr>(Next->getAssociatedExpression()) || 7654 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7655 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 7656 "Unexpected expression"); 7657 7658 Address LB = 7659 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress(); 7660 7661 // If this component is a pointer inside the base struct then we don't 7662 // need to create any entry for it - it will be combined with the object 7663 // it is pointing to into a single PTR_AND_OBJ entry. 7664 bool IsMemberPointer = 7665 IsPointer && EncounteredME && 7666 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7667 EncounteredME); 7668 if (!OverlappedElements.empty()) { 7669 // Handle base element with the info for overlapped elements. 7670 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7671 assert(Next == CE && 7672 "Expected last element for the overlapped elements."); 7673 assert(!IsPointer && 7674 "Unexpected base element with the pointer type."); 7675 // Mark the whole struct as the struct that requires allocation on the 7676 // device. 7677 PartialStruct.LowestElem = {0, LB}; 7678 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7679 I->getAssociatedExpression()->getType()); 7680 Address HB = CGF.Builder.CreateConstGEP( 7681 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7682 CGF.VoidPtrTy), 7683 TypeSize.getQuantity() - 1); 7684 PartialStruct.HighestElem = { 7685 std::numeric_limits<decltype( 7686 PartialStruct.HighestElem.first)>::max(), 7687 HB}; 7688 PartialStruct.Base = BP; 7689 // Emit data for non-overlapped data. 7690 OpenMPOffloadMappingFlags Flags = 7691 OMP_MAP_MEMBER_OF | 7692 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7693 /*AddPtrFlag=*/false, 7694 /*AddIsTargetParamFlag=*/false); 7695 LB = BP; 7696 llvm::Value *Size = nullptr; 7697 // Do bitcopy of all non-overlapped structure elements. 7698 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7699 Component : OverlappedElements) { 7700 Address ComponentLB = Address::invalid(); 7701 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7702 Component) { 7703 if (MC.getAssociatedDeclaration()) { 7704 ComponentLB = 7705 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7706 .getAddress(); 7707 Size = CGF.Builder.CreatePtrDiff( 7708 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7709 CGF.EmitCastToVoidPtr(LB.getPointer())); 7710 break; 7711 } 7712 } 7713 BasePointers.push_back(BP.getPointer()); 7714 Pointers.push_back(LB.getPointer()); 7715 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7716 /*isSigned=*/true)); 7717 Types.push_back(Flags); 7718 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7719 } 7720 BasePointers.push_back(BP.getPointer()); 7721 Pointers.push_back(LB.getPointer()); 7722 Size = CGF.Builder.CreatePtrDiff( 7723 CGF.EmitCastToVoidPtr( 7724 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7725 CGF.EmitCastToVoidPtr(LB.getPointer())); 7726 Sizes.push_back( 7727 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7728 Types.push_back(Flags); 7729 break; 7730 } 7731 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7732 if (!IsMemberPointer) { 7733 BasePointers.push_back(BP.getPointer()); 7734 Pointers.push_back(LB.getPointer()); 7735 Sizes.push_back( 7736 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7737 7738 // We need to add a pointer flag for each map that comes from the 7739 // same expression except for the first one. We also need to signal 7740 // this map is the first one that relates with the current capture 7741 // (there is a set of entries for each capture). 7742 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7743 MapType, MapModifiers, IsImplicit, 7744 !IsExpressionFirstInfo || RequiresReference, 7745 IsCaptureFirstInfo && !RequiresReference); 7746 7747 if (!IsExpressionFirstInfo) { 7748 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7749 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7750 if (IsPointer) 7751 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7752 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7753 7754 if (ShouldBeMemberOf) { 7755 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7756 // should be later updated with the correct value of MEMBER_OF. 7757 Flags |= OMP_MAP_MEMBER_OF; 7758 // From now on, all subsequent PTR_AND_OBJ entries should not be 7759 // marked as MEMBER_OF. 7760 ShouldBeMemberOf = false; 7761 } 7762 } 7763 7764 Types.push_back(Flags); 7765 } 7766 7767 // If we have encountered a member expression so far, keep track of the 7768 // mapped member. If the parent is "*this", then the value declaration 7769 // is nullptr. 7770 if (EncounteredME) { 7771 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); 7772 unsigned FieldIndex = FD->getFieldIndex(); 7773 7774 // Update info about the lowest and highest elements for this struct 7775 if (!PartialStruct.Base.isValid()) { 7776 PartialStruct.LowestElem = {FieldIndex, LB}; 7777 PartialStruct.HighestElem = {FieldIndex, LB}; 7778 PartialStruct.Base = BP; 7779 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7780 PartialStruct.LowestElem = {FieldIndex, LB}; 7781 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7782 PartialStruct.HighestElem = {FieldIndex, LB}; 7783 } 7784 } 7785 7786 // If we have a final array section, we are done with this expression. 7787 if (IsFinalArraySection) 7788 break; 7789 7790 // The pointer becomes the base for the next element. 7791 if (Next != CE) 7792 BP = LB; 7793 7794 IsExpressionFirstInfo = false; 7795 IsCaptureFirstInfo = false; 7796 } 7797 } 7798 } 7799 7800 /// Return the adjusted map modifiers if the declaration a capture refers to 7801 /// appears in a first-private clause. This is expected to be used only with 7802 /// directives that start with 'target'. 7803 MappableExprsHandler::OpenMPOffloadMappingFlags 7804 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7805 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7806 7807 // A first private variable captured by reference will use only the 7808 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7809 // declaration is known as first-private in this handler. 7810 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7811 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7812 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7813 return MappableExprsHandler::OMP_MAP_ALWAYS | 7814 MappableExprsHandler::OMP_MAP_TO; 7815 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7816 return MappableExprsHandler::OMP_MAP_TO | 7817 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7818 return MappableExprsHandler::OMP_MAP_PRIVATE | 7819 MappableExprsHandler::OMP_MAP_TO; 7820 } 7821 return MappableExprsHandler::OMP_MAP_TO | 7822 MappableExprsHandler::OMP_MAP_FROM; 7823 } 7824 7825 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7826 // Rotate by getFlagMemberOffset() bits. 7827 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7828 << getFlagMemberOffset()); 7829 } 7830 7831 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7832 OpenMPOffloadMappingFlags MemberOfFlag) { 7833 // If the entry is PTR_AND_OBJ but has not been marked with the special 7834 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7835 // marked as MEMBER_OF. 7836 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7837 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7838 return; 7839 7840 // Reset the placeholder value to prepare the flag for the assignment of the 7841 // proper MEMBER_OF value. 7842 Flags &= ~OMP_MAP_MEMBER_OF; 7843 Flags |= MemberOfFlag; 7844 } 7845 7846 void getPlainLayout(const CXXRecordDecl *RD, 7847 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7848 bool AsBase) const { 7849 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7850 7851 llvm::StructType *St = 7852 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7853 7854 unsigned NumElements = St->getNumElements(); 7855 llvm::SmallVector< 7856 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7857 RecordLayout(NumElements); 7858 7859 // Fill bases. 7860 for (const auto &I : RD->bases()) { 7861 if (I.isVirtual()) 7862 continue; 7863 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7864 // Ignore empty bases. 7865 if (Base->isEmpty() || CGF.getContext() 7866 .getASTRecordLayout(Base) 7867 .getNonVirtualSize() 7868 .isZero()) 7869 continue; 7870 7871 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7872 RecordLayout[FieldIndex] = Base; 7873 } 7874 // Fill in virtual bases. 7875 for (const auto &I : RD->vbases()) { 7876 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7877 // Ignore empty bases. 7878 if (Base->isEmpty()) 7879 continue; 7880 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7881 if (RecordLayout[FieldIndex]) 7882 continue; 7883 RecordLayout[FieldIndex] = Base; 7884 } 7885 // Fill in all the fields. 7886 assert(!RD->isUnion() && "Unexpected union."); 7887 for (const auto *Field : RD->fields()) { 7888 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7889 // will fill in later.) 7890 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7891 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7892 RecordLayout[FieldIndex] = Field; 7893 } 7894 } 7895 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7896 &Data : RecordLayout) { 7897 if (Data.isNull()) 7898 continue; 7899 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7900 getPlainLayout(Base, Layout, /*AsBase=*/true); 7901 else 7902 Layout.push_back(Data.get<const FieldDecl *>()); 7903 } 7904 } 7905 7906 public: 7907 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7908 : CurDir(&Dir), CGF(CGF) { 7909 // Extract firstprivate clause information. 7910 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7911 for (const auto *D : C->varlists()) 7912 FirstPrivateDecls.try_emplace( 7913 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 7914 // Extract device pointer clause information. 7915 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7916 for (auto L : C->component_lists()) 7917 DevPointersMap[L.first].push_back(L.second); 7918 } 7919 7920 /// Constructor for the declare mapper directive. 7921 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 7922 : CurDir(&Dir), CGF(CGF) {} 7923 7924 /// Generate code for the combined entry if we have a partially mapped struct 7925 /// and take care of the mapping flags of the arguments corresponding to 7926 /// individual struct members. 7927 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 7928 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7929 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 7930 const StructRangeInfoTy &PartialStruct) const { 7931 // Base is the base of the struct 7932 BasePointers.push_back(PartialStruct.Base.getPointer()); 7933 // Pointer is the address of the lowest element 7934 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7935 Pointers.push_back(LB); 7936 // Size is (addr of {highest+1} element) - (addr of lowest element) 7937 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7938 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7939 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7940 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7941 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7942 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 7943 /*isSigned=*/false); 7944 Sizes.push_back(Size); 7945 // Map type is always TARGET_PARAM 7946 Types.push_back(OMP_MAP_TARGET_PARAM); 7947 // Remove TARGET_PARAM flag from the first element 7948 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7949 7950 // All other current entries will be MEMBER_OF the combined entry 7951 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7952 // 0xFFFF in the MEMBER_OF field). 7953 OpenMPOffloadMappingFlags MemberOfFlag = 7954 getMemberOfFlag(BasePointers.size() - 1); 7955 for (auto &M : CurTypes) 7956 setCorrectMemberOfFlag(M, MemberOfFlag); 7957 } 7958 7959 /// Generate all the base pointers, section pointers, sizes and map 7960 /// types for the extracted mappable expressions. Also, for each item that 7961 /// relates with a device pointer, a pair of the relevant declaration and 7962 /// index where it occurs is appended to the device pointers info array. 7963 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 7964 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7965 MapFlagsArrayTy &Types) const { 7966 // We have to process the component lists that relate with the same 7967 // declaration in a single chunk so that we can generate the map flags 7968 // correctly. Therefore, we organize all lists in a map. 7969 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7970 7971 // Helper function to fill the information map for the different supported 7972 // clauses. 7973 auto &&InfoGen = [&Info]( 7974 const ValueDecl *D, 7975 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7976 OpenMPMapClauseKind MapType, 7977 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7978 bool ReturnDevicePointer, bool IsImplicit) { 7979 const ValueDecl *VD = 7980 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7981 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7982 IsImplicit); 7983 }; 7984 7985 assert(CurDir.is<const OMPExecutableDirective *>() && 7986 "Expect a executable directive"); 7987 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 7988 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 7989 for (const auto &L : C->component_lists()) { 7990 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 7991 /*ReturnDevicePointer=*/false, C->isImplicit()); 7992 } 7993 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 7994 for (const auto &L : C->component_lists()) { 7995 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 7996 /*ReturnDevicePointer=*/false, C->isImplicit()); 7997 } 7998 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 7999 for (const auto &L : C->component_lists()) { 8000 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 8001 /*ReturnDevicePointer=*/false, C->isImplicit()); 8002 } 8003 8004 // Look at the use_device_ptr clause information and mark the existing map 8005 // entries as such. If there is no map information for an entry in the 8006 // use_device_ptr list, we create one with map type 'alloc' and zero size 8007 // section. It is the user fault if that was not mapped before. If there is 8008 // no map information and the pointer is a struct member, then we defer the 8009 // emission of that entry until the whole struct has been processed. 8010 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 8011 DeferredInfo; 8012 8013 for (const auto *C : 8014 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 8015 for (const auto &L : C->component_lists()) { 8016 assert(!L.second.empty() && "Not expecting empty list of components!"); 8017 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 8018 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8019 const Expr *IE = L.second.back().getAssociatedExpression(); 8020 // If the first component is a member expression, we have to look into 8021 // 'this', which maps to null in the map of map information. Otherwise 8022 // look directly for the information. 8023 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8024 8025 // We potentially have map information for this declaration already. 8026 // Look for the first set of components that refer to it. 8027 if (It != Info.end()) { 8028 auto CI = std::find_if( 8029 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 8030 return MI.Components.back().getAssociatedDeclaration() == VD; 8031 }); 8032 // If we found a map entry, signal that the pointer has to be returned 8033 // and move on to the next declaration. 8034 if (CI != It->second.end()) { 8035 CI->ReturnDevicePointer = true; 8036 continue; 8037 } 8038 } 8039 8040 // We didn't find any match in our map information - generate a zero 8041 // size array section - if the pointer is a struct member we defer this 8042 // action until the whole struct has been processed. 8043 if (isa<MemberExpr>(IE)) { 8044 // Insert the pointer into Info to be processed by 8045 // generateInfoForComponentList. Because it is a member pointer 8046 // without a pointee, no entry will be generated for it, therefore 8047 // we need to generate one after the whole struct has been processed. 8048 // Nonetheless, generateInfoForComponentList must be called to take 8049 // the pointer into account for the calculation of the range of the 8050 // partial struct. 8051 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 8052 /*ReturnDevicePointer=*/false, C->isImplicit()); 8053 DeferredInfo[nullptr].emplace_back(IE, VD); 8054 } else { 8055 llvm::Value *Ptr = 8056 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8057 BasePointers.emplace_back(Ptr, VD); 8058 Pointers.push_back(Ptr); 8059 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8060 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8061 } 8062 } 8063 } 8064 8065 for (const auto &M : Info) { 8066 // We need to know when we generate information for the first component 8067 // associated with a capture, because the mapping flags depend on it. 8068 bool IsFirstComponentList = true; 8069 8070 // Temporary versions of arrays 8071 MapBaseValuesArrayTy CurBasePointers; 8072 MapValuesArrayTy CurPointers; 8073 MapValuesArrayTy CurSizes; 8074 MapFlagsArrayTy CurTypes; 8075 StructRangeInfoTy PartialStruct; 8076 8077 for (const MapInfo &L : M.second) { 8078 assert(!L.Components.empty() && 8079 "Not expecting declaration with no component lists."); 8080 8081 // Remember the current base pointer index. 8082 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8083 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8084 CurBasePointers, CurPointers, CurSizes, 8085 CurTypes, PartialStruct, 8086 IsFirstComponentList, L.IsImplicit); 8087 8088 // If this entry relates with a device pointer, set the relevant 8089 // declaration and add the 'return pointer' flag. 8090 if (L.ReturnDevicePointer) { 8091 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8092 "Unexpected number of mapped base pointers."); 8093 8094 const ValueDecl *RelevantVD = 8095 L.Components.back().getAssociatedDeclaration(); 8096 assert(RelevantVD && 8097 "No relevant declaration related with device pointer??"); 8098 8099 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8100 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8101 } 8102 IsFirstComponentList = false; 8103 } 8104 8105 // Append any pending zero-length pointers which are struct members and 8106 // used with use_device_ptr. 8107 auto CI = DeferredInfo.find(M.first); 8108 if (CI != DeferredInfo.end()) { 8109 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8110 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(); 8111 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8112 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8113 CurBasePointers.emplace_back(BasePtr, L.VD); 8114 CurPointers.push_back(Ptr); 8115 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8116 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8117 // value MEMBER_OF=FFFF so that the entry is later updated with the 8118 // correct value of MEMBER_OF. 8119 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8120 OMP_MAP_MEMBER_OF); 8121 } 8122 } 8123 8124 // If there is an entry in PartialStruct it means we have a struct with 8125 // individual members mapped. Emit an extra combined entry. 8126 if (PartialStruct.Base.isValid()) 8127 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8128 PartialStruct); 8129 8130 // We need to append the results of this capture to what we already have. 8131 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8132 Pointers.append(CurPointers.begin(), CurPointers.end()); 8133 Sizes.append(CurSizes.begin(), CurSizes.end()); 8134 Types.append(CurTypes.begin(), CurTypes.end()); 8135 } 8136 } 8137 8138 /// Generate all the base pointers, section pointers, sizes and map types for 8139 /// the extracted map clauses of user-defined mapper. 8140 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8141 MapValuesArrayTy &Pointers, 8142 MapValuesArrayTy &Sizes, 8143 MapFlagsArrayTy &Types) const { 8144 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8145 "Expect a declare mapper directive"); 8146 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8147 // We have to process the component lists that relate with the same 8148 // declaration in a single chunk so that we can generate the map flags 8149 // correctly. Therefore, we organize all lists in a map. 8150 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8151 8152 // Helper function to fill the information map for the different supported 8153 // clauses. 8154 auto &&InfoGen = [&Info]( 8155 const ValueDecl *D, 8156 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8157 OpenMPMapClauseKind MapType, 8158 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8159 bool ReturnDevicePointer, bool IsImplicit) { 8160 const ValueDecl *VD = 8161 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8162 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8163 IsImplicit); 8164 }; 8165 8166 for (const auto *C : CurMapperDir->clauselists()) { 8167 const auto *MC = cast<OMPMapClause>(C); 8168 for (const auto &L : MC->component_lists()) { 8169 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8170 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8171 } 8172 } 8173 8174 for (const auto &M : Info) { 8175 // We need to know when we generate information for the first component 8176 // associated with a capture, because the mapping flags depend on it. 8177 bool IsFirstComponentList = true; 8178 8179 // Temporary versions of arrays 8180 MapBaseValuesArrayTy CurBasePointers; 8181 MapValuesArrayTy CurPointers; 8182 MapValuesArrayTy CurSizes; 8183 MapFlagsArrayTy CurTypes; 8184 StructRangeInfoTy PartialStruct; 8185 8186 for (const MapInfo &L : M.second) { 8187 assert(!L.Components.empty() && 8188 "Not expecting declaration with no component lists."); 8189 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8190 CurBasePointers, CurPointers, CurSizes, 8191 CurTypes, PartialStruct, 8192 IsFirstComponentList, L.IsImplicit); 8193 IsFirstComponentList = false; 8194 } 8195 8196 // If there is an entry in PartialStruct it means we have a struct with 8197 // individual members mapped. Emit an extra combined entry. 8198 if (PartialStruct.Base.isValid()) 8199 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8200 PartialStruct); 8201 8202 // We need to append the results of this capture to what we already have. 8203 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8204 Pointers.append(CurPointers.begin(), CurPointers.end()); 8205 Sizes.append(CurSizes.begin(), CurSizes.end()); 8206 Types.append(CurTypes.begin(), CurTypes.end()); 8207 } 8208 } 8209 8210 /// Emit capture info for lambdas for variables captured by reference. 8211 void generateInfoForLambdaCaptures( 8212 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8213 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8214 MapFlagsArrayTy &Types, 8215 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8216 const auto *RD = VD->getType() 8217 .getCanonicalType() 8218 .getNonReferenceType() 8219 ->getAsCXXRecordDecl(); 8220 if (!RD || !RD->isLambda()) 8221 return; 8222 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8223 LValue VDLVal = CGF.MakeAddrLValue( 8224 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8225 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8226 FieldDecl *ThisCapture = nullptr; 8227 RD->getCaptureFields(Captures, ThisCapture); 8228 if (ThisCapture) { 8229 LValue ThisLVal = 8230 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8231 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8232 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer()); 8233 BasePointers.push_back(ThisLVal.getPointer()); 8234 Pointers.push_back(ThisLValVal.getPointer()); 8235 Sizes.push_back( 8236 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8237 CGF.Int64Ty, /*isSigned=*/true)); 8238 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8239 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8240 } 8241 for (const LambdaCapture &LC : RD->captures()) { 8242 if (!LC.capturesVariable()) 8243 continue; 8244 const VarDecl *VD = LC.getCapturedVar(); 8245 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8246 continue; 8247 auto It = Captures.find(VD); 8248 assert(It != Captures.end() && "Found lambda capture without field."); 8249 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8250 if (LC.getCaptureKind() == LCK_ByRef) { 8251 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8252 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer()); 8253 BasePointers.push_back(VarLVal.getPointer()); 8254 Pointers.push_back(VarLValVal.getPointer()); 8255 Sizes.push_back(CGF.Builder.CreateIntCast( 8256 CGF.getTypeSize( 8257 VD->getType().getCanonicalType().getNonReferenceType()), 8258 CGF.Int64Ty, /*isSigned=*/true)); 8259 } else { 8260 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8261 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer()); 8262 BasePointers.push_back(VarLVal.getPointer()); 8263 Pointers.push_back(VarRVal.getScalarVal()); 8264 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8265 } 8266 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8267 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8268 } 8269 } 8270 8271 /// Set correct indices for lambdas captures. 8272 void adjustMemberOfForLambdaCaptures( 8273 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8274 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8275 MapFlagsArrayTy &Types) const { 8276 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8277 // Set correct member_of idx for all implicit lambda captures. 8278 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8279 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8280 continue; 8281 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8282 assert(BasePtr && "Unable to find base lambda address."); 8283 int TgtIdx = -1; 8284 for (unsigned J = I; J > 0; --J) { 8285 unsigned Idx = J - 1; 8286 if (Pointers[Idx] != BasePtr) 8287 continue; 8288 TgtIdx = Idx; 8289 break; 8290 } 8291 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8292 // All other current entries will be MEMBER_OF the combined entry 8293 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8294 // 0xFFFF in the MEMBER_OF field). 8295 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8296 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8297 } 8298 } 8299 8300 /// Generate the base pointers, section pointers, sizes and map types 8301 /// associated to a given capture. 8302 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8303 llvm::Value *Arg, 8304 MapBaseValuesArrayTy &BasePointers, 8305 MapValuesArrayTy &Pointers, 8306 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8307 StructRangeInfoTy &PartialStruct) const { 8308 assert(!Cap->capturesVariableArrayType() && 8309 "Not expecting to generate map info for a variable array type!"); 8310 8311 // We need to know when we generating information for the first component 8312 const ValueDecl *VD = Cap->capturesThis() 8313 ? nullptr 8314 : Cap->getCapturedVar()->getCanonicalDecl(); 8315 8316 // If this declaration appears in a is_device_ptr clause we just have to 8317 // pass the pointer by value. If it is a reference to a declaration, we just 8318 // pass its value. 8319 if (DevPointersMap.count(VD)) { 8320 BasePointers.emplace_back(Arg, VD); 8321 Pointers.push_back(Arg); 8322 Sizes.push_back( 8323 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8324 CGF.Int64Ty, /*isSigned=*/true)); 8325 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8326 return; 8327 } 8328 8329 using MapData = 8330 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8331 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8332 SmallVector<MapData, 4> DeclComponentLists; 8333 assert(CurDir.is<const OMPExecutableDirective *>() && 8334 "Expect a executable directive"); 8335 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8336 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8337 for (const auto &L : C->decl_component_lists(VD)) { 8338 assert(L.first == VD && 8339 "We got information for the wrong declaration??"); 8340 assert(!L.second.empty() && 8341 "Not expecting declaration with no component lists."); 8342 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8343 C->getMapTypeModifiers(), 8344 C->isImplicit()); 8345 } 8346 } 8347 8348 // Find overlapping elements (including the offset from the base element). 8349 llvm::SmallDenseMap< 8350 const MapData *, 8351 llvm::SmallVector< 8352 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8353 4> 8354 OverlappedData; 8355 size_t Count = 0; 8356 for (const MapData &L : DeclComponentLists) { 8357 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8358 OpenMPMapClauseKind MapType; 8359 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8360 bool IsImplicit; 8361 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8362 ++Count; 8363 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8364 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8365 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8366 auto CI = Components.rbegin(); 8367 auto CE = Components.rend(); 8368 auto SI = Components1.rbegin(); 8369 auto SE = Components1.rend(); 8370 for (; CI != CE && SI != SE; ++CI, ++SI) { 8371 if (CI->getAssociatedExpression()->getStmtClass() != 8372 SI->getAssociatedExpression()->getStmtClass()) 8373 break; 8374 // Are we dealing with different variables/fields? 8375 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8376 break; 8377 } 8378 // Found overlapping if, at least for one component, reached the head of 8379 // the components list. 8380 if (CI == CE || SI == SE) { 8381 assert((CI != CE || SI != SE) && 8382 "Unexpected full match of the mapping components."); 8383 const MapData &BaseData = CI == CE ? L : L1; 8384 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8385 SI == SE ? Components : Components1; 8386 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8387 OverlappedElements.getSecond().push_back(SubData); 8388 } 8389 } 8390 } 8391 // Sort the overlapped elements for each item. 8392 llvm::SmallVector<const FieldDecl *, 4> Layout; 8393 if (!OverlappedData.empty()) { 8394 if (const auto *CRD = 8395 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8396 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8397 else { 8398 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8399 Layout.append(RD->field_begin(), RD->field_end()); 8400 } 8401 } 8402 for (auto &Pair : OverlappedData) { 8403 llvm::sort( 8404 Pair.getSecond(), 8405 [&Layout]( 8406 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8407 OMPClauseMappableExprCommon::MappableExprComponentListRef 8408 Second) { 8409 auto CI = First.rbegin(); 8410 auto CE = First.rend(); 8411 auto SI = Second.rbegin(); 8412 auto SE = Second.rend(); 8413 for (; CI != CE && SI != SE; ++CI, ++SI) { 8414 if (CI->getAssociatedExpression()->getStmtClass() != 8415 SI->getAssociatedExpression()->getStmtClass()) 8416 break; 8417 // Are we dealing with different variables/fields? 8418 if (CI->getAssociatedDeclaration() != 8419 SI->getAssociatedDeclaration()) 8420 break; 8421 } 8422 8423 // Lists contain the same elements. 8424 if (CI == CE && SI == SE) 8425 return false; 8426 8427 // List with less elements is less than list with more elements. 8428 if (CI == CE || SI == SE) 8429 return CI == CE; 8430 8431 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8432 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8433 if (FD1->getParent() == FD2->getParent()) 8434 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8435 const auto It = 8436 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8437 return FD == FD1 || FD == FD2; 8438 }); 8439 return *It == FD1; 8440 }); 8441 } 8442 8443 // Associated with a capture, because the mapping flags depend on it. 8444 // Go through all of the elements with the overlapped elements. 8445 for (const auto &Pair : OverlappedData) { 8446 const MapData &L = *Pair.getFirst(); 8447 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8448 OpenMPMapClauseKind MapType; 8449 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8450 bool IsImplicit; 8451 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8452 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8453 OverlappedComponents = Pair.getSecond(); 8454 bool IsFirstComponentList = true; 8455 generateInfoForComponentList(MapType, MapModifiers, Components, 8456 BasePointers, Pointers, Sizes, Types, 8457 PartialStruct, IsFirstComponentList, 8458 IsImplicit, OverlappedComponents); 8459 } 8460 // Go through other elements without overlapped elements. 8461 bool IsFirstComponentList = OverlappedData.empty(); 8462 for (const MapData &L : DeclComponentLists) { 8463 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8464 OpenMPMapClauseKind MapType; 8465 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8466 bool IsImplicit; 8467 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8468 auto It = OverlappedData.find(&L); 8469 if (It == OverlappedData.end()) 8470 generateInfoForComponentList(MapType, MapModifiers, Components, 8471 BasePointers, Pointers, Sizes, Types, 8472 PartialStruct, IsFirstComponentList, 8473 IsImplicit); 8474 IsFirstComponentList = false; 8475 } 8476 } 8477 8478 /// Generate the base pointers, section pointers, sizes and map types 8479 /// associated with the declare target link variables. 8480 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8481 MapValuesArrayTy &Pointers, 8482 MapValuesArrayTy &Sizes, 8483 MapFlagsArrayTy &Types) const { 8484 assert(CurDir.is<const OMPExecutableDirective *>() && 8485 "Expect a executable directive"); 8486 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8487 // Map other list items in the map clause which are not captured variables 8488 // but "declare target link" global variables. 8489 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8490 for (const auto &L : C->component_lists()) { 8491 if (!L.first) 8492 continue; 8493 const auto *VD = dyn_cast<VarDecl>(L.first); 8494 if (!VD) 8495 continue; 8496 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8497 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8498 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8499 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8500 continue; 8501 StructRangeInfoTy PartialStruct; 8502 generateInfoForComponentList( 8503 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8504 Pointers, Sizes, Types, PartialStruct, 8505 /*IsFirstComponentList=*/true, C->isImplicit()); 8506 assert(!PartialStruct.Base.isValid() && 8507 "No partial structs for declare target link expected."); 8508 } 8509 } 8510 } 8511 8512 /// Generate the default map information for a given capture \a CI, 8513 /// record field declaration \a RI and captured value \a CV. 8514 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8515 const FieldDecl &RI, llvm::Value *CV, 8516 MapBaseValuesArrayTy &CurBasePointers, 8517 MapValuesArrayTy &CurPointers, 8518 MapValuesArrayTy &CurSizes, 8519 MapFlagsArrayTy &CurMapTypes) const { 8520 bool IsImplicit = true; 8521 // Do the default mapping. 8522 if (CI.capturesThis()) { 8523 CurBasePointers.push_back(CV); 8524 CurPointers.push_back(CV); 8525 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8526 CurSizes.push_back( 8527 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8528 CGF.Int64Ty, /*isSigned=*/true)); 8529 // Default map type. 8530 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8531 } else if (CI.capturesVariableByCopy()) { 8532 CurBasePointers.push_back(CV); 8533 CurPointers.push_back(CV); 8534 if (!RI.getType()->isAnyPointerType()) { 8535 // We have to signal to the runtime captures passed by value that are 8536 // not pointers. 8537 CurMapTypes.push_back(OMP_MAP_LITERAL); 8538 CurSizes.push_back(CGF.Builder.CreateIntCast( 8539 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8540 } else { 8541 // Pointers are implicitly mapped with a zero size and no flags 8542 // (other than first map that is added for all implicit maps). 8543 CurMapTypes.push_back(OMP_MAP_NONE); 8544 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8545 } 8546 const VarDecl *VD = CI.getCapturedVar(); 8547 auto I = FirstPrivateDecls.find(VD); 8548 if (I != FirstPrivateDecls.end()) 8549 IsImplicit = I->getSecond(); 8550 } else { 8551 assert(CI.capturesVariable() && "Expected captured reference."); 8552 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8553 QualType ElementType = PtrTy->getPointeeType(); 8554 CurSizes.push_back(CGF.Builder.CreateIntCast( 8555 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8556 // The default map type for a scalar/complex type is 'to' because by 8557 // default the value doesn't have to be retrieved. For an aggregate 8558 // type, the default is 'tofrom'. 8559 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8560 const VarDecl *VD = CI.getCapturedVar(); 8561 auto I = FirstPrivateDecls.find(VD); 8562 if (I != FirstPrivateDecls.end() && 8563 VD->getType().isConstant(CGF.getContext())) { 8564 llvm::Constant *Addr = 8565 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8566 // Copy the value of the original variable to the new global copy. 8567 CGF.Builder.CreateMemCpy( 8568 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(), 8569 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8570 CurSizes.back(), /*IsVolatile=*/false); 8571 // Use new global variable as the base pointers. 8572 CurBasePointers.push_back(Addr); 8573 CurPointers.push_back(Addr); 8574 } else { 8575 CurBasePointers.push_back(CV); 8576 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8577 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8578 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8579 AlignmentSource::Decl)); 8580 CurPointers.push_back(PtrAddr.getPointer()); 8581 } else { 8582 CurPointers.push_back(CV); 8583 } 8584 } 8585 if (I != FirstPrivateDecls.end()) 8586 IsImplicit = I->getSecond(); 8587 } 8588 // Every default map produces a single argument which is a target parameter. 8589 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8590 8591 // Add flag stating this is an implicit map. 8592 if (IsImplicit) 8593 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8594 } 8595 }; 8596 } // anonymous namespace 8597 8598 /// Emit the arrays used to pass the captures and map information to the 8599 /// offloading runtime library. If there is no map or capture information, 8600 /// return nullptr by reference. 8601 static void 8602 emitOffloadingArrays(CodeGenFunction &CGF, 8603 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8604 MappableExprsHandler::MapValuesArrayTy &Pointers, 8605 MappableExprsHandler::MapValuesArrayTy &Sizes, 8606 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8607 CGOpenMPRuntime::TargetDataInfo &Info) { 8608 CodeGenModule &CGM = CGF.CGM; 8609 ASTContext &Ctx = CGF.getContext(); 8610 8611 // Reset the array information. 8612 Info.clearArrayInfo(); 8613 Info.NumberOfPtrs = BasePointers.size(); 8614 8615 if (Info.NumberOfPtrs) { 8616 // Detect if we have any capture size requiring runtime evaluation of the 8617 // size so that a constant array could be eventually used. 8618 bool hasRuntimeEvaluationCaptureSize = false; 8619 for (llvm::Value *S : Sizes) 8620 if (!isa<llvm::Constant>(S)) { 8621 hasRuntimeEvaluationCaptureSize = true; 8622 break; 8623 } 8624 8625 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8626 QualType PointerArrayType = 8627 Ctx.getConstantArrayType(Ctx.VoidPtrTy, PointerNumAP, ArrayType::Normal, 8628 /*IndexTypeQuals=*/0); 8629 8630 Info.BasePointersArray = 8631 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8632 Info.PointersArray = 8633 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8634 8635 // If we don't have any VLA types or other types that require runtime 8636 // evaluation, we can use a constant array for the map sizes, otherwise we 8637 // need to fill up the arrays as we do for the pointers. 8638 QualType Int64Ty = 8639 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8640 if (hasRuntimeEvaluationCaptureSize) { 8641 QualType SizeArrayType = 8642 Ctx.getConstantArrayType(Int64Ty, PointerNumAP, ArrayType::Normal, 8643 /*IndexTypeQuals=*/0); 8644 Info.SizesArray = 8645 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8646 } else { 8647 // We expect all the sizes to be constant, so we collect them to create 8648 // a constant array. 8649 SmallVector<llvm::Constant *, 16> ConstSizes; 8650 for (llvm::Value *S : Sizes) 8651 ConstSizes.push_back(cast<llvm::Constant>(S)); 8652 8653 auto *SizesArrayInit = llvm::ConstantArray::get( 8654 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8655 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8656 auto *SizesArrayGbl = new llvm::GlobalVariable( 8657 CGM.getModule(), SizesArrayInit->getType(), 8658 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8659 SizesArrayInit, Name); 8660 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8661 Info.SizesArray = SizesArrayGbl; 8662 } 8663 8664 // The map types are always constant so we don't need to generate code to 8665 // fill arrays. Instead, we create an array constant. 8666 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8667 llvm::copy(MapTypes, Mapping.begin()); 8668 llvm::Constant *MapTypesArrayInit = 8669 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8670 std::string MaptypesName = 8671 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8672 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8673 CGM.getModule(), MapTypesArrayInit->getType(), 8674 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8675 MapTypesArrayInit, MaptypesName); 8676 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8677 Info.MapTypesArray = MapTypesArrayGbl; 8678 8679 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8680 llvm::Value *BPVal = *BasePointers[I]; 8681 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8682 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8683 Info.BasePointersArray, 0, I); 8684 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8685 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8686 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8687 CGF.Builder.CreateStore(BPVal, BPAddr); 8688 8689 if (Info.requiresDevicePointerInfo()) 8690 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8691 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8692 8693 llvm::Value *PVal = Pointers[I]; 8694 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8695 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8696 Info.PointersArray, 0, I); 8697 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8698 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8699 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8700 CGF.Builder.CreateStore(PVal, PAddr); 8701 8702 if (hasRuntimeEvaluationCaptureSize) { 8703 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8704 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8705 Info.SizesArray, 8706 /*Idx0=*/0, 8707 /*Idx1=*/I); 8708 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8709 CGF.Builder.CreateStore( 8710 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8711 SAddr); 8712 } 8713 } 8714 } 8715 } 8716 8717 /// Emit the arguments to be passed to the runtime library based on the 8718 /// arrays of pointers, sizes and map types. 8719 static void emitOffloadingArraysArgument( 8720 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8721 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8722 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8723 CodeGenModule &CGM = CGF.CGM; 8724 if (Info.NumberOfPtrs) { 8725 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8726 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8727 Info.BasePointersArray, 8728 /*Idx0=*/0, /*Idx1=*/0); 8729 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8730 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8731 Info.PointersArray, 8732 /*Idx0=*/0, 8733 /*Idx1=*/0); 8734 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8735 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8736 /*Idx0=*/0, /*Idx1=*/0); 8737 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8738 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8739 Info.MapTypesArray, 8740 /*Idx0=*/0, 8741 /*Idx1=*/0); 8742 } else { 8743 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8744 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8745 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8746 MapTypesArrayArg = 8747 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8748 } 8749 } 8750 8751 /// Check for inner distribute directive. 8752 static const OMPExecutableDirective * 8753 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8754 const auto *CS = D.getInnermostCapturedStmt(); 8755 const auto *Body = 8756 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8757 const Stmt *ChildStmt = 8758 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8759 8760 if (const auto *NestedDir = 8761 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8762 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8763 switch (D.getDirectiveKind()) { 8764 case OMPD_target: 8765 if (isOpenMPDistributeDirective(DKind)) 8766 return NestedDir; 8767 if (DKind == OMPD_teams) { 8768 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8769 /*IgnoreCaptured=*/true); 8770 if (!Body) 8771 return nullptr; 8772 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8773 if (const auto *NND = 8774 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8775 DKind = NND->getDirectiveKind(); 8776 if (isOpenMPDistributeDirective(DKind)) 8777 return NND; 8778 } 8779 } 8780 return nullptr; 8781 case OMPD_target_teams: 8782 if (isOpenMPDistributeDirective(DKind)) 8783 return NestedDir; 8784 return nullptr; 8785 case OMPD_target_parallel: 8786 case OMPD_target_simd: 8787 case OMPD_target_parallel_for: 8788 case OMPD_target_parallel_for_simd: 8789 return nullptr; 8790 case OMPD_target_teams_distribute: 8791 case OMPD_target_teams_distribute_simd: 8792 case OMPD_target_teams_distribute_parallel_for: 8793 case OMPD_target_teams_distribute_parallel_for_simd: 8794 case OMPD_parallel: 8795 case OMPD_for: 8796 case OMPD_parallel_for: 8797 case OMPD_parallel_sections: 8798 case OMPD_for_simd: 8799 case OMPD_parallel_for_simd: 8800 case OMPD_cancel: 8801 case OMPD_cancellation_point: 8802 case OMPD_ordered: 8803 case OMPD_threadprivate: 8804 case OMPD_allocate: 8805 case OMPD_task: 8806 case OMPD_simd: 8807 case OMPD_sections: 8808 case OMPD_section: 8809 case OMPD_single: 8810 case OMPD_master: 8811 case OMPD_critical: 8812 case OMPD_taskyield: 8813 case OMPD_barrier: 8814 case OMPD_taskwait: 8815 case OMPD_taskgroup: 8816 case OMPD_atomic: 8817 case OMPD_flush: 8818 case OMPD_teams: 8819 case OMPD_target_data: 8820 case OMPD_target_exit_data: 8821 case OMPD_target_enter_data: 8822 case OMPD_distribute: 8823 case OMPD_distribute_simd: 8824 case OMPD_distribute_parallel_for: 8825 case OMPD_distribute_parallel_for_simd: 8826 case OMPD_teams_distribute: 8827 case OMPD_teams_distribute_simd: 8828 case OMPD_teams_distribute_parallel_for: 8829 case OMPD_teams_distribute_parallel_for_simd: 8830 case OMPD_target_update: 8831 case OMPD_declare_simd: 8832 case OMPD_declare_variant: 8833 case OMPD_declare_target: 8834 case OMPD_end_declare_target: 8835 case OMPD_declare_reduction: 8836 case OMPD_declare_mapper: 8837 case OMPD_taskloop: 8838 case OMPD_taskloop_simd: 8839 case OMPD_requires: 8840 case OMPD_unknown: 8841 llvm_unreachable("Unexpected directive."); 8842 } 8843 } 8844 8845 return nullptr; 8846 } 8847 8848 /// Emit the user-defined mapper function. The code generation follows the 8849 /// pattern in the example below. 8850 /// \code 8851 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8852 /// void *base, void *begin, 8853 /// int64_t size, int64_t type) { 8854 /// // Allocate space for an array section first. 8855 /// if (size > 1 && !maptype.IsDelete) 8856 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8857 /// size*sizeof(Ty), clearToFrom(type)); 8858 /// // Map members. 8859 /// for (unsigned i = 0; i < size; i++) { 8860 /// // For each component specified by this mapper: 8861 /// for (auto c : all_components) { 8862 /// if (c.hasMapper()) 8863 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8864 /// c.arg_type); 8865 /// else 8866 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8867 /// c.arg_begin, c.arg_size, c.arg_type); 8868 /// } 8869 /// } 8870 /// // Delete the array section. 8871 /// if (size > 1 && maptype.IsDelete) 8872 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8873 /// size*sizeof(Ty), clearToFrom(type)); 8874 /// } 8875 /// \endcode 8876 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8877 CodeGenFunction *CGF) { 8878 if (UDMMap.count(D) > 0) 8879 return; 8880 ASTContext &C = CGM.getContext(); 8881 QualType Ty = D->getType(); 8882 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8883 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8884 auto *MapperVarDecl = 8885 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8886 SourceLocation Loc = D->getLocation(); 8887 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8888 8889 // Prepare mapper function arguments and attributes. 8890 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8891 C.VoidPtrTy, ImplicitParamDecl::Other); 8892 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8893 ImplicitParamDecl::Other); 8894 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8895 C.VoidPtrTy, ImplicitParamDecl::Other); 8896 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8897 ImplicitParamDecl::Other); 8898 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8899 ImplicitParamDecl::Other); 8900 FunctionArgList Args; 8901 Args.push_back(&HandleArg); 8902 Args.push_back(&BaseArg); 8903 Args.push_back(&BeginArg); 8904 Args.push_back(&SizeArg); 8905 Args.push_back(&TypeArg); 8906 const CGFunctionInfo &FnInfo = 8907 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8908 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8909 SmallString<64> TyStr; 8910 llvm::raw_svector_ostream Out(TyStr); 8911 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 8912 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 8913 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 8914 Name, &CGM.getModule()); 8915 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 8916 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 8917 // Start the mapper function code generation. 8918 CodeGenFunction MapperCGF(CGM); 8919 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 8920 // Compute the starting and end addreses of array elements. 8921 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 8922 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 8923 C.getPointerType(Int64Ty), Loc); 8924 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 8925 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 8926 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 8927 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 8928 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 8929 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 8930 C.getPointerType(Int64Ty), Loc); 8931 // Prepare common arguments for array initiation and deletion. 8932 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 8933 MapperCGF.GetAddrOfLocalVar(&HandleArg), 8934 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8935 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 8936 MapperCGF.GetAddrOfLocalVar(&BaseArg), 8937 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8938 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 8939 MapperCGF.GetAddrOfLocalVar(&BeginArg), 8940 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8941 8942 // Emit array initiation if this is an array section and \p MapType indicates 8943 // that memory allocation is required. 8944 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 8945 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8946 ElementSize, HeadBB, /*IsInit=*/true); 8947 8948 // Emit a for loop to iterate through SizeArg of elements and map all of them. 8949 8950 // Emit the loop header block. 8951 MapperCGF.EmitBlock(HeadBB); 8952 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 8953 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 8954 // Evaluate whether the initial condition is satisfied. 8955 llvm::Value *IsEmpty = 8956 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 8957 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 8958 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 8959 8960 // Emit the loop body block. 8961 MapperCGF.EmitBlock(BodyBB); 8962 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 8963 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 8964 PtrPHI->addIncoming(PtrBegin, EntryBB); 8965 Address PtrCurrent = 8966 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 8967 .getAlignment() 8968 .alignmentOfArrayElement(ElementSize)); 8969 // Privatize the declared variable of mapper to be the current array element. 8970 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 8971 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 8972 return MapperCGF 8973 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 8974 .getAddress(); 8975 }); 8976 (void)Scope.Privatize(); 8977 8978 // Get map clause information. Fill up the arrays with all mapped variables. 8979 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 8980 MappableExprsHandler::MapValuesArrayTy Pointers; 8981 MappableExprsHandler::MapValuesArrayTy Sizes; 8982 MappableExprsHandler::MapFlagsArrayTy MapTypes; 8983 MappableExprsHandler MEHandler(*D, MapperCGF); 8984 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 8985 8986 // Call the runtime API __tgt_mapper_num_components to get the number of 8987 // pre-existing components. 8988 llvm::Value *OffloadingArgs[] = {Handle}; 8989 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 8990 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 8991 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 8992 PreviousSize, 8993 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 8994 8995 // Fill up the runtime mapper handle for all components. 8996 for (unsigned I = 0; I < BasePointers.size(); ++I) { 8997 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 8998 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8999 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9000 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9001 llvm::Value *CurSizeArg = Sizes[I]; 9002 9003 // Extract the MEMBER_OF field from the map type. 9004 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 9005 MapperCGF.EmitBlock(MemberBB); 9006 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 9007 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 9008 OriMapType, 9009 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 9010 llvm::BasicBlock *MemberCombineBB = 9011 MapperCGF.createBasicBlock("omp.member.combine"); 9012 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 9013 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 9014 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 9015 // Add the number of pre-existing components to the MEMBER_OF field if it 9016 // is valid. 9017 MapperCGF.EmitBlock(MemberCombineBB); 9018 llvm::Value *CombinedMember = 9019 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9020 // Do nothing if it is not a member of previous components. 9021 MapperCGF.EmitBlock(TypeBB); 9022 llvm::PHINode *MemberMapType = 9023 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 9024 MemberMapType->addIncoming(OriMapType, MemberBB); 9025 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 9026 9027 // Combine the map type inherited from user-defined mapper with that 9028 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9029 // bits of the \a MapType, which is the input argument of the mapper 9030 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9031 // bits of MemberMapType. 9032 // [OpenMP 5.0], 1.2.6. map-type decay. 9033 // | alloc | to | from | tofrom | release | delete 9034 // ---------------------------------------------------------- 9035 // alloc | alloc | alloc | alloc | alloc | release | delete 9036 // to | alloc | to | alloc | to | release | delete 9037 // from | alloc | alloc | from | from | release | delete 9038 // tofrom | alloc | to | from | tofrom | release | delete 9039 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9040 MapType, 9041 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9042 MappableExprsHandler::OMP_MAP_FROM)); 9043 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9044 llvm::BasicBlock *AllocElseBB = 9045 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9046 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9047 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9048 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9049 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9050 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9051 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9052 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9053 MapperCGF.EmitBlock(AllocBB); 9054 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9055 MemberMapType, 9056 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9057 MappableExprsHandler::OMP_MAP_FROM))); 9058 MapperCGF.Builder.CreateBr(EndBB); 9059 MapperCGF.EmitBlock(AllocElseBB); 9060 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9061 LeftToFrom, 9062 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9063 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9064 // In case of to, clear OMP_MAP_FROM. 9065 MapperCGF.EmitBlock(ToBB); 9066 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9067 MemberMapType, 9068 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9069 MapperCGF.Builder.CreateBr(EndBB); 9070 MapperCGF.EmitBlock(ToElseBB); 9071 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9072 LeftToFrom, 9073 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9074 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9075 // In case of from, clear OMP_MAP_TO. 9076 MapperCGF.EmitBlock(FromBB); 9077 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9078 MemberMapType, 9079 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9080 // In case of tofrom, do nothing. 9081 MapperCGF.EmitBlock(EndBB); 9082 llvm::PHINode *CurMapType = 9083 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9084 CurMapType->addIncoming(AllocMapType, AllocBB); 9085 CurMapType->addIncoming(ToMapType, ToBB); 9086 CurMapType->addIncoming(FromMapType, FromBB); 9087 CurMapType->addIncoming(MemberMapType, ToElseBB); 9088 9089 // TODO: call the corresponding mapper function if a user-defined mapper is 9090 // associated with this map clause. 9091 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9092 // data structure. 9093 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9094 CurSizeArg, CurMapType}; 9095 MapperCGF.EmitRuntimeCall( 9096 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9097 OffloadingArgs); 9098 } 9099 9100 // Update the pointer to point to the next element that needs to be mapped, 9101 // and check whether we have mapped all elements. 9102 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9103 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9104 PtrPHI->addIncoming(PtrNext, BodyBB); 9105 llvm::Value *IsDone = 9106 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9107 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9108 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9109 9110 MapperCGF.EmitBlock(ExitBB); 9111 // Emit array deletion if this is an array section and \p MapType indicates 9112 // that deletion is required. 9113 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9114 ElementSize, DoneBB, /*IsInit=*/false); 9115 9116 // Emit the function exit block. 9117 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9118 MapperCGF.FinishFunction(); 9119 UDMMap.try_emplace(D, Fn); 9120 if (CGF) { 9121 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9122 Decls.second.push_back(D); 9123 } 9124 } 9125 9126 /// Emit the array initialization or deletion portion for user-defined mapper 9127 /// code generation. First, it evaluates whether an array section is mapped and 9128 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9129 /// true, and \a MapType indicates to not delete this array, array 9130 /// initialization code is generated. If \a IsInit is false, and \a MapType 9131 /// indicates to not this array, array deletion code is generated. 9132 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9133 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9134 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9135 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9136 StringRef Prefix = IsInit ? ".init" : ".del"; 9137 9138 // Evaluate if this is an array section. 9139 llvm::BasicBlock *IsDeleteBB = 9140 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete"); 9141 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix); 9142 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9143 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9144 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9145 9146 // Evaluate if we are going to delete this section. 9147 MapperCGF.EmitBlock(IsDeleteBB); 9148 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9149 MapType, 9150 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9151 llvm::Value *DeleteCond; 9152 if (IsInit) { 9153 DeleteCond = MapperCGF.Builder.CreateIsNull( 9154 DeleteBit, "omp.array" + Prefix + ".delete"); 9155 } else { 9156 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9157 DeleteBit, "omp.array" + Prefix + ".delete"); 9158 } 9159 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9160 9161 MapperCGF.EmitBlock(BodyBB); 9162 // Get the array size by multiplying element size and element number (i.e., \p 9163 // Size). 9164 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9165 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9166 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9167 // memory allocation/deletion purpose only. 9168 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9169 MapType, 9170 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9171 MappableExprsHandler::OMP_MAP_FROM))); 9172 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9173 // data structure. 9174 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9175 MapperCGF.EmitRuntimeCall( 9176 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9177 } 9178 9179 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9180 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9181 llvm::Value *DeviceID, 9182 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9183 const OMPLoopDirective &D)> 9184 SizeEmitter) { 9185 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9186 const OMPExecutableDirective *TD = &D; 9187 // Get nested teams distribute kind directive, if any. 9188 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9189 TD = getNestedDistributeDirective(CGM.getContext(), D); 9190 if (!TD) 9191 return; 9192 const auto *LD = cast<OMPLoopDirective>(TD); 9193 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9194 PrePostActionTy &) { 9195 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9196 llvm::Value *Args[] = {DeviceID, NumIterations}; 9197 CGF.EmitRuntimeCall( 9198 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9199 } 9200 }; 9201 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9202 } 9203 9204 void CGOpenMPRuntime::emitTargetCall( 9205 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9206 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9207 const Expr *Device, 9208 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9209 const OMPLoopDirective &D)> 9210 SizeEmitter) { 9211 if (!CGF.HaveInsertPoint()) 9212 return; 9213 9214 assert(OutlinedFn && "Invalid outlined function!"); 9215 9216 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9217 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9218 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9219 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9220 PrePostActionTy &) { 9221 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9222 }; 9223 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9224 9225 CodeGenFunction::OMPTargetDataInfo InputInfo; 9226 llvm::Value *MapTypesArray = nullptr; 9227 // Fill up the pointer arrays and transfer execution to the device. 9228 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9229 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9230 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9231 // On top of the arrays that were filled up, the target offloading call 9232 // takes as arguments the device id as well as the host pointer. The host 9233 // pointer is used by the runtime library to identify the current target 9234 // region, so it only has to be unique and not necessarily point to 9235 // anything. It could be the pointer to the outlined function that 9236 // implements the target region, but we aren't using that so that the 9237 // compiler doesn't need to keep that, and could therefore inline the host 9238 // function if proven worthwhile during optimization. 9239 9240 // From this point on, we need to have an ID of the target region defined. 9241 assert(OutlinedFnID && "Invalid outlined function ID!"); 9242 9243 // Emit device ID if any. 9244 llvm::Value *DeviceID; 9245 if (Device) { 9246 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9247 CGF.Int64Ty, /*isSigned=*/true); 9248 } else { 9249 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9250 } 9251 9252 // Emit the number of elements in the offloading arrays. 9253 llvm::Value *PointerNum = 9254 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9255 9256 // Return value of the runtime offloading call. 9257 llvm::Value *Return; 9258 9259 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9260 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9261 9262 // Emit tripcount for the target loop-based directive. 9263 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9264 9265 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9266 // The target region is an outlined function launched by the runtime 9267 // via calls __tgt_target() or __tgt_target_teams(). 9268 // 9269 // __tgt_target() launches a target region with one team and one thread, 9270 // executing a serial region. This master thread may in turn launch 9271 // more threads within its team upon encountering a parallel region, 9272 // however, no additional teams can be launched on the device. 9273 // 9274 // __tgt_target_teams() launches a target region with one or more teams, 9275 // each with one or more threads. This call is required for target 9276 // constructs such as: 9277 // 'target teams' 9278 // 'target' / 'teams' 9279 // 'target teams distribute parallel for' 9280 // 'target parallel' 9281 // and so on. 9282 // 9283 // Note that on the host and CPU targets, the runtime implementation of 9284 // these calls simply call the outlined function without forking threads. 9285 // The outlined functions themselves have runtime calls to 9286 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9287 // the compiler in emitTeamsCall() and emitParallelCall(). 9288 // 9289 // In contrast, on the NVPTX target, the implementation of 9290 // __tgt_target_teams() launches a GPU kernel with the requested number 9291 // of teams and threads so no additional calls to the runtime are required. 9292 if (NumTeams) { 9293 // If we have NumTeams defined this means that we have an enclosed teams 9294 // region. Therefore we also expect to have NumThreads defined. These two 9295 // values should be defined in the presence of a teams directive, 9296 // regardless of having any clauses associated. If the user is using teams 9297 // but no clauses, these two values will be the default that should be 9298 // passed to the runtime library - a 32-bit integer with the value zero. 9299 assert(NumThreads && "Thread limit expression should be available along " 9300 "with number of teams."); 9301 llvm::Value *OffloadingArgs[] = {DeviceID, 9302 OutlinedFnID, 9303 PointerNum, 9304 InputInfo.BasePointersArray.getPointer(), 9305 InputInfo.PointersArray.getPointer(), 9306 InputInfo.SizesArray.getPointer(), 9307 MapTypesArray, 9308 NumTeams, 9309 NumThreads}; 9310 Return = CGF.EmitRuntimeCall( 9311 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9312 : OMPRTL__tgt_target_teams), 9313 OffloadingArgs); 9314 } else { 9315 llvm::Value *OffloadingArgs[] = {DeviceID, 9316 OutlinedFnID, 9317 PointerNum, 9318 InputInfo.BasePointersArray.getPointer(), 9319 InputInfo.PointersArray.getPointer(), 9320 InputInfo.SizesArray.getPointer(), 9321 MapTypesArray}; 9322 Return = CGF.EmitRuntimeCall( 9323 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9324 : OMPRTL__tgt_target), 9325 OffloadingArgs); 9326 } 9327 9328 // Check the error code and execute the host version if required. 9329 llvm::BasicBlock *OffloadFailedBlock = 9330 CGF.createBasicBlock("omp_offload.failed"); 9331 llvm::BasicBlock *OffloadContBlock = 9332 CGF.createBasicBlock("omp_offload.cont"); 9333 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9334 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9335 9336 CGF.EmitBlock(OffloadFailedBlock); 9337 if (RequiresOuterTask) { 9338 CapturedVars.clear(); 9339 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9340 } 9341 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9342 CGF.EmitBranch(OffloadContBlock); 9343 9344 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9345 }; 9346 9347 // Notify that the host version must be executed. 9348 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9349 RequiresOuterTask](CodeGenFunction &CGF, 9350 PrePostActionTy &) { 9351 if (RequiresOuterTask) { 9352 CapturedVars.clear(); 9353 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9354 } 9355 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9356 }; 9357 9358 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9359 &CapturedVars, RequiresOuterTask, 9360 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9361 // Fill up the arrays with all the captured variables. 9362 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9363 MappableExprsHandler::MapValuesArrayTy Pointers; 9364 MappableExprsHandler::MapValuesArrayTy Sizes; 9365 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9366 9367 // Get mappable expression information. 9368 MappableExprsHandler MEHandler(D, CGF); 9369 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9370 9371 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9372 auto CV = CapturedVars.begin(); 9373 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9374 CE = CS.capture_end(); 9375 CI != CE; ++CI, ++RI, ++CV) { 9376 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9377 MappableExprsHandler::MapValuesArrayTy CurPointers; 9378 MappableExprsHandler::MapValuesArrayTy CurSizes; 9379 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9380 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9381 9382 // VLA sizes are passed to the outlined region by copy and do not have map 9383 // information associated. 9384 if (CI->capturesVariableArrayType()) { 9385 CurBasePointers.push_back(*CV); 9386 CurPointers.push_back(*CV); 9387 CurSizes.push_back(CGF.Builder.CreateIntCast( 9388 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9389 // Copy to the device as an argument. No need to retrieve it. 9390 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9391 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9392 MappableExprsHandler::OMP_MAP_IMPLICIT); 9393 } else { 9394 // If we have any information in the map clause, we use it, otherwise we 9395 // just do a default mapping. 9396 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9397 CurSizes, CurMapTypes, PartialStruct); 9398 if (CurBasePointers.empty()) 9399 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9400 CurPointers, CurSizes, CurMapTypes); 9401 // Generate correct mapping for variables captured by reference in 9402 // lambdas. 9403 if (CI->capturesVariable()) 9404 MEHandler.generateInfoForLambdaCaptures( 9405 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9406 CurMapTypes, LambdaPointers); 9407 } 9408 // We expect to have at least an element of information for this capture. 9409 assert(!CurBasePointers.empty() && 9410 "Non-existing map pointer for capture!"); 9411 assert(CurBasePointers.size() == CurPointers.size() && 9412 CurBasePointers.size() == CurSizes.size() && 9413 CurBasePointers.size() == CurMapTypes.size() && 9414 "Inconsistent map information sizes!"); 9415 9416 // If there is an entry in PartialStruct it means we have a struct with 9417 // individual members mapped. Emit an extra combined entry. 9418 if (PartialStruct.Base.isValid()) 9419 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9420 CurMapTypes, PartialStruct); 9421 9422 // We need to append the results of this capture to what we already have. 9423 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9424 Pointers.append(CurPointers.begin(), CurPointers.end()); 9425 Sizes.append(CurSizes.begin(), CurSizes.end()); 9426 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9427 } 9428 // Adjust MEMBER_OF flags for the lambdas captures. 9429 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9430 Pointers, MapTypes); 9431 // Map other list items in the map clause which are not captured variables 9432 // but "declare target link" global variables. 9433 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9434 MapTypes); 9435 9436 TargetDataInfo Info; 9437 // Fill up the arrays and create the arguments. 9438 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9439 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9440 Info.PointersArray, Info.SizesArray, 9441 Info.MapTypesArray, Info); 9442 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9443 InputInfo.BasePointersArray = 9444 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9445 InputInfo.PointersArray = 9446 Address(Info.PointersArray, CGM.getPointerAlign()); 9447 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9448 MapTypesArray = Info.MapTypesArray; 9449 if (RequiresOuterTask) 9450 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9451 else 9452 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9453 }; 9454 9455 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9456 CodeGenFunction &CGF, PrePostActionTy &) { 9457 if (RequiresOuterTask) { 9458 CodeGenFunction::OMPTargetDataInfo InputInfo; 9459 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9460 } else { 9461 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9462 } 9463 }; 9464 9465 // If we have a target function ID it means that we need to support 9466 // offloading, otherwise, just execute on the host. We need to execute on host 9467 // regardless of the conditional in the if clause if, e.g., the user do not 9468 // specify target triples. 9469 if (OutlinedFnID) { 9470 if (IfCond) { 9471 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9472 } else { 9473 RegionCodeGenTy ThenRCG(TargetThenGen); 9474 ThenRCG(CGF); 9475 } 9476 } else { 9477 RegionCodeGenTy ElseRCG(TargetElseGen); 9478 ElseRCG(CGF); 9479 } 9480 } 9481 9482 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9483 StringRef ParentName) { 9484 if (!S) 9485 return; 9486 9487 // Codegen OMP target directives that offload compute to the device. 9488 bool RequiresDeviceCodegen = 9489 isa<OMPExecutableDirective>(S) && 9490 isOpenMPTargetExecutionDirective( 9491 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9492 9493 if (RequiresDeviceCodegen) { 9494 const auto &E = *cast<OMPExecutableDirective>(S); 9495 unsigned DeviceID; 9496 unsigned FileID; 9497 unsigned Line; 9498 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9499 FileID, Line); 9500 9501 // Is this a target region that should not be emitted as an entry point? If 9502 // so just signal we are done with this target region. 9503 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9504 ParentName, Line)) 9505 return; 9506 9507 switch (E.getDirectiveKind()) { 9508 case OMPD_target: 9509 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9510 cast<OMPTargetDirective>(E)); 9511 break; 9512 case OMPD_target_parallel: 9513 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9514 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9515 break; 9516 case OMPD_target_teams: 9517 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9518 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9519 break; 9520 case OMPD_target_teams_distribute: 9521 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9522 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9523 break; 9524 case OMPD_target_teams_distribute_simd: 9525 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9526 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9527 break; 9528 case OMPD_target_parallel_for: 9529 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9530 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9531 break; 9532 case OMPD_target_parallel_for_simd: 9533 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9534 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9535 break; 9536 case OMPD_target_simd: 9537 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9538 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9539 break; 9540 case OMPD_target_teams_distribute_parallel_for: 9541 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9542 CGM, ParentName, 9543 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9544 break; 9545 case OMPD_target_teams_distribute_parallel_for_simd: 9546 CodeGenFunction:: 9547 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9548 CGM, ParentName, 9549 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9550 break; 9551 case OMPD_parallel: 9552 case OMPD_for: 9553 case OMPD_parallel_for: 9554 case OMPD_parallel_sections: 9555 case OMPD_for_simd: 9556 case OMPD_parallel_for_simd: 9557 case OMPD_cancel: 9558 case OMPD_cancellation_point: 9559 case OMPD_ordered: 9560 case OMPD_threadprivate: 9561 case OMPD_allocate: 9562 case OMPD_task: 9563 case OMPD_simd: 9564 case OMPD_sections: 9565 case OMPD_section: 9566 case OMPD_single: 9567 case OMPD_master: 9568 case OMPD_critical: 9569 case OMPD_taskyield: 9570 case OMPD_barrier: 9571 case OMPD_taskwait: 9572 case OMPD_taskgroup: 9573 case OMPD_atomic: 9574 case OMPD_flush: 9575 case OMPD_teams: 9576 case OMPD_target_data: 9577 case OMPD_target_exit_data: 9578 case OMPD_target_enter_data: 9579 case OMPD_distribute: 9580 case OMPD_distribute_simd: 9581 case OMPD_distribute_parallel_for: 9582 case OMPD_distribute_parallel_for_simd: 9583 case OMPD_teams_distribute: 9584 case OMPD_teams_distribute_simd: 9585 case OMPD_teams_distribute_parallel_for: 9586 case OMPD_teams_distribute_parallel_for_simd: 9587 case OMPD_target_update: 9588 case OMPD_declare_simd: 9589 case OMPD_declare_variant: 9590 case OMPD_declare_target: 9591 case OMPD_end_declare_target: 9592 case OMPD_declare_reduction: 9593 case OMPD_declare_mapper: 9594 case OMPD_taskloop: 9595 case OMPD_taskloop_simd: 9596 case OMPD_requires: 9597 case OMPD_unknown: 9598 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9599 } 9600 return; 9601 } 9602 9603 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9604 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9605 return; 9606 9607 scanForTargetRegionsFunctions( 9608 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9609 return; 9610 } 9611 9612 // If this is a lambda function, look into its body. 9613 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9614 S = L->getBody(); 9615 9616 // Keep looking for target regions recursively. 9617 for (const Stmt *II : S->children()) 9618 scanForTargetRegionsFunctions(II, ParentName); 9619 } 9620 9621 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9622 // If emitting code for the host, we do not process FD here. Instead we do 9623 // the normal code generation. 9624 if (!CGM.getLangOpts().OpenMPIsDevice) { 9625 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9626 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9627 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9628 // Do not emit device_type(nohost) functions for the host. 9629 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9630 return true; 9631 } 9632 return false; 9633 } 9634 9635 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9636 StringRef Name = CGM.getMangledName(GD); 9637 // Try to detect target regions in the function. 9638 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9639 scanForTargetRegionsFunctions(FD->getBody(), Name); 9640 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9641 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9642 // Do not emit device_type(nohost) functions for the host. 9643 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9644 return true; 9645 } 9646 9647 // Do not to emit function if it is not marked as declare target. 9648 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9649 AlreadyEmittedTargetFunctions.count(Name) == 0; 9650 } 9651 9652 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9653 if (!CGM.getLangOpts().OpenMPIsDevice) 9654 return false; 9655 9656 // Check if there are Ctors/Dtors in this declaration and look for target 9657 // regions in it. We use the complete variant to produce the kernel name 9658 // mangling. 9659 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9660 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9661 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9662 StringRef ParentName = 9663 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9664 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9665 } 9666 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9667 StringRef ParentName = 9668 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9669 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9670 } 9671 } 9672 9673 // Do not to emit variable if it is not marked as declare target. 9674 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9675 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9676 cast<VarDecl>(GD.getDecl())); 9677 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9678 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9679 HasRequiresUnifiedSharedMemory)) { 9680 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9681 return true; 9682 } 9683 return false; 9684 } 9685 9686 llvm::Constant * 9687 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9688 const VarDecl *VD) { 9689 assert(VD->getType().isConstant(CGM.getContext()) && 9690 "Expected constant variable."); 9691 StringRef VarName; 9692 llvm::Constant *Addr; 9693 llvm::GlobalValue::LinkageTypes Linkage; 9694 QualType Ty = VD->getType(); 9695 SmallString<128> Buffer; 9696 { 9697 unsigned DeviceID; 9698 unsigned FileID; 9699 unsigned Line; 9700 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9701 FileID, Line); 9702 llvm::raw_svector_ostream OS(Buffer); 9703 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9704 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9705 VarName = OS.str(); 9706 } 9707 Linkage = llvm::GlobalValue::InternalLinkage; 9708 Addr = 9709 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9710 getDefaultFirstprivateAddressSpace()); 9711 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9712 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9713 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9714 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9715 VarName, Addr, VarSize, 9716 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9717 return Addr; 9718 } 9719 9720 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9721 llvm::Constant *Addr) { 9722 if (CGM.getLangOpts().OMPTargetTriples.empty()) 9723 return; 9724 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9725 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9726 if (!Res) { 9727 if (CGM.getLangOpts().OpenMPIsDevice) { 9728 // Register non-target variables being emitted in device code (debug info 9729 // may cause this). 9730 StringRef VarName = CGM.getMangledName(VD); 9731 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9732 } 9733 return; 9734 } 9735 // Register declare target variables. 9736 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9737 StringRef VarName; 9738 CharUnits VarSize; 9739 llvm::GlobalValue::LinkageTypes Linkage; 9740 9741 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9742 !HasRequiresUnifiedSharedMemory) { 9743 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9744 VarName = CGM.getMangledName(VD); 9745 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9746 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9747 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9748 } else { 9749 VarSize = CharUnits::Zero(); 9750 } 9751 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9752 // Temp solution to prevent optimizations of the internal variables. 9753 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9754 std::string RefName = getName({VarName, "ref"}); 9755 if (!CGM.GetGlobalValue(RefName)) { 9756 llvm::Constant *AddrRef = 9757 getOrCreateInternalVariable(Addr->getType(), RefName); 9758 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9759 GVAddrRef->setConstant(/*Val=*/true); 9760 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9761 GVAddrRef->setInitializer(Addr); 9762 CGM.addCompilerUsedGlobal(GVAddrRef); 9763 } 9764 } 9765 } else { 9766 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9767 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9768 HasRequiresUnifiedSharedMemory)) && 9769 "Declare target attribute must link or to with unified memory."); 9770 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9771 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9772 else 9773 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9774 9775 if (CGM.getLangOpts().OpenMPIsDevice) { 9776 VarName = Addr->getName(); 9777 Addr = nullptr; 9778 } else { 9779 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9780 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9781 } 9782 VarSize = CGM.getPointerSize(); 9783 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9784 } 9785 9786 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9787 VarName, Addr, VarSize, Flags, Linkage); 9788 } 9789 9790 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9791 if (isa<FunctionDecl>(GD.getDecl()) || 9792 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9793 return emitTargetFunctions(GD); 9794 9795 return emitTargetGlobalVariable(GD); 9796 } 9797 9798 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9799 for (const VarDecl *VD : DeferredGlobalVariables) { 9800 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9801 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9802 if (!Res) 9803 continue; 9804 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9805 !HasRequiresUnifiedSharedMemory) { 9806 CGM.EmitGlobal(VD); 9807 } else { 9808 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9809 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9810 HasRequiresUnifiedSharedMemory)) && 9811 "Expected link clause or to clause with unified memory."); 9812 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9813 } 9814 } 9815 } 9816 9817 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9818 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9819 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9820 " Expected target-based directive."); 9821 } 9822 9823 void CGOpenMPRuntime::checkArchForUnifiedAddressing( 9824 const OMPRequiresDecl *D) { 9825 for (const OMPClause *Clause : D->clauselists()) { 9826 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9827 HasRequiresUnifiedSharedMemory = true; 9828 break; 9829 } 9830 } 9831 } 9832 9833 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9834 LangAS &AS) { 9835 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9836 return false; 9837 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9838 switch(A->getAllocatorType()) { 9839 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9840 // Not supported, fallback to the default mem space. 9841 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9842 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9843 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9844 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9845 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9846 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9847 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9848 AS = LangAS::Default; 9849 return true; 9850 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9851 llvm_unreachable("Expected predefined allocator for the variables with the " 9852 "static storage."); 9853 } 9854 return false; 9855 } 9856 9857 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9858 return HasRequiresUnifiedSharedMemory; 9859 } 9860 9861 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9862 CodeGenModule &CGM) 9863 : CGM(CGM) { 9864 if (CGM.getLangOpts().OpenMPIsDevice) { 9865 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9866 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9867 } 9868 } 9869 9870 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9871 if (CGM.getLangOpts().OpenMPIsDevice) 9872 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9873 } 9874 9875 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9876 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9877 return true; 9878 9879 StringRef Name = CGM.getMangledName(GD); 9880 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9881 // Do not to emit function if it is marked as declare target as it was already 9882 // emitted. 9883 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9884 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) { 9885 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name))) 9886 return !F->isDeclaration(); 9887 return false; 9888 } 9889 return true; 9890 } 9891 9892 return !AlreadyEmittedTargetFunctions.insert(Name).second; 9893 } 9894 9895 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9896 // If we don't have entries or if we are emitting code for the device, we 9897 // don't need to do anything. 9898 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9899 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9900 (OffloadEntriesInfoManager.empty() && 9901 !HasEmittedDeclareTargetRegion && 9902 !HasEmittedTargetRegion)) 9903 return nullptr; 9904 9905 // Create and register the function that handles the requires directives. 9906 ASTContext &C = CGM.getContext(); 9907 9908 llvm::Function *RequiresRegFn; 9909 { 9910 CodeGenFunction CGF(CGM); 9911 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9912 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9913 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9914 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9915 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9916 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9917 // TODO: check for other requires clauses. 9918 // The requires directive takes effect only when a target region is 9919 // present in the compilation unit. Otherwise it is ignored and not 9920 // passed to the runtime. This avoids the runtime from throwing an error 9921 // for mismatching requires clauses across compilation units that don't 9922 // contain at least 1 target region. 9923 assert((HasEmittedTargetRegion || 9924 HasEmittedDeclareTargetRegion || 9925 !OffloadEntriesInfoManager.empty()) && 9926 "Target or declare target region expected."); 9927 if (HasRequiresUnifiedSharedMemory) 9928 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9929 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 9930 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9931 CGF.FinishFunction(); 9932 } 9933 return RequiresRegFn; 9934 } 9935 9936 llvm::Function *CGOpenMPRuntime::emitRegistrationFunction() { 9937 // If we have offloading in the current module, we need to emit the entries 9938 // now and register the offloading descriptor. 9939 createOffloadEntriesAndInfoMetadata(); 9940 9941 // Create and register the offloading binary descriptors. This is the main 9942 // entity that captures all the information about offloading in the current 9943 // compilation unit. 9944 return createOffloadingBinaryDescriptorRegistration(); 9945 } 9946 9947 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9948 const OMPExecutableDirective &D, 9949 SourceLocation Loc, 9950 llvm::Function *OutlinedFn, 9951 ArrayRef<llvm::Value *> CapturedVars) { 9952 if (!CGF.HaveInsertPoint()) 9953 return; 9954 9955 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9956 CodeGenFunction::RunCleanupsScope Scope(CGF); 9957 9958 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9959 llvm::Value *Args[] = { 9960 RTLoc, 9961 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9962 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9963 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9964 RealArgs.append(std::begin(Args), std::end(Args)); 9965 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9966 9967 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 9968 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9969 } 9970 9971 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9972 const Expr *NumTeams, 9973 const Expr *ThreadLimit, 9974 SourceLocation Loc) { 9975 if (!CGF.HaveInsertPoint()) 9976 return; 9977 9978 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9979 9980 llvm::Value *NumTeamsVal = 9981 NumTeams 9982 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9983 CGF.CGM.Int32Ty, /* isSigned = */ true) 9984 : CGF.Builder.getInt32(0); 9985 9986 llvm::Value *ThreadLimitVal = 9987 ThreadLimit 9988 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 9989 CGF.CGM.Int32Ty, /* isSigned = */ true) 9990 : CGF.Builder.getInt32(0); 9991 9992 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 9993 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 9994 ThreadLimitVal}; 9995 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 9996 PushNumTeamsArgs); 9997 } 9998 9999 void CGOpenMPRuntime::emitTargetDataCalls( 10000 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10001 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 10002 if (!CGF.HaveInsertPoint()) 10003 return; 10004 10005 // Action used to replace the default codegen action and turn privatization 10006 // off. 10007 PrePostActionTy NoPrivAction; 10008 10009 // Generate the code for the opening of the data environment. Capture all the 10010 // arguments of the runtime call by reference because they are used in the 10011 // closing of the region. 10012 auto &&BeginThenGen = [this, &D, Device, &Info, 10013 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 10014 // Fill up the arrays with all the mapped variables. 10015 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10016 MappableExprsHandler::MapValuesArrayTy Pointers; 10017 MappableExprsHandler::MapValuesArrayTy Sizes; 10018 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10019 10020 // Get map clause information. 10021 MappableExprsHandler MCHandler(D, CGF); 10022 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10023 10024 // Fill up the arrays and create the arguments. 10025 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10026 10027 llvm::Value *BasePointersArrayArg = nullptr; 10028 llvm::Value *PointersArrayArg = nullptr; 10029 llvm::Value *SizesArrayArg = nullptr; 10030 llvm::Value *MapTypesArrayArg = nullptr; 10031 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10032 SizesArrayArg, MapTypesArrayArg, Info); 10033 10034 // Emit device ID if any. 10035 llvm::Value *DeviceID = nullptr; 10036 if (Device) { 10037 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10038 CGF.Int64Ty, /*isSigned=*/true); 10039 } else { 10040 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10041 } 10042 10043 // Emit the number of elements in the offloading arrays. 10044 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10045 10046 llvm::Value *OffloadingArgs[] = { 10047 DeviceID, PointerNum, BasePointersArrayArg, 10048 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10049 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 10050 OffloadingArgs); 10051 10052 // If device pointer privatization is required, emit the body of the region 10053 // here. It will have to be duplicated: with and without privatization. 10054 if (!Info.CaptureDeviceAddrMap.empty()) 10055 CodeGen(CGF); 10056 }; 10057 10058 // Generate code for the closing of the data region. 10059 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10060 PrePostActionTy &) { 10061 assert(Info.isValid() && "Invalid data environment closing arguments."); 10062 10063 llvm::Value *BasePointersArrayArg = nullptr; 10064 llvm::Value *PointersArrayArg = nullptr; 10065 llvm::Value *SizesArrayArg = nullptr; 10066 llvm::Value *MapTypesArrayArg = nullptr; 10067 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10068 SizesArrayArg, MapTypesArrayArg, Info); 10069 10070 // Emit device ID if any. 10071 llvm::Value *DeviceID = nullptr; 10072 if (Device) { 10073 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10074 CGF.Int64Ty, /*isSigned=*/true); 10075 } else { 10076 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10077 } 10078 10079 // Emit the number of elements in the offloading arrays. 10080 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10081 10082 llvm::Value *OffloadingArgs[] = { 10083 DeviceID, PointerNum, BasePointersArrayArg, 10084 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10085 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10086 OffloadingArgs); 10087 }; 10088 10089 // If we need device pointer privatization, we need to emit the body of the 10090 // region with no privatization in the 'else' branch of the conditional. 10091 // Otherwise, we don't have to do anything. 10092 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10093 PrePostActionTy &) { 10094 if (!Info.CaptureDeviceAddrMap.empty()) { 10095 CodeGen.setAction(NoPrivAction); 10096 CodeGen(CGF); 10097 } 10098 }; 10099 10100 // We don't have to do anything to close the region if the if clause evaluates 10101 // to false. 10102 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10103 10104 if (IfCond) { 10105 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10106 } else { 10107 RegionCodeGenTy RCG(BeginThenGen); 10108 RCG(CGF); 10109 } 10110 10111 // If we don't require privatization of device pointers, we emit the body in 10112 // between the runtime calls. This avoids duplicating the body code. 10113 if (Info.CaptureDeviceAddrMap.empty()) { 10114 CodeGen.setAction(NoPrivAction); 10115 CodeGen(CGF); 10116 } 10117 10118 if (IfCond) { 10119 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10120 } else { 10121 RegionCodeGenTy RCG(EndThenGen); 10122 RCG(CGF); 10123 } 10124 } 10125 10126 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10127 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10128 const Expr *Device) { 10129 if (!CGF.HaveInsertPoint()) 10130 return; 10131 10132 assert((isa<OMPTargetEnterDataDirective>(D) || 10133 isa<OMPTargetExitDataDirective>(D) || 10134 isa<OMPTargetUpdateDirective>(D)) && 10135 "Expecting either target enter, exit data, or update directives."); 10136 10137 CodeGenFunction::OMPTargetDataInfo InputInfo; 10138 llvm::Value *MapTypesArray = nullptr; 10139 // Generate the code for the opening of the data environment. 10140 auto &&ThenGen = [this, &D, Device, &InputInfo, 10141 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10142 // Emit device ID if any. 10143 llvm::Value *DeviceID = nullptr; 10144 if (Device) { 10145 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10146 CGF.Int64Ty, /*isSigned=*/true); 10147 } else { 10148 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10149 } 10150 10151 // Emit the number of elements in the offloading arrays. 10152 llvm::Constant *PointerNum = 10153 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10154 10155 llvm::Value *OffloadingArgs[] = {DeviceID, 10156 PointerNum, 10157 InputInfo.BasePointersArray.getPointer(), 10158 InputInfo.PointersArray.getPointer(), 10159 InputInfo.SizesArray.getPointer(), 10160 MapTypesArray}; 10161 10162 // Select the right runtime function call for each expected standalone 10163 // directive. 10164 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10165 OpenMPRTLFunction RTLFn; 10166 switch (D.getDirectiveKind()) { 10167 case OMPD_target_enter_data: 10168 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10169 : OMPRTL__tgt_target_data_begin; 10170 break; 10171 case OMPD_target_exit_data: 10172 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10173 : OMPRTL__tgt_target_data_end; 10174 break; 10175 case OMPD_target_update: 10176 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10177 : OMPRTL__tgt_target_data_update; 10178 break; 10179 case OMPD_parallel: 10180 case OMPD_for: 10181 case OMPD_parallel_for: 10182 case OMPD_parallel_sections: 10183 case OMPD_for_simd: 10184 case OMPD_parallel_for_simd: 10185 case OMPD_cancel: 10186 case OMPD_cancellation_point: 10187 case OMPD_ordered: 10188 case OMPD_threadprivate: 10189 case OMPD_allocate: 10190 case OMPD_task: 10191 case OMPD_simd: 10192 case OMPD_sections: 10193 case OMPD_section: 10194 case OMPD_single: 10195 case OMPD_master: 10196 case OMPD_critical: 10197 case OMPD_taskyield: 10198 case OMPD_barrier: 10199 case OMPD_taskwait: 10200 case OMPD_taskgroup: 10201 case OMPD_atomic: 10202 case OMPD_flush: 10203 case OMPD_teams: 10204 case OMPD_target_data: 10205 case OMPD_distribute: 10206 case OMPD_distribute_simd: 10207 case OMPD_distribute_parallel_for: 10208 case OMPD_distribute_parallel_for_simd: 10209 case OMPD_teams_distribute: 10210 case OMPD_teams_distribute_simd: 10211 case OMPD_teams_distribute_parallel_for: 10212 case OMPD_teams_distribute_parallel_for_simd: 10213 case OMPD_declare_simd: 10214 case OMPD_declare_variant: 10215 case OMPD_declare_target: 10216 case OMPD_end_declare_target: 10217 case OMPD_declare_reduction: 10218 case OMPD_declare_mapper: 10219 case OMPD_taskloop: 10220 case OMPD_taskloop_simd: 10221 case OMPD_target: 10222 case OMPD_target_simd: 10223 case OMPD_target_teams_distribute: 10224 case OMPD_target_teams_distribute_simd: 10225 case OMPD_target_teams_distribute_parallel_for: 10226 case OMPD_target_teams_distribute_parallel_for_simd: 10227 case OMPD_target_teams: 10228 case OMPD_target_parallel: 10229 case OMPD_target_parallel_for: 10230 case OMPD_target_parallel_for_simd: 10231 case OMPD_requires: 10232 case OMPD_unknown: 10233 llvm_unreachable("Unexpected standalone target data directive."); 10234 break; 10235 } 10236 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10237 }; 10238 10239 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10240 CodeGenFunction &CGF, PrePostActionTy &) { 10241 // Fill up the arrays with all the mapped variables. 10242 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10243 MappableExprsHandler::MapValuesArrayTy Pointers; 10244 MappableExprsHandler::MapValuesArrayTy Sizes; 10245 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10246 10247 // Get map clause information. 10248 MappableExprsHandler MEHandler(D, CGF); 10249 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10250 10251 TargetDataInfo Info; 10252 // Fill up the arrays and create the arguments. 10253 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10254 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10255 Info.PointersArray, Info.SizesArray, 10256 Info.MapTypesArray, Info); 10257 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10258 InputInfo.BasePointersArray = 10259 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10260 InputInfo.PointersArray = 10261 Address(Info.PointersArray, CGM.getPointerAlign()); 10262 InputInfo.SizesArray = 10263 Address(Info.SizesArray, CGM.getPointerAlign()); 10264 MapTypesArray = Info.MapTypesArray; 10265 if (D.hasClausesOfKind<OMPDependClause>()) 10266 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10267 else 10268 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10269 }; 10270 10271 if (IfCond) { 10272 emitOMPIfClause(CGF, IfCond, TargetThenGen, 10273 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10274 } else { 10275 RegionCodeGenTy ThenRCG(TargetThenGen); 10276 ThenRCG(CGF); 10277 } 10278 } 10279 10280 namespace { 10281 /// Kind of parameter in a function with 'declare simd' directive. 10282 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10283 /// Attribute set of the parameter. 10284 struct ParamAttrTy { 10285 ParamKindTy Kind = Vector; 10286 llvm::APSInt StrideOrArg; 10287 llvm::APSInt Alignment; 10288 }; 10289 } // namespace 10290 10291 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10292 ArrayRef<ParamAttrTy> ParamAttrs) { 10293 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10294 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10295 // of that clause. The VLEN value must be power of 2. 10296 // In other case the notion of the function`s "characteristic data type" (CDT) 10297 // is used to compute the vector length. 10298 // CDT is defined in the following order: 10299 // a) For non-void function, the CDT is the return type. 10300 // b) If the function has any non-uniform, non-linear parameters, then the 10301 // CDT is the type of the first such parameter. 10302 // c) If the CDT determined by a) or b) above is struct, union, or class 10303 // type which is pass-by-value (except for the type that maps to the 10304 // built-in complex data type), the characteristic data type is int. 10305 // d) If none of the above three cases is applicable, the CDT is int. 10306 // The VLEN is then determined based on the CDT and the size of vector 10307 // register of that ISA for which current vector version is generated. The 10308 // VLEN is computed using the formula below: 10309 // VLEN = sizeof(vector_register) / sizeof(CDT), 10310 // where vector register size specified in section 3.2.1 Registers and the 10311 // Stack Frame of original AMD64 ABI document. 10312 QualType RetType = FD->getReturnType(); 10313 if (RetType.isNull()) 10314 return 0; 10315 ASTContext &C = FD->getASTContext(); 10316 QualType CDT; 10317 if (!RetType.isNull() && !RetType->isVoidType()) { 10318 CDT = RetType; 10319 } else { 10320 unsigned Offset = 0; 10321 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10322 if (ParamAttrs[Offset].Kind == Vector) 10323 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10324 ++Offset; 10325 } 10326 if (CDT.isNull()) { 10327 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10328 if (ParamAttrs[I + Offset].Kind == Vector) { 10329 CDT = FD->getParamDecl(I)->getType(); 10330 break; 10331 } 10332 } 10333 } 10334 } 10335 if (CDT.isNull()) 10336 CDT = C.IntTy; 10337 CDT = CDT->getCanonicalTypeUnqualified(); 10338 if (CDT->isRecordType() || CDT->isUnionType()) 10339 CDT = C.IntTy; 10340 return C.getTypeSize(CDT); 10341 } 10342 10343 static void 10344 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10345 const llvm::APSInt &VLENVal, 10346 ArrayRef<ParamAttrTy> ParamAttrs, 10347 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10348 struct ISADataTy { 10349 char ISA; 10350 unsigned VecRegSize; 10351 }; 10352 ISADataTy ISAData[] = { 10353 { 10354 'b', 128 10355 }, // SSE 10356 { 10357 'c', 256 10358 }, // AVX 10359 { 10360 'd', 256 10361 }, // AVX2 10362 { 10363 'e', 512 10364 }, // AVX512 10365 }; 10366 llvm::SmallVector<char, 2> Masked; 10367 switch (State) { 10368 case OMPDeclareSimdDeclAttr::BS_Undefined: 10369 Masked.push_back('N'); 10370 Masked.push_back('M'); 10371 break; 10372 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10373 Masked.push_back('N'); 10374 break; 10375 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10376 Masked.push_back('M'); 10377 break; 10378 } 10379 for (char Mask : Masked) { 10380 for (const ISADataTy &Data : ISAData) { 10381 SmallString<256> Buffer; 10382 llvm::raw_svector_ostream Out(Buffer); 10383 Out << "_ZGV" << Data.ISA << Mask; 10384 if (!VLENVal) { 10385 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10386 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10387 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10388 } else { 10389 Out << VLENVal; 10390 } 10391 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10392 switch (ParamAttr.Kind){ 10393 case LinearWithVarStride: 10394 Out << 's' << ParamAttr.StrideOrArg; 10395 break; 10396 case Linear: 10397 Out << 'l'; 10398 if (!!ParamAttr.StrideOrArg) 10399 Out << ParamAttr.StrideOrArg; 10400 break; 10401 case Uniform: 10402 Out << 'u'; 10403 break; 10404 case Vector: 10405 Out << 'v'; 10406 break; 10407 } 10408 if (!!ParamAttr.Alignment) 10409 Out << 'a' << ParamAttr.Alignment; 10410 } 10411 Out << '_' << Fn->getName(); 10412 Fn->addFnAttr(Out.str()); 10413 } 10414 } 10415 } 10416 10417 // This are the Functions that are needed to mangle the name of the 10418 // vector functions generated by the compiler, according to the rules 10419 // defined in the "Vector Function ABI specifications for AArch64", 10420 // available at 10421 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10422 10423 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10424 /// 10425 /// TODO: Need to implement the behavior for reference marked with a 10426 /// var or no linear modifiers (1.b in the section). For this, we 10427 /// need to extend ParamKindTy to support the linear modifiers. 10428 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10429 QT = QT.getCanonicalType(); 10430 10431 if (QT->isVoidType()) 10432 return false; 10433 10434 if (Kind == ParamKindTy::Uniform) 10435 return false; 10436 10437 if (Kind == ParamKindTy::Linear) 10438 return false; 10439 10440 // TODO: Handle linear references with modifiers 10441 10442 if (Kind == ParamKindTy::LinearWithVarStride) 10443 return false; 10444 10445 return true; 10446 } 10447 10448 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10449 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10450 QT = QT.getCanonicalType(); 10451 unsigned Size = C.getTypeSize(QT); 10452 10453 // Only scalars and complex within 16 bytes wide set PVB to true. 10454 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10455 return false; 10456 10457 if (QT->isFloatingType()) 10458 return true; 10459 10460 if (QT->isIntegerType()) 10461 return true; 10462 10463 if (QT->isPointerType()) 10464 return true; 10465 10466 // TODO: Add support for complex types (section 3.1.2, item 2). 10467 10468 return false; 10469 } 10470 10471 /// Computes the lane size (LS) of a return type or of an input parameter, 10472 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10473 /// TODO: Add support for references, section 3.2.1, item 1. 10474 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10475 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10476 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10477 if (getAArch64PBV(PTy, C)) 10478 return C.getTypeSize(PTy); 10479 } 10480 if (getAArch64PBV(QT, C)) 10481 return C.getTypeSize(QT); 10482 10483 return C.getTypeSize(C.getUIntPtrType()); 10484 } 10485 10486 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10487 // signature of the scalar function, as defined in 3.2.2 of the 10488 // AAVFABI. 10489 static std::tuple<unsigned, unsigned, bool> 10490 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10491 QualType RetType = FD->getReturnType().getCanonicalType(); 10492 10493 ASTContext &C = FD->getASTContext(); 10494 10495 bool OutputBecomesInput = false; 10496 10497 llvm::SmallVector<unsigned, 8> Sizes; 10498 if (!RetType->isVoidType()) { 10499 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10500 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10501 OutputBecomesInput = true; 10502 } 10503 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10504 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10505 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10506 } 10507 10508 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10509 // The LS of a function parameter / return value can only be a power 10510 // of 2, starting from 8 bits, up to 128. 10511 assert(std::all_of(Sizes.begin(), Sizes.end(), 10512 [](unsigned Size) { 10513 return Size == 8 || Size == 16 || Size == 32 || 10514 Size == 64 || Size == 128; 10515 }) && 10516 "Invalid size"); 10517 10518 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10519 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10520 OutputBecomesInput); 10521 } 10522 10523 /// Mangle the parameter part of the vector function name according to 10524 /// their OpenMP classification. The mangling function is defined in 10525 /// section 3.5 of the AAVFABI. 10526 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10527 SmallString<256> Buffer; 10528 llvm::raw_svector_ostream Out(Buffer); 10529 for (const auto &ParamAttr : ParamAttrs) { 10530 switch (ParamAttr.Kind) { 10531 case LinearWithVarStride: 10532 Out << "ls" << ParamAttr.StrideOrArg; 10533 break; 10534 case Linear: 10535 Out << 'l'; 10536 // Don't print the step value if it is not present or if it is 10537 // equal to 1. 10538 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10539 Out << ParamAttr.StrideOrArg; 10540 break; 10541 case Uniform: 10542 Out << 'u'; 10543 break; 10544 case Vector: 10545 Out << 'v'; 10546 break; 10547 } 10548 10549 if (!!ParamAttr.Alignment) 10550 Out << 'a' << ParamAttr.Alignment; 10551 } 10552 10553 return Out.str(); 10554 } 10555 10556 // Function used to add the attribute. The parameter `VLEN` is 10557 // templated to allow the use of "x" when targeting scalable functions 10558 // for SVE. 10559 template <typename T> 10560 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10561 char ISA, StringRef ParSeq, 10562 StringRef MangledName, bool OutputBecomesInput, 10563 llvm::Function *Fn) { 10564 SmallString<256> Buffer; 10565 llvm::raw_svector_ostream Out(Buffer); 10566 Out << Prefix << ISA << LMask << VLEN; 10567 if (OutputBecomesInput) 10568 Out << "v"; 10569 Out << ParSeq << "_" << MangledName; 10570 Fn->addFnAttr(Out.str()); 10571 } 10572 10573 // Helper function to generate the Advanced SIMD names depending on 10574 // the value of the NDS when simdlen is not present. 10575 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10576 StringRef Prefix, char ISA, 10577 StringRef ParSeq, StringRef MangledName, 10578 bool OutputBecomesInput, 10579 llvm::Function *Fn) { 10580 switch (NDS) { 10581 case 8: 10582 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10583 OutputBecomesInput, Fn); 10584 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10585 OutputBecomesInput, Fn); 10586 break; 10587 case 16: 10588 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10589 OutputBecomesInput, Fn); 10590 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10591 OutputBecomesInput, Fn); 10592 break; 10593 case 32: 10594 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10595 OutputBecomesInput, Fn); 10596 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10597 OutputBecomesInput, Fn); 10598 break; 10599 case 64: 10600 case 128: 10601 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10602 OutputBecomesInput, Fn); 10603 break; 10604 default: 10605 llvm_unreachable("Scalar type is too wide."); 10606 } 10607 } 10608 10609 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10610 static void emitAArch64DeclareSimdFunction( 10611 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10612 ArrayRef<ParamAttrTy> ParamAttrs, 10613 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10614 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10615 10616 // Get basic data for building the vector signature. 10617 const auto Data = getNDSWDS(FD, ParamAttrs); 10618 const unsigned NDS = std::get<0>(Data); 10619 const unsigned WDS = std::get<1>(Data); 10620 const bool OutputBecomesInput = std::get<2>(Data); 10621 10622 // Check the values provided via `simdlen` by the user. 10623 // 1. A `simdlen(1)` doesn't produce vector signatures, 10624 if (UserVLEN == 1) { 10625 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10626 DiagnosticsEngine::Warning, 10627 "The clause simdlen(1) has no effect when targeting aarch64."); 10628 CGM.getDiags().Report(SLoc, DiagID); 10629 return; 10630 } 10631 10632 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10633 // Advanced SIMD output. 10634 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10635 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10636 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10637 "power of 2 when targeting Advanced SIMD."); 10638 CGM.getDiags().Report(SLoc, DiagID); 10639 return; 10640 } 10641 10642 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10643 // limits. 10644 if (ISA == 's' && UserVLEN != 0) { 10645 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10646 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10647 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10648 "lanes in the architectural constraints " 10649 "for SVE (min is 128-bit, max is " 10650 "2048-bit, by steps of 128-bit)"); 10651 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10652 return; 10653 } 10654 } 10655 10656 // Sort out parameter sequence. 10657 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10658 StringRef Prefix = "_ZGV"; 10659 // Generate simdlen from user input (if any). 10660 if (UserVLEN) { 10661 if (ISA == 's') { 10662 // SVE generates only a masked function. 10663 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10664 OutputBecomesInput, Fn); 10665 } else { 10666 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10667 // Advanced SIMD generates one or two functions, depending on 10668 // the `[not]inbranch` clause. 10669 switch (State) { 10670 case OMPDeclareSimdDeclAttr::BS_Undefined: 10671 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10672 OutputBecomesInput, Fn); 10673 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10674 OutputBecomesInput, Fn); 10675 break; 10676 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10677 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10678 OutputBecomesInput, Fn); 10679 break; 10680 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10681 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10682 OutputBecomesInput, Fn); 10683 break; 10684 } 10685 } 10686 } else { 10687 // If no user simdlen is provided, follow the AAVFABI rules for 10688 // generating the vector length. 10689 if (ISA == 's') { 10690 // SVE, section 3.4.1, item 1. 10691 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10692 OutputBecomesInput, Fn); 10693 } else { 10694 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10695 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10696 // two vector names depending on the use of the clause 10697 // `[not]inbranch`. 10698 switch (State) { 10699 case OMPDeclareSimdDeclAttr::BS_Undefined: 10700 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10701 OutputBecomesInput, Fn); 10702 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10703 OutputBecomesInput, Fn); 10704 break; 10705 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10706 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10707 OutputBecomesInput, Fn); 10708 break; 10709 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10710 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10711 OutputBecomesInput, Fn); 10712 break; 10713 } 10714 } 10715 } 10716 } 10717 10718 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10719 llvm::Function *Fn) { 10720 ASTContext &C = CGM.getContext(); 10721 FD = FD->getMostRecentDecl(); 10722 // Map params to their positions in function decl. 10723 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10724 if (isa<CXXMethodDecl>(FD)) 10725 ParamPositions.try_emplace(FD, 0); 10726 unsigned ParamPos = ParamPositions.size(); 10727 for (const ParmVarDecl *P : FD->parameters()) { 10728 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10729 ++ParamPos; 10730 } 10731 while (FD) { 10732 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10733 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10734 // Mark uniform parameters. 10735 for (const Expr *E : Attr->uniforms()) { 10736 E = E->IgnoreParenImpCasts(); 10737 unsigned Pos; 10738 if (isa<CXXThisExpr>(E)) { 10739 Pos = ParamPositions[FD]; 10740 } else { 10741 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10742 ->getCanonicalDecl(); 10743 Pos = ParamPositions[PVD]; 10744 } 10745 ParamAttrs[Pos].Kind = Uniform; 10746 } 10747 // Get alignment info. 10748 auto NI = Attr->alignments_begin(); 10749 for (const Expr *E : Attr->aligneds()) { 10750 E = E->IgnoreParenImpCasts(); 10751 unsigned Pos; 10752 QualType ParmTy; 10753 if (isa<CXXThisExpr>(E)) { 10754 Pos = ParamPositions[FD]; 10755 ParmTy = E->getType(); 10756 } else { 10757 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10758 ->getCanonicalDecl(); 10759 Pos = ParamPositions[PVD]; 10760 ParmTy = PVD->getType(); 10761 } 10762 ParamAttrs[Pos].Alignment = 10763 (*NI) 10764 ? (*NI)->EvaluateKnownConstInt(C) 10765 : llvm::APSInt::getUnsigned( 10766 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10767 .getQuantity()); 10768 ++NI; 10769 } 10770 // Mark linear parameters. 10771 auto SI = Attr->steps_begin(); 10772 auto MI = Attr->modifiers_begin(); 10773 for (const Expr *E : Attr->linears()) { 10774 E = E->IgnoreParenImpCasts(); 10775 unsigned Pos; 10776 if (isa<CXXThisExpr>(E)) { 10777 Pos = ParamPositions[FD]; 10778 } else { 10779 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10780 ->getCanonicalDecl(); 10781 Pos = ParamPositions[PVD]; 10782 } 10783 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10784 ParamAttr.Kind = Linear; 10785 if (*SI) { 10786 Expr::EvalResult Result; 10787 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10788 if (const auto *DRE = 10789 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10790 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10791 ParamAttr.Kind = LinearWithVarStride; 10792 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10793 ParamPositions[StridePVD->getCanonicalDecl()]); 10794 } 10795 } 10796 } else { 10797 ParamAttr.StrideOrArg = Result.Val.getInt(); 10798 } 10799 } 10800 ++SI; 10801 ++MI; 10802 } 10803 llvm::APSInt VLENVal; 10804 SourceLocation ExprLoc; 10805 const Expr *VLENExpr = Attr->getSimdlen(); 10806 if (VLENExpr) { 10807 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10808 ExprLoc = VLENExpr->getExprLoc(); 10809 } 10810 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10811 if (CGM.getTriple().getArch() == llvm::Triple::x86 || 10812 CGM.getTriple().getArch() == llvm::Triple::x86_64) { 10813 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10814 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10815 unsigned VLEN = VLENVal.getExtValue(); 10816 StringRef MangledName = Fn->getName(); 10817 if (CGM.getTarget().hasFeature("sve")) 10818 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10819 MangledName, 's', 128, Fn, ExprLoc); 10820 if (CGM.getTarget().hasFeature("neon")) 10821 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10822 MangledName, 'n', 128, Fn, ExprLoc); 10823 } 10824 } 10825 FD = FD->getPreviousDecl(); 10826 } 10827 } 10828 10829 namespace { 10830 /// Cleanup action for doacross support. 10831 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10832 public: 10833 static const int DoacrossFinArgs = 2; 10834 10835 private: 10836 llvm::FunctionCallee RTLFn; 10837 llvm::Value *Args[DoacrossFinArgs]; 10838 10839 public: 10840 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10841 ArrayRef<llvm::Value *> CallArgs) 10842 : RTLFn(RTLFn) { 10843 assert(CallArgs.size() == DoacrossFinArgs); 10844 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10845 } 10846 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10847 if (!CGF.HaveInsertPoint()) 10848 return; 10849 CGF.EmitRuntimeCall(RTLFn, Args); 10850 } 10851 }; 10852 } // namespace 10853 10854 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10855 const OMPLoopDirective &D, 10856 ArrayRef<Expr *> NumIterations) { 10857 if (!CGF.HaveInsertPoint()) 10858 return; 10859 10860 ASTContext &C = CGM.getContext(); 10861 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10862 RecordDecl *RD; 10863 if (KmpDimTy.isNull()) { 10864 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10865 // kmp_int64 lo; // lower 10866 // kmp_int64 up; // upper 10867 // kmp_int64 st; // stride 10868 // }; 10869 RD = C.buildImplicitRecord("kmp_dim"); 10870 RD->startDefinition(); 10871 addFieldToRecordDecl(C, RD, Int64Ty); 10872 addFieldToRecordDecl(C, RD, Int64Ty); 10873 addFieldToRecordDecl(C, RD, Int64Ty); 10874 RD->completeDefinition(); 10875 KmpDimTy = C.getRecordType(RD); 10876 } else { 10877 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10878 } 10879 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10880 QualType ArrayTy = 10881 C.getConstantArrayType(KmpDimTy, Size, ArrayType::Normal, 0); 10882 10883 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10884 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10885 enum { LowerFD = 0, UpperFD, StrideFD }; 10886 // Fill dims with data. 10887 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10888 LValue DimsLVal = CGF.MakeAddrLValue( 10889 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10890 // dims.upper = num_iterations; 10891 LValue UpperLVal = CGF.EmitLValueForField( 10892 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10893 llvm::Value *NumIterVal = 10894 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10895 D.getNumIterations()->getType(), Int64Ty, 10896 D.getNumIterations()->getExprLoc()); 10897 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10898 // dims.stride = 1; 10899 LValue StrideLVal = CGF.EmitLValueForField( 10900 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10901 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10902 StrideLVal); 10903 } 10904 10905 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10906 // kmp_int32 num_dims, struct kmp_dim * dims); 10907 llvm::Value *Args[] = { 10908 emitUpdateLocation(CGF, D.getBeginLoc()), 10909 getThreadID(CGF, D.getBeginLoc()), 10910 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10911 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10912 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10913 CGM.VoidPtrTy)}; 10914 10915 llvm::FunctionCallee RTLFn = 10916 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 10917 CGF.EmitRuntimeCall(RTLFn, Args); 10918 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10919 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10920 llvm::FunctionCallee FiniRTLFn = 10921 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 10922 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10923 llvm::makeArrayRef(FiniArgs)); 10924 } 10925 10926 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10927 const OMPDependClause *C) { 10928 QualType Int64Ty = 10929 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10930 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10931 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10932 Int64Ty, Size, ArrayType::Normal, 0); 10933 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10934 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10935 const Expr *CounterVal = C->getLoopData(I); 10936 assert(CounterVal); 10937 llvm::Value *CntVal = CGF.EmitScalarConversion( 10938 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10939 CounterVal->getExprLoc()); 10940 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10941 /*Volatile=*/false, Int64Ty); 10942 } 10943 llvm::Value *Args[] = { 10944 emitUpdateLocation(CGF, C->getBeginLoc()), 10945 getThreadID(CGF, C->getBeginLoc()), 10946 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10947 llvm::FunctionCallee RTLFn; 10948 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10949 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 10950 } else { 10951 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10952 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 10953 } 10954 CGF.EmitRuntimeCall(RTLFn, Args); 10955 } 10956 10957 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10958 llvm::FunctionCallee Callee, 10959 ArrayRef<llvm::Value *> Args) const { 10960 assert(Loc.isValid() && "Outlined function call location must be valid."); 10961 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10962 10963 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10964 if (Fn->doesNotThrow()) { 10965 CGF.EmitNounwindRuntimeCall(Fn, Args); 10966 return; 10967 } 10968 } 10969 CGF.EmitRuntimeCall(Callee, Args); 10970 } 10971 10972 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10973 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10974 ArrayRef<llvm::Value *> Args) const { 10975 emitCall(CGF, Loc, OutlinedFn, Args); 10976 } 10977 10978 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10979 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 10980 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 10981 HasEmittedDeclareTargetRegion = true; 10982 } 10983 10984 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 10985 const VarDecl *NativeParam, 10986 const VarDecl *TargetParam) const { 10987 return CGF.GetAddrOfLocalVar(NativeParam); 10988 } 10989 10990 namespace { 10991 /// Cleanup action for allocate support. 10992 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 10993 public: 10994 static const int CleanupArgs = 3; 10995 10996 private: 10997 llvm::FunctionCallee RTLFn; 10998 llvm::Value *Args[CleanupArgs]; 10999 11000 public: 11001 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 11002 ArrayRef<llvm::Value *> CallArgs) 11003 : RTLFn(RTLFn) { 11004 assert(CallArgs.size() == CleanupArgs && 11005 "Size of arguments does not match."); 11006 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11007 } 11008 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11009 if (!CGF.HaveInsertPoint()) 11010 return; 11011 CGF.EmitRuntimeCall(RTLFn, Args); 11012 } 11013 }; 11014 } // namespace 11015 11016 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11017 const VarDecl *VD) { 11018 if (!VD) 11019 return Address::invalid(); 11020 const VarDecl *CVD = VD->getCanonicalDecl(); 11021 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 11022 return Address::invalid(); 11023 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 11024 // Use the default allocation. 11025 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 11026 !AA->getAllocator()) 11027 return Address::invalid(); 11028 llvm::Value *Size; 11029 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11030 if (CVD->getType()->isVariablyModifiedType()) { 11031 Size = CGF.getTypeSize(CVD->getType()); 11032 // Align the size: ((size + align - 1) / align) * align 11033 Size = CGF.Builder.CreateNUWAdd( 11034 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11035 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11036 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11037 } else { 11038 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11039 Size = CGM.getSize(Sz.alignTo(Align)); 11040 } 11041 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11042 assert(AA->getAllocator() && 11043 "Expected allocator expression for non-default allocator."); 11044 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11045 // According to the standard, the original allocator type is a enum (integer). 11046 // Convert to pointer type, if required. 11047 if (Allocator->getType()->isIntegerTy()) 11048 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11049 else if (Allocator->getType()->isPointerTy()) 11050 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11051 CGM.VoidPtrTy); 11052 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11053 11054 llvm::Value *Addr = 11055 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11056 CVD->getName() + ".void.addr"); 11057 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11058 Allocator}; 11059 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11060 11061 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11062 llvm::makeArrayRef(FiniArgs)); 11063 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11064 Addr, 11065 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11066 CVD->getName() + ".addr"); 11067 return Address(Addr, Align); 11068 } 11069 11070 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11071 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11072 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11073 llvm_unreachable("Not supported in SIMD-only mode"); 11074 } 11075 11076 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11077 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11078 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11079 llvm_unreachable("Not supported in SIMD-only mode"); 11080 } 11081 11082 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11083 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11084 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11085 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11086 bool Tied, unsigned &NumberOfParts) { 11087 llvm_unreachable("Not supported in SIMD-only mode"); 11088 } 11089 11090 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11091 SourceLocation Loc, 11092 llvm::Function *OutlinedFn, 11093 ArrayRef<llvm::Value *> CapturedVars, 11094 const Expr *IfCond) { 11095 llvm_unreachable("Not supported in SIMD-only mode"); 11096 } 11097 11098 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11099 CodeGenFunction &CGF, StringRef CriticalName, 11100 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11101 const Expr *Hint) { 11102 llvm_unreachable("Not supported in SIMD-only mode"); 11103 } 11104 11105 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11106 const RegionCodeGenTy &MasterOpGen, 11107 SourceLocation Loc) { 11108 llvm_unreachable("Not supported in SIMD-only mode"); 11109 } 11110 11111 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11112 SourceLocation Loc) { 11113 llvm_unreachable("Not supported in SIMD-only mode"); 11114 } 11115 11116 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11117 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11118 SourceLocation Loc) { 11119 llvm_unreachable("Not supported in SIMD-only mode"); 11120 } 11121 11122 void CGOpenMPSIMDRuntime::emitSingleRegion( 11123 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11124 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11125 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11126 ArrayRef<const Expr *> AssignmentOps) { 11127 llvm_unreachable("Not supported in SIMD-only mode"); 11128 } 11129 11130 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11131 const RegionCodeGenTy &OrderedOpGen, 11132 SourceLocation Loc, 11133 bool IsThreads) { 11134 llvm_unreachable("Not supported in SIMD-only mode"); 11135 } 11136 11137 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11138 SourceLocation Loc, 11139 OpenMPDirectiveKind Kind, 11140 bool EmitChecks, 11141 bool ForceSimpleCall) { 11142 llvm_unreachable("Not supported in SIMD-only mode"); 11143 } 11144 11145 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11146 CodeGenFunction &CGF, SourceLocation Loc, 11147 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11148 bool Ordered, const DispatchRTInput &DispatchValues) { 11149 llvm_unreachable("Not supported in SIMD-only mode"); 11150 } 11151 11152 void CGOpenMPSIMDRuntime::emitForStaticInit( 11153 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11154 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11155 llvm_unreachable("Not supported in SIMD-only mode"); 11156 } 11157 11158 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11159 CodeGenFunction &CGF, SourceLocation Loc, 11160 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11161 llvm_unreachable("Not supported in SIMD-only mode"); 11162 } 11163 11164 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11165 SourceLocation Loc, 11166 unsigned IVSize, 11167 bool IVSigned) { 11168 llvm_unreachable("Not supported in SIMD-only mode"); 11169 } 11170 11171 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11172 SourceLocation Loc, 11173 OpenMPDirectiveKind DKind) { 11174 llvm_unreachable("Not supported in SIMD-only mode"); 11175 } 11176 11177 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11178 SourceLocation Loc, 11179 unsigned IVSize, bool IVSigned, 11180 Address IL, Address LB, 11181 Address UB, Address ST) { 11182 llvm_unreachable("Not supported in SIMD-only mode"); 11183 } 11184 11185 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11186 llvm::Value *NumThreads, 11187 SourceLocation Loc) { 11188 llvm_unreachable("Not supported in SIMD-only mode"); 11189 } 11190 11191 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11192 OpenMPProcBindClauseKind ProcBind, 11193 SourceLocation Loc) { 11194 llvm_unreachable("Not supported in SIMD-only mode"); 11195 } 11196 11197 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11198 const VarDecl *VD, 11199 Address VDAddr, 11200 SourceLocation Loc) { 11201 llvm_unreachable("Not supported in SIMD-only mode"); 11202 } 11203 11204 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11205 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11206 CodeGenFunction *CGF) { 11207 llvm_unreachable("Not supported in SIMD-only mode"); 11208 } 11209 11210 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11211 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11212 llvm_unreachable("Not supported in SIMD-only mode"); 11213 } 11214 11215 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11216 ArrayRef<const Expr *> Vars, 11217 SourceLocation Loc) { 11218 llvm_unreachable("Not supported in SIMD-only mode"); 11219 } 11220 11221 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11222 const OMPExecutableDirective &D, 11223 llvm::Function *TaskFunction, 11224 QualType SharedsTy, Address Shareds, 11225 const Expr *IfCond, 11226 const OMPTaskDataTy &Data) { 11227 llvm_unreachable("Not supported in SIMD-only mode"); 11228 } 11229 11230 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11231 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11232 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11233 const Expr *IfCond, const OMPTaskDataTy &Data) { 11234 llvm_unreachable("Not supported in SIMD-only mode"); 11235 } 11236 11237 void CGOpenMPSIMDRuntime::emitReduction( 11238 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11239 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11240 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11241 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11242 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 11243 ReductionOps, Options); 11244 } 11245 11246 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 11247 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 11248 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 11249 llvm_unreachable("Not supported in SIMD-only mode"); 11250 } 11251 11252 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 11253 SourceLocation Loc, 11254 ReductionCodeGen &RCG, 11255 unsigned N) { 11256 llvm_unreachable("Not supported in SIMD-only mode"); 11257 } 11258 11259 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 11260 SourceLocation Loc, 11261 llvm::Value *ReductionsPtr, 11262 LValue SharedLVal) { 11263 llvm_unreachable("Not supported in SIMD-only mode"); 11264 } 11265 11266 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 11267 SourceLocation Loc) { 11268 llvm_unreachable("Not supported in SIMD-only mode"); 11269 } 11270 11271 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 11272 CodeGenFunction &CGF, SourceLocation Loc, 11273 OpenMPDirectiveKind CancelRegion) { 11274 llvm_unreachable("Not supported in SIMD-only mode"); 11275 } 11276 11277 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 11278 SourceLocation Loc, const Expr *IfCond, 11279 OpenMPDirectiveKind CancelRegion) { 11280 llvm_unreachable("Not supported in SIMD-only mode"); 11281 } 11282 11283 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 11284 const OMPExecutableDirective &D, StringRef ParentName, 11285 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 11286 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 11287 llvm_unreachable("Not supported in SIMD-only mode"); 11288 } 11289 11290 void CGOpenMPSIMDRuntime::emitTargetCall( 11291 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11292 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 11293 const Expr *Device, 11294 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 11295 const OMPLoopDirective &D)> 11296 SizeEmitter) { 11297 llvm_unreachable("Not supported in SIMD-only mode"); 11298 } 11299 11300 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 11301 llvm_unreachable("Not supported in SIMD-only mode"); 11302 } 11303 11304 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 11305 llvm_unreachable("Not supported in SIMD-only mode"); 11306 } 11307 11308 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 11309 return false; 11310 } 11311 11312 llvm::Function *CGOpenMPSIMDRuntime::emitRegistrationFunction() { 11313 return nullptr; 11314 } 11315 11316 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 11317 const OMPExecutableDirective &D, 11318 SourceLocation Loc, 11319 llvm::Function *OutlinedFn, 11320 ArrayRef<llvm::Value *> CapturedVars) { 11321 llvm_unreachable("Not supported in SIMD-only mode"); 11322 } 11323 11324 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11325 const Expr *NumTeams, 11326 const Expr *ThreadLimit, 11327 SourceLocation Loc) { 11328 llvm_unreachable("Not supported in SIMD-only mode"); 11329 } 11330 11331 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 11332 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11333 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11334 llvm_unreachable("Not supported in SIMD-only mode"); 11335 } 11336 11337 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 11338 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11339 const Expr *Device) { 11340 llvm_unreachable("Not supported in SIMD-only mode"); 11341 } 11342 11343 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11344 const OMPLoopDirective &D, 11345 ArrayRef<Expr *> NumIterations) { 11346 llvm_unreachable("Not supported in SIMD-only mode"); 11347 } 11348 11349 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11350 const OMPDependClause *C) { 11351 llvm_unreachable("Not supported in SIMD-only mode"); 11352 } 11353 11354 const VarDecl * 11355 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 11356 const VarDecl *NativeParam) const { 11357 llvm_unreachable("Not supported in SIMD-only mode"); 11358 } 11359 11360 Address 11361 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 11362 const VarDecl *NativeParam, 11363 const VarDecl *TargetParam) const { 11364 llvm_unreachable("Not supported in SIMD-only mode"); 11365 } 11366