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/ADT/SetOperations.h" 24 #include "llvm/Bitcode/BitcodeReader.h" 25 #include "llvm/IR/DerivedTypes.h" 26 #include "llvm/IR/GlobalValue.h" 27 #include "llvm/IR/Value.h" 28 #include "llvm/Support/Format.h" 29 #include "llvm/Support/raw_ostream.h" 30 #include <cassert> 31 32 using namespace clang; 33 using namespace CodeGen; 34 35 namespace { 36 /// Base class for handling code generation inside OpenMP regions. 37 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 38 public: 39 /// Kinds of OpenMP regions used in codegen. 40 enum CGOpenMPRegionKind { 41 /// Region with outlined function for standalone 'parallel' 42 /// directive. 43 ParallelOutlinedRegion, 44 /// Region with outlined function for standalone 'task' directive. 45 TaskOutlinedRegion, 46 /// Region for constructs that do not require function outlining, 47 /// like 'for', 'sections', 'atomic' etc. directives. 48 InlinedRegion, 49 /// Region with outlined function for standalone 'target' directive. 50 TargetRegion, 51 }; 52 53 CGOpenMPRegionInfo(const CapturedStmt &CS, 54 const CGOpenMPRegionKind RegionKind, 55 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 56 bool HasCancel) 57 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 58 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 59 60 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 61 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 62 bool HasCancel) 63 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 64 Kind(Kind), HasCancel(HasCancel) {} 65 66 /// Get a variable or parameter for storing global thread id 67 /// inside OpenMP construct. 68 virtual const VarDecl *getThreadIDVariable() const = 0; 69 70 /// Emit the captured statement body. 71 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 72 73 /// Get an LValue for the current ThreadID variable. 74 /// \return LValue for thread id variable. This LValue always has type int32*. 75 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 76 77 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 78 79 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 80 81 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 82 83 bool hasCancel() const { return HasCancel; } 84 85 static bool classof(const CGCapturedStmtInfo *Info) { 86 return Info->getKind() == CR_OpenMP; 87 } 88 89 ~CGOpenMPRegionInfo() override = default; 90 91 protected: 92 CGOpenMPRegionKind RegionKind; 93 RegionCodeGenTy CodeGen; 94 OpenMPDirectiveKind Kind; 95 bool HasCancel; 96 }; 97 98 /// API for captured statement code generation in OpenMP constructs. 99 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 100 public: 101 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 102 const RegionCodeGenTy &CodeGen, 103 OpenMPDirectiveKind Kind, bool HasCancel, 104 StringRef HelperName) 105 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 106 HasCancel), 107 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 108 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 109 } 110 111 /// Get a variable or parameter for storing global thread id 112 /// inside OpenMP construct. 113 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 114 115 /// Get the name of the capture helper. 116 StringRef getHelperName() const override { return HelperName; } 117 118 static bool classof(const CGCapturedStmtInfo *Info) { 119 return CGOpenMPRegionInfo::classof(Info) && 120 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 121 ParallelOutlinedRegion; 122 } 123 124 private: 125 /// A variable or parameter storing global thread id for OpenMP 126 /// constructs. 127 const VarDecl *ThreadIDVar; 128 StringRef HelperName; 129 }; 130 131 /// API for captured statement code generation in OpenMP constructs. 132 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 133 public: 134 class UntiedTaskActionTy final : public PrePostActionTy { 135 bool Untied; 136 const VarDecl *PartIDVar; 137 const RegionCodeGenTy UntiedCodeGen; 138 llvm::SwitchInst *UntiedSwitch = nullptr; 139 140 public: 141 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 142 const RegionCodeGenTy &UntiedCodeGen) 143 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 144 void Enter(CodeGenFunction &CGF) override { 145 if (Untied) { 146 // Emit task switching point. 147 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 148 CGF.GetAddrOfLocalVar(PartIDVar), 149 PartIDVar->getType()->castAs<PointerType>()); 150 llvm::Value *Res = 151 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 152 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 153 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 154 CGF.EmitBlock(DoneBB); 155 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 156 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 157 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 158 CGF.Builder.GetInsertBlock()); 159 emitUntiedSwitch(CGF); 160 } 161 } 162 void emitUntiedSwitch(CodeGenFunction &CGF) const { 163 if (Untied) { 164 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 165 CGF.GetAddrOfLocalVar(PartIDVar), 166 PartIDVar->getType()->castAs<PointerType>()); 167 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 168 PartIdLVal); 169 UntiedCodeGen(CGF); 170 CodeGenFunction::JumpDest CurPoint = 171 CGF.getJumpDestInCurrentScope(".untied.next."); 172 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 173 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 174 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 175 CGF.Builder.GetInsertBlock()); 176 CGF.EmitBranchThroughCleanup(CurPoint); 177 CGF.EmitBlock(CurPoint.getBlock()); 178 } 179 } 180 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 181 }; 182 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 183 const VarDecl *ThreadIDVar, 184 const RegionCodeGenTy &CodeGen, 185 OpenMPDirectiveKind Kind, bool HasCancel, 186 const UntiedTaskActionTy &Action) 187 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 188 ThreadIDVar(ThreadIDVar), Action(Action) { 189 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 190 } 191 192 /// Get a variable or parameter for storing global thread id 193 /// inside OpenMP construct. 194 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 195 196 /// Get an LValue for the current ThreadID variable. 197 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 198 199 /// Get the name of the capture helper. 200 StringRef getHelperName() const override { return ".omp_outlined."; } 201 202 void emitUntiedSwitch(CodeGenFunction &CGF) override { 203 Action.emitUntiedSwitch(CGF); 204 } 205 206 static bool classof(const CGCapturedStmtInfo *Info) { 207 return CGOpenMPRegionInfo::classof(Info) && 208 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 209 TaskOutlinedRegion; 210 } 211 212 private: 213 /// A variable or parameter storing global thread id for OpenMP 214 /// constructs. 215 const VarDecl *ThreadIDVar; 216 /// Action for emitting code for untied tasks. 217 const UntiedTaskActionTy &Action; 218 }; 219 220 /// API for inlined captured statement code generation in OpenMP 221 /// constructs. 222 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 223 public: 224 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 225 const RegionCodeGenTy &CodeGen, 226 OpenMPDirectiveKind Kind, bool HasCancel) 227 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 228 OldCSI(OldCSI), 229 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 230 231 // Retrieve the value of the context parameter. 232 llvm::Value *getContextValue() const override { 233 if (OuterRegionInfo) 234 return OuterRegionInfo->getContextValue(); 235 llvm_unreachable("No context value for inlined OpenMP region"); 236 } 237 238 void setContextValue(llvm::Value *V) override { 239 if (OuterRegionInfo) { 240 OuterRegionInfo->setContextValue(V); 241 return; 242 } 243 llvm_unreachable("No context value for inlined OpenMP region"); 244 } 245 246 /// Lookup the captured field decl for a variable. 247 const FieldDecl *lookup(const VarDecl *VD) const override { 248 if (OuterRegionInfo) 249 return OuterRegionInfo->lookup(VD); 250 // If there is no outer outlined region,no need to lookup in a list of 251 // captured variables, we can use the original one. 252 return nullptr; 253 } 254 255 FieldDecl *getThisFieldDecl() const override { 256 if (OuterRegionInfo) 257 return OuterRegionInfo->getThisFieldDecl(); 258 return nullptr; 259 } 260 261 /// Get a variable or parameter for storing global thread id 262 /// inside OpenMP construct. 263 const VarDecl *getThreadIDVariable() const override { 264 if (OuterRegionInfo) 265 return OuterRegionInfo->getThreadIDVariable(); 266 return nullptr; 267 } 268 269 /// Get an LValue for the current ThreadID variable. 270 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 271 if (OuterRegionInfo) 272 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 273 llvm_unreachable("No LValue for inlined OpenMP construct"); 274 } 275 276 /// Get the name of the capture helper. 277 StringRef getHelperName() const override { 278 if (auto *OuterRegionInfo = getOldCSI()) 279 return OuterRegionInfo->getHelperName(); 280 llvm_unreachable("No helper name for inlined OpenMP construct"); 281 } 282 283 void emitUntiedSwitch(CodeGenFunction &CGF) override { 284 if (OuterRegionInfo) 285 OuterRegionInfo->emitUntiedSwitch(CGF); 286 } 287 288 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 289 290 static bool classof(const CGCapturedStmtInfo *Info) { 291 return CGOpenMPRegionInfo::classof(Info) && 292 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 293 } 294 295 ~CGOpenMPInlinedRegionInfo() override = default; 296 297 private: 298 /// CodeGen info about outer OpenMP region. 299 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 300 CGOpenMPRegionInfo *OuterRegionInfo; 301 }; 302 303 /// API for captured statement code generation in OpenMP target 304 /// constructs. For this captures, implicit parameters are used instead of the 305 /// captured fields. The name of the target region has to be unique in a given 306 /// application so it is provided by the client, because only the client has 307 /// the information to generate that. 308 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 309 public: 310 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 311 const RegionCodeGenTy &CodeGen, StringRef HelperName) 312 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 313 /*HasCancel=*/false), 314 HelperName(HelperName) {} 315 316 /// This is unused for target regions because each starts executing 317 /// with a single thread. 318 const VarDecl *getThreadIDVariable() const override { return nullptr; } 319 320 /// Get the name of the capture helper. 321 StringRef getHelperName() const override { return HelperName; } 322 323 static bool classof(const CGCapturedStmtInfo *Info) { 324 return CGOpenMPRegionInfo::classof(Info) && 325 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 326 } 327 328 private: 329 StringRef HelperName; 330 }; 331 332 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 333 llvm_unreachable("No codegen for expressions"); 334 } 335 /// API for generation of expressions captured in a innermost OpenMP 336 /// region. 337 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 338 public: 339 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 340 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 341 OMPD_unknown, 342 /*HasCancel=*/false), 343 PrivScope(CGF) { 344 // Make sure the globals captured in the provided statement are local by 345 // using the privatization logic. We assume the same variable is not 346 // captured more than once. 347 for (const auto &C : CS.captures()) { 348 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 349 continue; 350 351 const VarDecl *VD = C.getCapturedVar(); 352 if (VD->isLocalVarDeclOrParm()) 353 continue; 354 355 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 356 /*RefersToEnclosingVariableOrCapture=*/false, 357 VD->getType().getNonReferenceType(), VK_LValue, 358 C.getLocation()); 359 PrivScope.addPrivate( 360 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 361 } 362 (void)PrivScope.Privatize(); 363 } 364 365 /// Lookup the captured field decl for a variable. 366 const FieldDecl *lookup(const VarDecl *VD) const override { 367 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 368 return FD; 369 return nullptr; 370 } 371 372 /// Emit the captured statement body. 373 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 374 llvm_unreachable("No body for expressions"); 375 } 376 377 /// Get a variable or parameter for storing global thread id 378 /// inside OpenMP construct. 379 const VarDecl *getThreadIDVariable() const override { 380 llvm_unreachable("No thread id for expressions"); 381 } 382 383 /// Get the name of the capture helper. 384 StringRef getHelperName() const override { 385 llvm_unreachable("No helper name for expressions"); 386 } 387 388 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 389 390 private: 391 /// Private scope to capture global variables. 392 CodeGenFunction::OMPPrivateScope PrivScope; 393 }; 394 395 /// RAII for emitting code of OpenMP constructs. 396 class InlinedOpenMPRegionRAII { 397 CodeGenFunction &CGF; 398 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 399 FieldDecl *LambdaThisCaptureField = nullptr; 400 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 401 402 public: 403 /// Constructs region for combined constructs. 404 /// \param CodeGen Code generation sequence for combined directives. Includes 405 /// a list of functions used for code generation of implicitly inlined 406 /// regions. 407 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 408 OpenMPDirectiveKind Kind, bool HasCancel) 409 : CGF(CGF) { 410 // Start emission for the construct. 411 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 412 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 413 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 414 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 415 CGF.LambdaThisCaptureField = nullptr; 416 BlockInfo = CGF.BlockInfo; 417 CGF.BlockInfo = nullptr; 418 } 419 420 ~InlinedOpenMPRegionRAII() { 421 // Restore original CapturedStmtInfo only if we're done with code emission. 422 auto *OldCSI = 423 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 424 delete CGF.CapturedStmtInfo; 425 CGF.CapturedStmtInfo = OldCSI; 426 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 427 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 428 CGF.BlockInfo = BlockInfo; 429 } 430 }; 431 432 /// Values for bit flags used in the ident_t to describe the fields. 433 /// All enumeric elements are named and described in accordance with the code 434 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 435 enum OpenMPLocationFlags : unsigned { 436 /// Use trampoline for internal microtask. 437 OMP_IDENT_IMD = 0x01, 438 /// Use c-style ident structure. 439 OMP_IDENT_KMPC = 0x02, 440 /// Atomic reduction option for kmpc_reduce. 441 OMP_ATOMIC_REDUCE = 0x10, 442 /// Explicit 'barrier' directive. 443 OMP_IDENT_BARRIER_EXPL = 0x20, 444 /// Implicit barrier in code. 445 OMP_IDENT_BARRIER_IMPL = 0x40, 446 /// Implicit barrier in 'for' directive. 447 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 448 /// Implicit barrier in 'sections' directive. 449 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 450 /// Implicit barrier in 'single' directive. 451 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 452 /// Call of __kmp_for_static_init for static loop. 453 OMP_IDENT_WORK_LOOP = 0x200, 454 /// Call of __kmp_for_static_init for sections. 455 OMP_IDENT_WORK_SECTIONS = 0x400, 456 /// Call of __kmp_for_static_init for distribute. 457 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 458 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 459 }; 460 461 namespace { 462 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 463 /// Values for bit flags for marking which requires clauses have been used. 464 enum OpenMPOffloadingRequiresDirFlags : int64_t { 465 /// flag undefined. 466 OMP_REQ_UNDEFINED = 0x000, 467 /// no requires clause present. 468 OMP_REQ_NONE = 0x001, 469 /// reverse_offload clause. 470 OMP_REQ_REVERSE_OFFLOAD = 0x002, 471 /// unified_address clause. 472 OMP_REQ_UNIFIED_ADDRESS = 0x004, 473 /// unified_shared_memory clause. 474 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 475 /// dynamic_allocators clause. 476 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 477 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 478 }; 479 480 enum OpenMPOffloadingReservedDeviceIDs { 481 /// Device ID if the device was not defined, runtime should get it 482 /// from environment variables in the spec. 483 OMP_DEVICEID_UNDEF = -1, 484 }; 485 } // anonymous namespace 486 487 /// Describes ident structure that describes a source location. 488 /// All descriptions are taken from 489 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 490 /// Original structure: 491 /// typedef struct ident { 492 /// kmp_int32 reserved_1; /**< might be used in Fortran; 493 /// see above */ 494 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 495 /// KMP_IDENT_KMPC identifies this union 496 /// member */ 497 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 498 /// see above */ 499 ///#if USE_ITT_BUILD 500 /// /* but currently used for storing 501 /// region-specific ITT */ 502 /// /* contextual information. */ 503 ///#endif /* USE_ITT_BUILD */ 504 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 505 /// C++ */ 506 /// char const *psource; /**< String describing the source location. 507 /// The string is composed of semi-colon separated 508 // fields which describe the source file, 509 /// the function and a pair of line numbers that 510 /// delimit the construct. 511 /// */ 512 /// } ident_t; 513 enum IdentFieldIndex { 514 /// might be used in Fortran 515 IdentField_Reserved_1, 516 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 517 IdentField_Flags, 518 /// Not really used in Fortran any more 519 IdentField_Reserved_2, 520 /// Source[4] in Fortran, do not use for C++ 521 IdentField_Reserved_3, 522 /// String describing the source location. The string is composed of 523 /// semi-colon separated fields which describe the source file, the function 524 /// and a pair of line numbers that delimit the construct. 525 IdentField_PSource 526 }; 527 528 /// Schedule types for 'omp for' loops (these enumerators are taken from 529 /// the enum sched_type in kmp.h). 530 enum OpenMPSchedType { 531 /// Lower bound for default (unordered) versions. 532 OMP_sch_lower = 32, 533 OMP_sch_static_chunked = 33, 534 OMP_sch_static = 34, 535 OMP_sch_dynamic_chunked = 35, 536 OMP_sch_guided_chunked = 36, 537 OMP_sch_runtime = 37, 538 OMP_sch_auto = 38, 539 /// static with chunk adjustment (e.g., simd) 540 OMP_sch_static_balanced_chunked = 45, 541 /// Lower bound for 'ordered' versions. 542 OMP_ord_lower = 64, 543 OMP_ord_static_chunked = 65, 544 OMP_ord_static = 66, 545 OMP_ord_dynamic_chunked = 67, 546 OMP_ord_guided_chunked = 68, 547 OMP_ord_runtime = 69, 548 OMP_ord_auto = 70, 549 OMP_sch_default = OMP_sch_static, 550 /// dist_schedule types 551 OMP_dist_sch_static_chunked = 91, 552 OMP_dist_sch_static = 92, 553 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 554 /// Set if the monotonic schedule modifier was present. 555 OMP_sch_modifier_monotonic = (1 << 29), 556 /// Set if the nonmonotonic schedule modifier was present. 557 OMP_sch_modifier_nonmonotonic = (1 << 30), 558 }; 559 560 enum OpenMPRTLFunction { 561 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 562 /// kmpc_micro microtask, ...); 563 OMPRTL__kmpc_fork_call, 564 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 565 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 566 OMPRTL__kmpc_threadprivate_cached, 567 /// Call to void __kmpc_threadprivate_register( ident_t *, 568 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 569 OMPRTL__kmpc_threadprivate_register, 570 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 571 OMPRTL__kmpc_global_thread_num, 572 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 573 // kmp_critical_name *crit); 574 OMPRTL__kmpc_critical, 575 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 576 // global_tid, kmp_critical_name *crit, uintptr_t hint); 577 OMPRTL__kmpc_critical_with_hint, 578 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 579 // kmp_critical_name *crit); 580 OMPRTL__kmpc_end_critical, 581 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 582 // global_tid); 583 OMPRTL__kmpc_cancel_barrier, 584 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 585 OMPRTL__kmpc_barrier, 586 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 587 OMPRTL__kmpc_for_static_fini, 588 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 589 // global_tid); 590 OMPRTL__kmpc_serialized_parallel, 591 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 592 // global_tid); 593 OMPRTL__kmpc_end_serialized_parallel, 594 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 595 // kmp_int32 num_threads); 596 OMPRTL__kmpc_push_num_threads, 597 // Call to void __kmpc_flush(ident_t *loc); 598 OMPRTL__kmpc_flush, 599 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 600 OMPRTL__kmpc_master, 601 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 602 OMPRTL__kmpc_end_master, 603 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 604 // int end_part); 605 OMPRTL__kmpc_omp_taskyield, 606 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 607 OMPRTL__kmpc_single, 608 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 609 OMPRTL__kmpc_end_single, 610 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 611 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 612 // kmp_routine_entry_t *task_entry); 613 OMPRTL__kmpc_omp_task_alloc, 614 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 615 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 616 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 617 // kmp_int64 device_id); 618 OMPRTL__kmpc_omp_target_task_alloc, 619 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 620 // new_task); 621 OMPRTL__kmpc_omp_task, 622 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 623 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 624 // kmp_int32 didit); 625 OMPRTL__kmpc_copyprivate, 626 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 627 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 628 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 629 OMPRTL__kmpc_reduce, 630 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 631 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 632 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 633 // *lck); 634 OMPRTL__kmpc_reduce_nowait, 635 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 636 // kmp_critical_name *lck); 637 OMPRTL__kmpc_end_reduce, 638 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 639 // kmp_critical_name *lck); 640 OMPRTL__kmpc_end_reduce_nowait, 641 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 642 // kmp_task_t * new_task); 643 OMPRTL__kmpc_omp_task_begin_if0, 644 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 645 // kmp_task_t * new_task); 646 OMPRTL__kmpc_omp_task_complete_if0, 647 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 648 OMPRTL__kmpc_ordered, 649 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 650 OMPRTL__kmpc_end_ordered, 651 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 652 // global_tid); 653 OMPRTL__kmpc_omp_taskwait, 654 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 655 OMPRTL__kmpc_taskgroup, 656 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 657 OMPRTL__kmpc_end_taskgroup, 658 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 659 // int proc_bind); 660 OMPRTL__kmpc_push_proc_bind, 661 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 662 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 663 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 664 OMPRTL__kmpc_omp_task_with_deps, 665 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 666 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 667 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 668 OMPRTL__kmpc_omp_wait_deps, 669 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 670 // global_tid, kmp_int32 cncl_kind); 671 OMPRTL__kmpc_cancellationpoint, 672 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 673 // kmp_int32 cncl_kind); 674 OMPRTL__kmpc_cancel, 675 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 676 // kmp_int32 num_teams, kmp_int32 thread_limit); 677 OMPRTL__kmpc_push_num_teams, 678 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 679 // microtask, ...); 680 OMPRTL__kmpc_fork_teams, 681 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 682 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 683 // sched, kmp_uint64 grainsize, void *task_dup); 684 OMPRTL__kmpc_taskloop, 685 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 686 // num_dims, struct kmp_dim *dims); 687 OMPRTL__kmpc_doacross_init, 688 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 689 OMPRTL__kmpc_doacross_fini, 690 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 691 // *vec); 692 OMPRTL__kmpc_doacross_post, 693 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 694 // *vec); 695 OMPRTL__kmpc_doacross_wait, 696 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 697 // *data); 698 OMPRTL__kmpc_task_reduction_init, 699 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 700 // *d); 701 OMPRTL__kmpc_task_reduction_get_th_data, 702 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 703 OMPRTL__kmpc_alloc, 704 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 705 OMPRTL__kmpc_free, 706 707 // 708 // Offloading related calls 709 // 710 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 711 // size); 712 OMPRTL__kmpc_push_target_tripcount, 713 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 714 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 715 // *arg_types); 716 OMPRTL__tgt_target, 717 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 718 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 719 // *arg_types); 720 OMPRTL__tgt_target_nowait, 721 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 722 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 723 // *arg_types, int32_t num_teams, int32_t thread_limit); 724 OMPRTL__tgt_target_teams, 725 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 726 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 727 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 728 OMPRTL__tgt_target_teams_nowait, 729 // Call to void __tgt_register_requires(int64_t flags); 730 OMPRTL__tgt_register_requires, 731 // Call to void __tgt_register_lib(__tgt_bin_desc *desc); 732 OMPRTL__tgt_register_lib, 733 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); 734 OMPRTL__tgt_unregister_lib, 735 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 736 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 737 OMPRTL__tgt_target_data_begin, 738 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 739 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 740 // *arg_types); 741 OMPRTL__tgt_target_data_begin_nowait, 742 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 743 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 744 OMPRTL__tgt_target_data_end, 745 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 746 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 747 // *arg_types); 748 OMPRTL__tgt_target_data_end_nowait, 749 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 750 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 751 OMPRTL__tgt_target_data_update, 752 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 753 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 754 // *arg_types); 755 OMPRTL__tgt_target_data_update_nowait, 756 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 757 OMPRTL__tgt_mapper_num_components, 758 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 759 // *base, void *begin, int64_t size, int64_t type); 760 OMPRTL__tgt_push_mapper_component, 761 }; 762 763 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 764 /// region. 765 class CleanupTy final : public EHScopeStack::Cleanup { 766 PrePostActionTy *Action; 767 768 public: 769 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 770 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 771 if (!CGF.HaveInsertPoint()) 772 return; 773 Action->Exit(CGF); 774 } 775 }; 776 777 } // anonymous namespace 778 779 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 780 CodeGenFunction::RunCleanupsScope Scope(CGF); 781 if (PrePostAction) { 782 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 783 Callback(CodeGen, CGF, *PrePostAction); 784 } else { 785 PrePostActionTy Action; 786 Callback(CodeGen, CGF, Action); 787 } 788 } 789 790 /// Check if the combiner is a call to UDR combiner and if it is so return the 791 /// UDR decl used for reduction. 792 static const OMPDeclareReductionDecl * 793 getReductionInit(const Expr *ReductionOp) { 794 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 795 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 796 if (const auto *DRE = 797 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 798 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 799 return DRD; 800 return nullptr; 801 } 802 803 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 804 const OMPDeclareReductionDecl *DRD, 805 const Expr *InitOp, 806 Address Private, Address Original, 807 QualType Ty) { 808 if (DRD->getInitializer()) { 809 std::pair<llvm::Function *, llvm::Function *> Reduction = 810 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 811 const auto *CE = cast<CallExpr>(InitOp); 812 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 813 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 814 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 815 const auto *LHSDRE = 816 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 817 const auto *RHSDRE = 818 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 819 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 820 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 821 [=]() { return Private; }); 822 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 823 [=]() { return Original; }); 824 (void)PrivateScope.Privatize(); 825 RValue Func = RValue::get(Reduction.second); 826 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 827 CGF.EmitIgnoredExpr(InitOp); 828 } else { 829 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 830 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 831 auto *GV = new llvm::GlobalVariable( 832 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 833 llvm::GlobalValue::PrivateLinkage, Init, Name); 834 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 835 RValue InitRVal; 836 switch (CGF.getEvaluationKind(Ty)) { 837 case TEK_Scalar: 838 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 839 break; 840 case TEK_Complex: 841 InitRVal = 842 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 843 break; 844 case TEK_Aggregate: 845 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 846 break; 847 } 848 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 849 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 850 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 851 /*IsInitializer=*/false); 852 } 853 } 854 855 /// Emit initialization of arrays of complex types. 856 /// \param DestAddr Address of the array. 857 /// \param Type Type of array. 858 /// \param Init Initial expression of array. 859 /// \param SrcAddr Address of the original array. 860 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 861 QualType Type, bool EmitDeclareReductionInit, 862 const Expr *Init, 863 const OMPDeclareReductionDecl *DRD, 864 Address SrcAddr = Address::invalid()) { 865 // Perform element-by-element initialization. 866 QualType ElementTy; 867 868 // Drill down to the base element type on both arrays. 869 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 870 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 871 DestAddr = 872 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 873 if (DRD) 874 SrcAddr = 875 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 876 877 llvm::Value *SrcBegin = nullptr; 878 if (DRD) 879 SrcBegin = SrcAddr.getPointer(); 880 llvm::Value *DestBegin = DestAddr.getPointer(); 881 // Cast from pointer to array type to pointer to single element. 882 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 883 // The basic structure here is a while-do loop. 884 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 885 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 886 llvm::Value *IsEmpty = 887 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 888 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 889 890 // Enter the loop body, making that address the current address. 891 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 892 CGF.EmitBlock(BodyBB); 893 894 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 895 896 llvm::PHINode *SrcElementPHI = nullptr; 897 Address SrcElementCurrent = Address::invalid(); 898 if (DRD) { 899 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 900 "omp.arraycpy.srcElementPast"); 901 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 902 SrcElementCurrent = 903 Address(SrcElementPHI, 904 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 905 } 906 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 907 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 908 DestElementPHI->addIncoming(DestBegin, EntryBB); 909 Address DestElementCurrent = 910 Address(DestElementPHI, 911 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 912 913 // Emit copy. 914 { 915 CodeGenFunction::RunCleanupsScope InitScope(CGF); 916 if (EmitDeclareReductionInit) { 917 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 918 SrcElementCurrent, ElementTy); 919 } else 920 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 921 /*IsInitializer=*/false); 922 } 923 924 if (DRD) { 925 // Shift the address forward by one element. 926 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 927 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 928 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 929 } 930 931 // Shift the address forward by one element. 932 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 933 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 934 // Check whether we've reached the end. 935 llvm::Value *Done = 936 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 937 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 938 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 939 940 // Done. 941 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 942 } 943 944 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 945 return CGF.EmitOMPSharedLValue(E); 946 } 947 948 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 949 const Expr *E) { 950 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 951 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 952 return LValue(); 953 } 954 955 void ReductionCodeGen::emitAggregateInitialization( 956 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 957 const OMPDeclareReductionDecl *DRD) { 958 // Emit VarDecl with copy init for arrays. 959 // Get the address of the original variable captured in current 960 // captured region. 961 const auto *PrivateVD = 962 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 963 bool EmitDeclareReductionInit = 964 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 965 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 966 EmitDeclareReductionInit, 967 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 968 : PrivateVD->getInit(), 969 DRD, SharedLVal.getAddress(CGF)); 970 } 971 972 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 973 ArrayRef<const Expr *> Privates, 974 ArrayRef<const Expr *> ReductionOps) { 975 ClausesData.reserve(Shareds.size()); 976 SharedAddresses.reserve(Shareds.size()); 977 Sizes.reserve(Shareds.size()); 978 BaseDecls.reserve(Shareds.size()); 979 auto IPriv = Privates.begin(); 980 auto IRed = ReductionOps.begin(); 981 for (const Expr *Ref : Shareds) { 982 ClausesData.emplace_back(Ref, *IPriv, *IRed); 983 std::advance(IPriv, 1); 984 std::advance(IRed, 1); 985 } 986 } 987 988 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 989 assert(SharedAddresses.size() == N && 990 "Number of generated lvalues must be exactly N."); 991 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 992 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 993 SharedAddresses.emplace_back(First, Second); 994 } 995 996 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 997 const auto *PrivateVD = 998 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 999 QualType PrivateType = PrivateVD->getType(); 1000 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1001 if (!PrivateType->isVariablyModifiedType()) { 1002 Sizes.emplace_back( 1003 CGF.getTypeSize( 1004 SharedAddresses[N].first.getType().getNonReferenceType()), 1005 nullptr); 1006 return; 1007 } 1008 llvm::Value *Size; 1009 llvm::Value *SizeInChars; 1010 auto *ElemType = cast<llvm::PointerType>( 1011 SharedAddresses[N].first.getPointer(CGF)->getType()) 1012 ->getElementType(); 1013 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1014 if (AsArraySection) { 1015 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF), 1016 SharedAddresses[N].first.getPointer(CGF)); 1017 Size = CGF.Builder.CreateNUWAdd( 1018 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1019 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1020 } else { 1021 SizeInChars = CGF.getTypeSize( 1022 SharedAddresses[N].first.getType().getNonReferenceType()); 1023 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1024 } 1025 Sizes.emplace_back(SizeInChars, Size); 1026 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1027 CGF, 1028 cast<OpaqueValueExpr>( 1029 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1030 RValue::get(Size)); 1031 CGF.EmitVariablyModifiedType(PrivateType); 1032 } 1033 1034 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1035 llvm::Value *Size) { 1036 const auto *PrivateVD = 1037 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1038 QualType PrivateType = PrivateVD->getType(); 1039 if (!PrivateType->isVariablyModifiedType()) { 1040 assert(!Size && !Sizes[N].second && 1041 "Size should be nullptr for non-variably modified reduction " 1042 "items."); 1043 return; 1044 } 1045 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1046 CGF, 1047 cast<OpaqueValueExpr>( 1048 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1049 RValue::get(Size)); 1050 CGF.EmitVariablyModifiedType(PrivateType); 1051 } 1052 1053 void ReductionCodeGen::emitInitialization( 1054 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1055 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1056 assert(SharedAddresses.size() > N && "No variable was generated"); 1057 const auto *PrivateVD = 1058 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1059 const OMPDeclareReductionDecl *DRD = 1060 getReductionInit(ClausesData[N].ReductionOp); 1061 QualType PrivateType = PrivateVD->getType(); 1062 PrivateAddr = CGF.Builder.CreateElementBitCast( 1063 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1064 QualType SharedType = SharedAddresses[N].first.getType(); 1065 SharedLVal = CGF.MakeAddrLValue( 1066 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 1067 CGF.ConvertTypeForMem(SharedType)), 1068 SharedType, SharedAddresses[N].first.getBaseInfo(), 1069 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1070 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1071 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1072 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1073 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1074 PrivateAddr, SharedLVal.getAddress(CGF), 1075 SharedLVal.getType()); 1076 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1077 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1078 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1079 PrivateVD->getType().getQualifiers(), 1080 /*IsInitializer=*/false); 1081 } 1082 } 1083 1084 bool ReductionCodeGen::needCleanups(unsigned N) { 1085 const auto *PrivateVD = 1086 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1087 QualType PrivateType = PrivateVD->getType(); 1088 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1089 return DTorKind != QualType::DK_none; 1090 } 1091 1092 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1093 Address PrivateAddr) { 1094 const auto *PrivateVD = 1095 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1096 QualType PrivateType = PrivateVD->getType(); 1097 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1098 if (needCleanups(N)) { 1099 PrivateAddr = CGF.Builder.CreateElementBitCast( 1100 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1101 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1102 } 1103 } 1104 1105 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1106 LValue BaseLV) { 1107 BaseTy = BaseTy.getNonReferenceType(); 1108 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1109 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1110 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1111 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 1112 } else { 1113 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 1114 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1115 } 1116 BaseTy = BaseTy->getPointeeType(); 1117 } 1118 return CGF.MakeAddrLValue( 1119 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 1120 CGF.ConvertTypeForMem(ElTy)), 1121 BaseLV.getType(), BaseLV.getBaseInfo(), 1122 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1123 } 1124 1125 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1126 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1127 llvm::Value *Addr) { 1128 Address Tmp = Address::invalid(); 1129 Address TopTmp = Address::invalid(); 1130 Address MostTopTmp = Address::invalid(); 1131 BaseTy = BaseTy.getNonReferenceType(); 1132 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1133 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1134 Tmp = CGF.CreateMemTemp(BaseTy); 1135 if (TopTmp.isValid()) 1136 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1137 else 1138 MostTopTmp = Tmp; 1139 TopTmp = Tmp; 1140 BaseTy = BaseTy->getPointeeType(); 1141 } 1142 llvm::Type *Ty = BaseLVType; 1143 if (Tmp.isValid()) 1144 Ty = Tmp.getElementType(); 1145 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1146 if (Tmp.isValid()) { 1147 CGF.Builder.CreateStore(Addr, Tmp); 1148 return MostTopTmp; 1149 } 1150 return Address(Addr, BaseLVAlignment); 1151 } 1152 1153 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1154 const VarDecl *OrigVD = nullptr; 1155 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1156 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1157 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1158 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1159 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1160 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1161 DE = cast<DeclRefExpr>(Base); 1162 OrigVD = cast<VarDecl>(DE->getDecl()); 1163 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1164 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1165 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1166 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1167 DE = cast<DeclRefExpr>(Base); 1168 OrigVD = cast<VarDecl>(DE->getDecl()); 1169 } 1170 return OrigVD; 1171 } 1172 1173 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1174 Address PrivateAddr) { 1175 const DeclRefExpr *DE; 1176 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1177 BaseDecls.emplace_back(OrigVD); 1178 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1179 LValue BaseLValue = 1180 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1181 OriginalBaseLValue); 1182 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1183 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1184 llvm::Value *PrivatePointer = 1185 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1186 PrivateAddr.getPointer(), 1187 SharedAddresses[N].first.getAddress(CGF).getType()); 1188 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1189 return castToBase(CGF, OrigVD->getType(), 1190 SharedAddresses[N].first.getType(), 1191 OriginalBaseLValue.getAddress(CGF).getType(), 1192 OriginalBaseLValue.getAlignment(), Ptr); 1193 } 1194 BaseDecls.emplace_back( 1195 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1196 return PrivateAddr; 1197 } 1198 1199 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1200 const OMPDeclareReductionDecl *DRD = 1201 getReductionInit(ClausesData[N].ReductionOp); 1202 return DRD && DRD->getInitializer(); 1203 } 1204 1205 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1206 return CGF.EmitLoadOfPointerLValue( 1207 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1208 getThreadIDVariable()->getType()->castAs<PointerType>()); 1209 } 1210 1211 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1212 if (!CGF.HaveInsertPoint()) 1213 return; 1214 // 1.2.2 OpenMP Language Terminology 1215 // Structured block - An executable statement with a single entry at the 1216 // top and a single exit at the bottom. 1217 // The point of exit cannot be a branch out of the structured block. 1218 // longjmp() and throw() must not violate the entry/exit criteria. 1219 CGF.EHStack.pushTerminate(); 1220 CodeGen(CGF); 1221 CGF.EHStack.popTerminate(); 1222 } 1223 1224 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1225 CodeGenFunction &CGF) { 1226 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1227 getThreadIDVariable()->getType(), 1228 AlignmentSource::Decl); 1229 } 1230 1231 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1232 QualType FieldTy) { 1233 auto *Field = FieldDecl::Create( 1234 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1235 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1236 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1237 Field->setAccess(AS_public); 1238 DC->addDecl(Field); 1239 return Field; 1240 } 1241 1242 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1243 StringRef Separator) 1244 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1245 OffloadEntriesInfoManager(CGM) { 1246 ASTContext &C = CGM.getContext(); 1247 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1248 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1249 RD->startDefinition(); 1250 // reserved_1 1251 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1252 // flags 1253 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1254 // reserved_2 1255 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1256 // reserved_3 1257 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1258 // psource 1259 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1260 RD->completeDefinition(); 1261 IdentQTy = C.getRecordType(RD); 1262 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1263 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1264 1265 loadOffloadInfoMetadata(); 1266 } 1267 1268 bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD, 1269 const GlobalDecl &OldGD, 1270 llvm::GlobalValue *OrigAddr, 1271 bool IsForDefinition) { 1272 // Emit at least a definition for the aliasee if the the address of the 1273 // original function is requested. 1274 if (IsForDefinition || OrigAddr) 1275 (void)CGM.GetAddrOfGlobal(NewGD); 1276 StringRef NewMangledName = CGM.getMangledName(NewGD); 1277 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1278 if (Addr && !Addr->isDeclaration()) { 1279 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1280 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(OldGD); 1281 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1282 1283 // Create a reference to the named value. This ensures that it is emitted 1284 // if a deferred decl. 1285 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1286 1287 // Create the new alias itself, but don't set a name yet. 1288 auto *GA = 1289 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1290 1291 if (OrigAddr) { 1292 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1293 1294 GA->takeName(OrigAddr); 1295 OrigAddr->replaceAllUsesWith( 1296 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1297 OrigAddr->eraseFromParent(); 1298 } else { 1299 GA->setName(CGM.getMangledName(OldGD)); 1300 } 1301 1302 // Set attributes which are particular to an alias; this is a 1303 // specialization of the attributes which may be set on a global function. 1304 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1305 D->isWeakImported()) 1306 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1307 1308 CGM.SetCommonAttributes(OldGD, GA); 1309 return true; 1310 } 1311 return false; 1312 } 1313 1314 void CGOpenMPRuntime::clear() { 1315 InternalVars.clear(); 1316 // Clean non-target variable declarations possibly used only in debug info. 1317 for (const auto &Data : EmittedNonTargetVariables) { 1318 if (!Data.getValue().pointsToAliveValue()) 1319 continue; 1320 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1321 if (!GV) 1322 continue; 1323 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1324 continue; 1325 GV->eraseFromParent(); 1326 } 1327 // Emit aliases for the deferred aliasees. 1328 for (const auto &Pair : DeferredVariantFunction) { 1329 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1330 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1331 // If not able to emit alias, just emit original declaration. 1332 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr, 1333 /*IsForDefinition=*/false); 1334 } 1335 } 1336 1337 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1338 SmallString<128> Buffer; 1339 llvm::raw_svector_ostream OS(Buffer); 1340 StringRef Sep = FirstSeparator; 1341 for (StringRef Part : Parts) { 1342 OS << Sep << Part; 1343 Sep = Separator; 1344 } 1345 return OS.str(); 1346 } 1347 1348 static llvm::Function * 1349 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1350 const Expr *CombinerInitializer, const VarDecl *In, 1351 const VarDecl *Out, bool IsCombiner) { 1352 // void .omp_combiner.(Ty *in, Ty *out); 1353 ASTContext &C = CGM.getContext(); 1354 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1355 FunctionArgList Args; 1356 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1357 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1358 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1359 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1360 Args.push_back(&OmpOutParm); 1361 Args.push_back(&OmpInParm); 1362 const CGFunctionInfo &FnInfo = 1363 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1364 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1365 std::string Name = CGM.getOpenMPRuntime().getName( 1366 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1367 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1368 Name, &CGM.getModule()); 1369 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1370 if (CGM.getLangOpts().Optimize) { 1371 Fn->removeFnAttr(llvm::Attribute::NoInline); 1372 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1373 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1374 } 1375 CodeGenFunction CGF(CGM); 1376 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1377 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1378 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1379 Out->getLocation()); 1380 CodeGenFunction::OMPPrivateScope Scope(CGF); 1381 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1382 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1383 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1384 .getAddress(CGF); 1385 }); 1386 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1387 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1388 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1389 .getAddress(CGF); 1390 }); 1391 (void)Scope.Privatize(); 1392 if (!IsCombiner && Out->hasInit() && 1393 !CGF.isTrivialInitializer(Out->getInit())) { 1394 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1395 Out->getType().getQualifiers(), 1396 /*IsInitializer=*/true); 1397 } 1398 if (CombinerInitializer) 1399 CGF.EmitIgnoredExpr(CombinerInitializer); 1400 Scope.ForceCleanup(); 1401 CGF.FinishFunction(); 1402 return Fn; 1403 } 1404 1405 void CGOpenMPRuntime::emitUserDefinedReduction( 1406 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1407 if (UDRMap.count(D) > 0) 1408 return; 1409 llvm::Function *Combiner = emitCombinerOrInitializer( 1410 CGM, D->getType(), D->getCombiner(), 1411 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1412 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1413 /*IsCombiner=*/true); 1414 llvm::Function *Initializer = nullptr; 1415 if (const Expr *Init = D->getInitializer()) { 1416 Initializer = emitCombinerOrInitializer( 1417 CGM, D->getType(), 1418 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1419 : nullptr, 1420 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1421 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1422 /*IsCombiner=*/false); 1423 } 1424 UDRMap.try_emplace(D, Combiner, Initializer); 1425 if (CGF) { 1426 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1427 Decls.second.push_back(D); 1428 } 1429 } 1430 1431 std::pair<llvm::Function *, llvm::Function *> 1432 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1433 auto I = UDRMap.find(D); 1434 if (I != UDRMap.end()) 1435 return I->second; 1436 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1437 return UDRMap.lookup(D); 1438 } 1439 1440 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1441 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1442 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1443 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1444 assert(ThreadIDVar->getType()->isPointerType() && 1445 "thread id variable must be of type kmp_int32 *"); 1446 CodeGenFunction CGF(CGM, true); 1447 bool HasCancel = false; 1448 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1449 HasCancel = OPD->hasCancel(); 1450 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1451 HasCancel = OPSD->hasCancel(); 1452 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1453 HasCancel = OPFD->hasCancel(); 1454 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1455 HasCancel = OPFD->hasCancel(); 1456 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1457 HasCancel = OPFD->hasCancel(); 1458 else if (const auto *OPFD = 1459 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1460 HasCancel = OPFD->hasCancel(); 1461 else if (const auto *OPFD = 1462 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1463 HasCancel = OPFD->hasCancel(); 1464 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1465 HasCancel, OutlinedHelperName); 1466 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1467 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 1468 } 1469 1470 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1471 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1472 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1473 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1474 return emitParallelOrTeamsOutlinedFunction( 1475 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1476 } 1477 1478 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1479 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1480 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1481 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1482 return emitParallelOrTeamsOutlinedFunction( 1483 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1484 } 1485 1486 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1487 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1488 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1489 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1490 bool Tied, unsigned &NumberOfParts) { 1491 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1492 PrePostActionTy &) { 1493 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1494 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1495 llvm::Value *TaskArgs[] = { 1496 UpLoc, ThreadID, 1497 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1498 TaskTVar->getType()->castAs<PointerType>()) 1499 .getPointer(CGF)}; 1500 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1501 }; 1502 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1503 UntiedCodeGen); 1504 CodeGen.setAction(Action); 1505 assert(!ThreadIDVar->getType()->isPointerType() && 1506 "thread id variable must be of type kmp_int32 for tasks"); 1507 const OpenMPDirectiveKind Region = 1508 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1509 : OMPD_task; 1510 const CapturedStmt *CS = D.getCapturedStmt(Region); 1511 const auto *TD = dyn_cast<OMPTaskDirective>(&D); 1512 CodeGenFunction CGF(CGM, true); 1513 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1514 InnermostKind, 1515 TD ? TD->hasCancel() : false, Action); 1516 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1517 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1518 if (!Tied) 1519 NumberOfParts = Action.getNumberOfParts(); 1520 return Res; 1521 } 1522 1523 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1524 const RecordDecl *RD, const CGRecordLayout &RL, 1525 ArrayRef<llvm::Constant *> Data) { 1526 llvm::StructType *StructTy = RL.getLLVMType(); 1527 unsigned PrevIdx = 0; 1528 ConstantInitBuilder CIBuilder(CGM); 1529 auto DI = Data.begin(); 1530 for (const FieldDecl *FD : RD->fields()) { 1531 unsigned Idx = RL.getLLVMFieldNo(FD); 1532 // Fill the alignment. 1533 for (unsigned I = PrevIdx; I < Idx; ++I) 1534 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1535 PrevIdx = Idx + 1; 1536 Fields.add(*DI); 1537 ++DI; 1538 } 1539 } 1540 1541 template <class... As> 1542 static llvm::GlobalVariable * 1543 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1544 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1545 As &&... Args) { 1546 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1547 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1548 ConstantInitBuilder CIBuilder(CGM); 1549 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1550 buildStructValue(Fields, CGM, RD, RL, Data); 1551 return Fields.finishAndCreateGlobal( 1552 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1553 std::forward<As>(Args)...); 1554 } 1555 1556 template <typename T> 1557 static void 1558 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1559 ArrayRef<llvm::Constant *> Data, 1560 T &Parent) { 1561 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1562 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1563 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1564 buildStructValue(Fields, CGM, RD, RL, Data); 1565 Fields.finishAndAddTo(Parent); 1566 } 1567 1568 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1569 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1570 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1571 FlagsTy FlagsKey(Flags, Reserved2Flags); 1572 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1573 if (!Entry) { 1574 if (!DefaultOpenMPPSource) { 1575 // Initialize default location for psource field of ident_t structure of 1576 // all ident_t objects. Format is ";file;function;line;column;;". 1577 // Taken from 1578 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1579 DefaultOpenMPPSource = 1580 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1581 DefaultOpenMPPSource = 1582 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1583 } 1584 1585 llvm::Constant *Data[] = { 1586 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1587 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1588 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1589 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1590 llvm::GlobalValue *DefaultOpenMPLocation = 1591 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1592 llvm::GlobalValue::PrivateLinkage); 1593 DefaultOpenMPLocation->setUnnamedAddr( 1594 llvm::GlobalValue::UnnamedAddr::Global); 1595 1596 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1597 } 1598 return Address(Entry, Align); 1599 } 1600 1601 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1602 bool AtCurrentPoint) { 1603 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1604 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1605 1606 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1607 if (AtCurrentPoint) { 1608 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1609 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1610 } else { 1611 Elem.second.ServiceInsertPt = 1612 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1613 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1614 } 1615 } 1616 1617 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1618 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1619 if (Elem.second.ServiceInsertPt) { 1620 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1621 Elem.second.ServiceInsertPt = nullptr; 1622 Ptr->eraseFromParent(); 1623 } 1624 } 1625 1626 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1627 SourceLocation Loc, 1628 unsigned Flags) { 1629 Flags |= OMP_IDENT_KMPC; 1630 // If no debug info is generated - return global default location. 1631 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1632 Loc.isInvalid()) 1633 return getOrCreateDefaultLocation(Flags).getPointer(); 1634 1635 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1636 1637 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1638 Address LocValue = Address::invalid(); 1639 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1640 if (I != OpenMPLocThreadIDMap.end()) 1641 LocValue = Address(I->second.DebugLoc, Align); 1642 1643 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1644 // GetOpenMPThreadID was called before this routine. 1645 if (!LocValue.isValid()) { 1646 // Generate "ident_t .kmpc_loc.addr;" 1647 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1648 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1649 Elem.second.DebugLoc = AI.getPointer(); 1650 LocValue = AI; 1651 1652 if (!Elem.second.ServiceInsertPt) 1653 setLocThreadIdInsertPt(CGF); 1654 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1655 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1656 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1657 CGF.getTypeSize(IdentQTy)); 1658 } 1659 1660 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1661 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1662 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1663 LValue PSource = 1664 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1665 1666 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1667 if (OMPDebugLoc == nullptr) { 1668 SmallString<128> Buffer2; 1669 llvm::raw_svector_ostream OS2(Buffer2); 1670 // Build debug location 1671 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1672 OS2 << ";" << PLoc.getFilename() << ";"; 1673 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1674 OS2 << FD->getQualifiedNameAsString(); 1675 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1676 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1677 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1678 } 1679 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1680 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1681 1682 // Our callers always pass this to a runtime function, so for 1683 // convenience, go ahead and return a naked pointer. 1684 return LocValue.getPointer(); 1685 } 1686 1687 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1688 SourceLocation Loc) { 1689 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1690 1691 llvm::Value *ThreadID = nullptr; 1692 // Check whether we've already cached a load of the thread id in this 1693 // function. 1694 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1695 if (I != OpenMPLocThreadIDMap.end()) { 1696 ThreadID = I->second.ThreadID; 1697 if (ThreadID != nullptr) 1698 return ThreadID; 1699 } 1700 // If exceptions are enabled, do not use parameter to avoid possible crash. 1701 if (auto *OMPRegionInfo = 1702 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1703 if (OMPRegionInfo->getThreadIDVariable()) { 1704 // Check if this an outlined function with thread id passed as argument. 1705 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1706 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1707 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1708 !CGF.getLangOpts().CXXExceptions || 1709 CGF.Builder.GetInsertBlock() == TopBlock || 1710 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1711 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1712 TopBlock || 1713 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1714 CGF.Builder.GetInsertBlock()) { 1715 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1716 // If value loaded in entry block, cache it and use it everywhere in 1717 // function. 1718 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1719 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1720 Elem.second.ThreadID = ThreadID; 1721 } 1722 return ThreadID; 1723 } 1724 } 1725 } 1726 1727 // This is not an outlined function region - need to call __kmpc_int32 1728 // kmpc_global_thread_num(ident_t *loc). 1729 // Generate thread id value and cache this value for use across the 1730 // function. 1731 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1732 if (!Elem.second.ServiceInsertPt) 1733 setLocThreadIdInsertPt(CGF); 1734 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1735 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1736 llvm::CallInst *Call = CGF.Builder.CreateCall( 1737 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1738 emitUpdateLocation(CGF, Loc)); 1739 Call->setCallingConv(CGF.getRuntimeCC()); 1740 Elem.second.ThreadID = Call; 1741 return Call; 1742 } 1743 1744 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1745 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1746 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1747 clearLocThreadIdInsertPt(CGF); 1748 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1749 } 1750 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1751 for(auto *D : FunctionUDRMap[CGF.CurFn]) 1752 UDRMap.erase(D); 1753 FunctionUDRMap.erase(CGF.CurFn); 1754 } 1755 auto I = FunctionUDMMap.find(CGF.CurFn); 1756 if (I != FunctionUDMMap.end()) { 1757 for(auto *D : I->second) 1758 UDMMap.erase(D); 1759 FunctionUDMMap.erase(I); 1760 } 1761 } 1762 1763 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1764 return IdentTy->getPointerTo(); 1765 } 1766 1767 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1768 if (!Kmpc_MicroTy) { 1769 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1770 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1771 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1772 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1773 } 1774 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1775 } 1776 1777 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1778 llvm::FunctionCallee RTLFn = nullptr; 1779 switch (static_cast<OpenMPRTLFunction>(Function)) { 1780 case OMPRTL__kmpc_fork_call: { 1781 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1782 // microtask, ...); 1783 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1784 getKmpc_MicroPointerTy()}; 1785 auto *FnTy = 1786 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1787 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1788 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1789 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1790 llvm::LLVMContext &Ctx = F->getContext(); 1791 llvm::MDBuilder MDB(Ctx); 1792 // Annotate the callback behavior of the __kmpc_fork_call: 1793 // - The callback callee is argument number 2 (microtask). 1794 // - The first two arguments of the callback callee are unknown (-1). 1795 // - All variadic arguments to the __kmpc_fork_call are passed to the 1796 // callback callee. 1797 F->addMetadata( 1798 llvm::LLVMContext::MD_callback, 1799 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1800 2, {-1, -1}, 1801 /* VarArgsArePassed */ true)})); 1802 } 1803 } 1804 break; 1805 } 1806 case OMPRTL__kmpc_global_thread_num: { 1807 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1808 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1809 auto *FnTy = 1810 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1811 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1812 break; 1813 } 1814 case OMPRTL__kmpc_threadprivate_cached: { 1815 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1816 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1817 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1818 CGM.VoidPtrTy, CGM.SizeTy, 1819 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1820 auto *FnTy = 1821 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1822 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1823 break; 1824 } 1825 case OMPRTL__kmpc_critical: { 1826 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1827 // kmp_critical_name *crit); 1828 llvm::Type *TypeParams[] = { 1829 getIdentTyPointerTy(), CGM.Int32Ty, 1830 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1831 auto *FnTy = 1832 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1833 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1834 break; 1835 } 1836 case OMPRTL__kmpc_critical_with_hint: { 1837 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1838 // kmp_critical_name *crit, uintptr_t hint); 1839 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1840 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1841 CGM.IntPtrTy}; 1842 auto *FnTy = 1843 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1844 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1845 break; 1846 } 1847 case OMPRTL__kmpc_threadprivate_register: { 1848 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1849 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1850 // typedef void *(*kmpc_ctor)(void *); 1851 auto *KmpcCtorTy = 1852 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1853 /*isVarArg*/ false)->getPointerTo(); 1854 // typedef void *(*kmpc_cctor)(void *, void *); 1855 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1856 auto *KmpcCopyCtorTy = 1857 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1858 /*isVarArg*/ false) 1859 ->getPointerTo(); 1860 // typedef void (*kmpc_dtor)(void *); 1861 auto *KmpcDtorTy = 1862 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1863 ->getPointerTo(); 1864 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1865 KmpcCopyCtorTy, KmpcDtorTy}; 1866 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1867 /*isVarArg*/ false); 1868 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1869 break; 1870 } 1871 case OMPRTL__kmpc_end_critical: { 1872 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1873 // kmp_critical_name *crit); 1874 llvm::Type *TypeParams[] = { 1875 getIdentTyPointerTy(), CGM.Int32Ty, 1876 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1877 auto *FnTy = 1878 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1879 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1880 break; 1881 } 1882 case OMPRTL__kmpc_cancel_barrier: { 1883 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1884 // global_tid); 1885 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1886 auto *FnTy = 1887 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1888 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1889 break; 1890 } 1891 case OMPRTL__kmpc_barrier: { 1892 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1893 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1894 auto *FnTy = 1895 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1896 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1897 break; 1898 } 1899 case OMPRTL__kmpc_for_static_fini: { 1900 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1901 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1902 auto *FnTy = 1903 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1904 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1905 break; 1906 } 1907 case OMPRTL__kmpc_push_num_threads: { 1908 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1909 // kmp_int32 num_threads) 1910 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1911 CGM.Int32Ty}; 1912 auto *FnTy = 1913 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1914 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1915 break; 1916 } 1917 case OMPRTL__kmpc_serialized_parallel: { 1918 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1919 // global_tid); 1920 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1921 auto *FnTy = 1922 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1923 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1924 break; 1925 } 1926 case OMPRTL__kmpc_end_serialized_parallel: { 1927 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1928 // global_tid); 1929 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1930 auto *FnTy = 1931 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1932 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1933 break; 1934 } 1935 case OMPRTL__kmpc_flush: { 1936 // Build void __kmpc_flush(ident_t *loc); 1937 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1938 auto *FnTy = 1939 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1940 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1941 break; 1942 } 1943 case OMPRTL__kmpc_master: { 1944 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1945 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1946 auto *FnTy = 1947 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1948 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 1949 break; 1950 } 1951 case OMPRTL__kmpc_end_master: { 1952 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 1953 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1954 auto *FnTy = 1955 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1956 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 1957 break; 1958 } 1959 case OMPRTL__kmpc_omp_taskyield: { 1960 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 1961 // int end_part); 1962 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1963 auto *FnTy = 1964 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1965 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 1966 break; 1967 } 1968 case OMPRTL__kmpc_single: { 1969 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 1970 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1971 auto *FnTy = 1972 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1973 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 1974 break; 1975 } 1976 case OMPRTL__kmpc_end_single: { 1977 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 1978 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1979 auto *FnTy = 1980 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1981 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 1982 break; 1983 } 1984 case OMPRTL__kmpc_omp_task_alloc: { 1985 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 1986 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1987 // kmp_routine_entry_t *task_entry); 1988 assert(KmpRoutineEntryPtrTy != nullptr && 1989 "Type kmp_routine_entry_t must be created."); 1990 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1991 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 1992 // Return void * and then cast to particular kmp_task_t type. 1993 auto *FnTy = 1994 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1995 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 1996 break; 1997 } 1998 case OMPRTL__kmpc_omp_target_task_alloc: { 1999 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 2000 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2001 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 2002 assert(KmpRoutineEntryPtrTy != nullptr && 2003 "Type kmp_routine_entry_t must be created."); 2004 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2005 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 2006 CGM.Int64Ty}; 2007 // Return void * and then cast to particular kmp_task_t type. 2008 auto *FnTy = 2009 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2010 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2011 break; 2012 } 2013 case OMPRTL__kmpc_omp_task: { 2014 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2015 // *new_task); 2016 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2017 CGM.VoidPtrTy}; 2018 auto *FnTy = 2019 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2020 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2021 break; 2022 } 2023 case OMPRTL__kmpc_copyprivate: { 2024 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2025 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2026 // kmp_int32 didit); 2027 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2028 auto *CpyFnTy = 2029 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2030 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2031 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2032 CGM.Int32Ty}; 2033 auto *FnTy = 2034 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2035 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2036 break; 2037 } 2038 case OMPRTL__kmpc_reduce: { 2039 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2040 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2041 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2042 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2043 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2044 /*isVarArg=*/false); 2045 llvm::Type *TypeParams[] = { 2046 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2047 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2048 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2049 auto *FnTy = 2050 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2051 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2052 break; 2053 } 2054 case OMPRTL__kmpc_reduce_nowait: { 2055 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2056 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2057 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2058 // *lck); 2059 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2060 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2061 /*isVarArg=*/false); 2062 llvm::Type *TypeParams[] = { 2063 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2064 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2065 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2066 auto *FnTy = 2067 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2068 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2069 break; 2070 } 2071 case OMPRTL__kmpc_end_reduce: { 2072 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2073 // kmp_critical_name *lck); 2074 llvm::Type *TypeParams[] = { 2075 getIdentTyPointerTy(), CGM.Int32Ty, 2076 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2077 auto *FnTy = 2078 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2079 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2080 break; 2081 } 2082 case OMPRTL__kmpc_end_reduce_nowait: { 2083 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2084 // kmp_critical_name *lck); 2085 llvm::Type *TypeParams[] = { 2086 getIdentTyPointerTy(), CGM.Int32Ty, 2087 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2088 auto *FnTy = 2089 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2090 RTLFn = 2091 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2092 break; 2093 } 2094 case OMPRTL__kmpc_omp_task_begin_if0: { 2095 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2096 // *new_task); 2097 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2098 CGM.VoidPtrTy}; 2099 auto *FnTy = 2100 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2101 RTLFn = 2102 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2103 break; 2104 } 2105 case OMPRTL__kmpc_omp_task_complete_if0: { 2106 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2107 // *new_task); 2108 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2109 CGM.VoidPtrTy}; 2110 auto *FnTy = 2111 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2112 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2113 /*Name=*/"__kmpc_omp_task_complete_if0"); 2114 break; 2115 } 2116 case OMPRTL__kmpc_ordered: { 2117 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2118 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2119 auto *FnTy = 2120 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2121 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2122 break; 2123 } 2124 case OMPRTL__kmpc_end_ordered: { 2125 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2126 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2127 auto *FnTy = 2128 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2129 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2130 break; 2131 } 2132 case OMPRTL__kmpc_omp_taskwait: { 2133 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2134 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2135 auto *FnTy = 2136 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2137 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2138 break; 2139 } 2140 case OMPRTL__kmpc_taskgroup: { 2141 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2142 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2143 auto *FnTy = 2144 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2145 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2146 break; 2147 } 2148 case OMPRTL__kmpc_end_taskgroup: { 2149 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2150 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2151 auto *FnTy = 2152 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2153 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2154 break; 2155 } 2156 case OMPRTL__kmpc_push_proc_bind: { 2157 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2158 // int proc_bind) 2159 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2160 auto *FnTy = 2161 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2162 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2163 break; 2164 } 2165 case OMPRTL__kmpc_omp_task_with_deps: { 2166 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2167 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2168 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2169 llvm::Type *TypeParams[] = { 2170 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2171 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2172 auto *FnTy = 2173 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2174 RTLFn = 2175 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2176 break; 2177 } 2178 case OMPRTL__kmpc_omp_wait_deps: { 2179 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2180 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2181 // kmp_depend_info_t *noalias_dep_list); 2182 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2183 CGM.Int32Ty, CGM.VoidPtrTy, 2184 CGM.Int32Ty, CGM.VoidPtrTy}; 2185 auto *FnTy = 2186 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2187 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2188 break; 2189 } 2190 case OMPRTL__kmpc_cancellationpoint: { 2191 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2192 // global_tid, kmp_int32 cncl_kind) 2193 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2194 auto *FnTy = 2195 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2196 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2197 break; 2198 } 2199 case OMPRTL__kmpc_cancel: { 2200 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2201 // kmp_int32 cncl_kind) 2202 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2203 auto *FnTy = 2204 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2205 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2206 break; 2207 } 2208 case OMPRTL__kmpc_push_num_teams: { 2209 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2210 // kmp_int32 num_teams, kmp_int32 num_threads) 2211 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2212 CGM.Int32Ty}; 2213 auto *FnTy = 2214 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2215 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2216 break; 2217 } 2218 case OMPRTL__kmpc_fork_teams: { 2219 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2220 // microtask, ...); 2221 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2222 getKmpc_MicroPointerTy()}; 2223 auto *FnTy = 2224 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2225 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2226 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2227 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2228 llvm::LLVMContext &Ctx = F->getContext(); 2229 llvm::MDBuilder MDB(Ctx); 2230 // Annotate the callback behavior of the __kmpc_fork_teams: 2231 // - The callback callee is argument number 2 (microtask). 2232 // - The first two arguments of the callback callee are unknown (-1). 2233 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2234 // callback callee. 2235 F->addMetadata( 2236 llvm::LLVMContext::MD_callback, 2237 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2238 2, {-1, -1}, 2239 /* VarArgsArePassed */ true)})); 2240 } 2241 } 2242 break; 2243 } 2244 case OMPRTL__kmpc_taskloop: { 2245 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2246 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2247 // sched, kmp_uint64 grainsize, void *task_dup); 2248 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2249 CGM.IntTy, 2250 CGM.VoidPtrTy, 2251 CGM.IntTy, 2252 CGM.Int64Ty->getPointerTo(), 2253 CGM.Int64Ty->getPointerTo(), 2254 CGM.Int64Ty, 2255 CGM.IntTy, 2256 CGM.IntTy, 2257 CGM.Int64Ty, 2258 CGM.VoidPtrTy}; 2259 auto *FnTy = 2260 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2261 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2262 break; 2263 } 2264 case OMPRTL__kmpc_doacross_init: { 2265 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2266 // num_dims, struct kmp_dim *dims); 2267 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2268 CGM.Int32Ty, 2269 CGM.Int32Ty, 2270 CGM.VoidPtrTy}; 2271 auto *FnTy = 2272 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2273 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2274 break; 2275 } 2276 case OMPRTL__kmpc_doacross_fini: { 2277 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2278 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2279 auto *FnTy = 2280 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2281 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2282 break; 2283 } 2284 case OMPRTL__kmpc_doacross_post: { 2285 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2286 // *vec); 2287 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2288 CGM.Int64Ty->getPointerTo()}; 2289 auto *FnTy = 2290 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2291 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2292 break; 2293 } 2294 case OMPRTL__kmpc_doacross_wait: { 2295 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2296 // *vec); 2297 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2298 CGM.Int64Ty->getPointerTo()}; 2299 auto *FnTy = 2300 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2301 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2302 break; 2303 } 2304 case OMPRTL__kmpc_task_reduction_init: { 2305 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2306 // *data); 2307 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2308 auto *FnTy = 2309 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2310 RTLFn = 2311 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2312 break; 2313 } 2314 case OMPRTL__kmpc_task_reduction_get_th_data: { 2315 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2316 // *d); 2317 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2318 auto *FnTy = 2319 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2320 RTLFn = CGM.CreateRuntimeFunction( 2321 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2322 break; 2323 } 2324 case OMPRTL__kmpc_alloc: { 2325 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2326 // al); omp_allocator_handle_t type is void *. 2327 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2328 auto *FnTy = 2329 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2330 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2331 break; 2332 } 2333 case OMPRTL__kmpc_free: { 2334 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2335 // al); omp_allocator_handle_t type is void *. 2336 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2337 auto *FnTy = 2338 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2339 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2340 break; 2341 } 2342 case OMPRTL__kmpc_push_target_tripcount: { 2343 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2344 // size); 2345 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2346 llvm::FunctionType *FnTy = 2347 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2348 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2349 break; 2350 } 2351 case OMPRTL__tgt_target: { 2352 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2353 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2354 // *arg_types); 2355 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2356 CGM.VoidPtrTy, 2357 CGM.Int32Ty, 2358 CGM.VoidPtrPtrTy, 2359 CGM.VoidPtrPtrTy, 2360 CGM.Int64Ty->getPointerTo(), 2361 CGM.Int64Ty->getPointerTo()}; 2362 auto *FnTy = 2363 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2364 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2365 break; 2366 } 2367 case OMPRTL__tgt_target_nowait: { 2368 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2369 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2370 // int64_t *arg_types); 2371 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2372 CGM.VoidPtrTy, 2373 CGM.Int32Ty, 2374 CGM.VoidPtrPtrTy, 2375 CGM.VoidPtrPtrTy, 2376 CGM.Int64Ty->getPointerTo(), 2377 CGM.Int64Ty->getPointerTo()}; 2378 auto *FnTy = 2379 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2380 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2381 break; 2382 } 2383 case OMPRTL__tgt_target_teams: { 2384 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2385 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2386 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2387 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2388 CGM.VoidPtrTy, 2389 CGM.Int32Ty, 2390 CGM.VoidPtrPtrTy, 2391 CGM.VoidPtrPtrTy, 2392 CGM.Int64Ty->getPointerTo(), 2393 CGM.Int64Ty->getPointerTo(), 2394 CGM.Int32Ty, 2395 CGM.Int32Ty}; 2396 auto *FnTy = 2397 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2398 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2399 break; 2400 } 2401 case OMPRTL__tgt_target_teams_nowait: { 2402 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2403 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2404 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2405 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2406 CGM.VoidPtrTy, 2407 CGM.Int32Ty, 2408 CGM.VoidPtrPtrTy, 2409 CGM.VoidPtrPtrTy, 2410 CGM.Int64Ty->getPointerTo(), 2411 CGM.Int64Ty->getPointerTo(), 2412 CGM.Int32Ty, 2413 CGM.Int32Ty}; 2414 auto *FnTy = 2415 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2416 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2417 break; 2418 } 2419 case OMPRTL__tgt_register_requires: { 2420 // Build void __tgt_register_requires(int64_t flags); 2421 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2422 auto *FnTy = 2423 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2424 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2425 break; 2426 } 2427 case OMPRTL__tgt_register_lib: { 2428 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 2429 QualType ParamTy = 2430 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2431 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2432 auto *FnTy = 2433 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2434 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 2435 break; 2436 } 2437 case OMPRTL__tgt_unregister_lib: { 2438 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 2439 QualType ParamTy = 2440 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2441 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2442 auto *FnTy = 2443 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2444 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 2445 break; 2446 } 2447 case OMPRTL__tgt_target_data_begin: { 2448 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2449 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2450 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2451 CGM.Int32Ty, 2452 CGM.VoidPtrPtrTy, 2453 CGM.VoidPtrPtrTy, 2454 CGM.Int64Ty->getPointerTo(), 2455 CGM.Int64Ty->getPointerTo()}; 2456 auto *FnTy = 2457 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2458 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2459 break; 2460 } 2461 case OMPRTL__tgt_target_data_begin_nowait: { 2462 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2463 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2464 // *arg_types); 2465 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2466 CGM.Int32Ty, 2467 CGM.VoidPtrPtrTy, 2468 CGM.VoidPtrPtrTy, 2469 CGM.Int64Ty->getPointerTo(), 2470 CGM.Int64Ty->getPointerTo()}; 2471 auto *FnTy = 2472 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2473 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2474 break; 2475 } 2476 case OMPRTL__tgt_target_data_end: { 2477 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2478 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2479 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2480 CGM.Int32Ty, 2481 CGM.VoidPtrPtrTy, 2482 CGM.VoidPtrPtrTy, 2483 CGM.Int64Ty->getPointerTo(), 2484 CGM.Int64Ty->getPointerTo()}; 2485 auto *FnTy = 2486 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2487 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2488 break; 2489 } 2490 case OMPRTL__tgt_target_data_end_nowait: { 2491 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2492 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2493 // *arg_types); 2494 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2495 CGM.Int32Ty, 2496 CGM.VoidPtrPtrTy, 2497 CGM.VoidPtrPtrTy, 2498 CGM.Int64Ty->getPointerTo(), 2499 CGM.Int64Ty->getPointerTo()}; 2500 auto *FnTy = 2501 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2502 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2503 break; 2504 } 2505 case OMPRTL__tgt_target_data_update: { 2506 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2507 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2508 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2509 CGM.Int32Ty, 2510 CGM.VoidPtrPtrTy, 2511 CGM.VoidPtrPtrTy, 2512 CGM.Int64Ty->getPointerTo(), 2513 CGM.Int64Ty->getPointerTo()}; 2514 auto *FnTy = 2515 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2516 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2517 break; 2518 } 2519 case OMPRTL__tgt_target_data_update_nowait: { 2520 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2521 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2522 // *arg_types); 2523 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2524 CGM.Int32Ty, 2525 CGM.VoidPtrPtrTy, 2526 CGM.VoidPtrPtrTy, 2527 CGM.Int64Ty->getPointerTo(), 2528 CGM.Int64Ty->getPointerTo()}; 2529 auto *FnTy = 2530 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2531 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2532 break; 2533 } 2534 case OMPRTL__tgt_mapper_num_components: { 2535 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2536 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2537 auto *FnTy = 2538 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2539 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2540 break; 2541 } 2542 case OMPRTL__tgt_push_mapper_component: { 2543 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2544 // *base, void *begin, int64_t size, int64_t type); 2545 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2546 CGM.Int64Ty, CGM.Int64Ty}; 2547 auto *FnTy = 2548 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2549 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2550 break; 2551 } 2552 } 2553 assert(RTLFn && "Unable to find OpenMP runtime function"); 2554 return RTLFn; 2555 } 2556 2557 llvm::FunctionCallee 2558 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2559 assert((IVSize == 32 || IVSize == 64) && 2560 "IV size is not compatible with the omp runtime"); 2561 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2562 : "__kmpc_for_static_init_4u") 2563 : (IVSigned ? "__kmpc_for_static_init_8" 2564 : "__kmpc_for_static_init_8u"); 2565 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2566 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2567 llvm::Type *TypeParams[] = { 2568 getIdentTyPointerTy(), // loc 2569 CGM.Int32Ty, // tid 2570 CGM.Int32Ty, // schedtype 2571 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2572 PtrTy, // p_lower 2573 PtrTy, // p_upper 2574 PtrTy, // p_stride 2575 ITy, // incr 2576 ITy // chunk 2577 }; 2578 auto *FnTy = 2579 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2580 return CGM.CreateRuntimeFunction(FnTy, Name); 2581 } 2582 2583 llvm::FunctionCallee 2584 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2585 assert((IVSize == 32 || IVSize == 64) && 2586 "IV size is not compatible with the omp runtime"); 2587 StringRef Name = 2588 IVSize == 32 2589 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2590 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2591 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2592 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2593 CGM.Int32Ty, // tid 2594 CGM.Int32Ty, // schedtype 2595 ITy, // lower 2596 ITy, // upper 2597 ITy, // stride 2598 ITy // chunk 2599 }; 2600 auto *FnTy = 2601 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2602 return CGM.CreateRuntimeFunction(FnTy, Name); 2603 } 2604 2605 llvm::FunctionCallee 2606 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2607 assert((IVSize == 32 || IVSize == 64) && 2608 "IV size is not compatible with the omp runtime"); 2609 StringRef Name = 2610 IVSize == 32 2611 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2612 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2613 llvm::Type *TypeParams[] = { 2614 getIdentTyPointerTy(), // loc 2615 CGM.Int32Ty, // tid 2616 }; 2617 auto *FnTy = 2618 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2619 return CGM.CreateRuntimeFunction(FnTy, Name); 2620 } 2621 2622 llvm::FunctionCallee 2623 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2624 assert((IVSize == 32 || IVSize == 64) && 2625 "IV size is not compatible with the omp runtime"); 2626 StringRef Name = 2627 IVSize == 32 2628 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2629 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2630 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2631 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2632 llvm::Type *TypeParams[] = { 2633 getIdentTyPointerTy(), // loc 2634 CGM.Int32Ty, // tid 2635 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2636 PtrTy, // p_lower 2637 PtrTy, // p_upper 2638 PtrTy // p_stride 2639 }; 2640 auto *FnTy = 2641 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2642 return CGM.CreateRuntimeFunction(FnTy, Name); 2643 } 2644 2645 /// Obtain information that uniquely identifies a target entry. This 2646 /// consists of the file and device IDs as well as line number associated with 2647 /// the relevant entry source location. 2648 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2649 unsigned &DeviceID, unsigned &FileID, 2650 unsigned &LineNum) { 2651 SourceManager &SM = C.getSourceManager(); 2652 2653 // The loc should be always valid and have a file ID (the user cannot use 2654 // #pragma directives in macros) 2655 2656 assert(Loc.isValid() && "Source location is expected to be always valid."); 2657 2658 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2659 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2660 2661 llvm::sys::fs::UniqueID ID; 2662 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2663 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2664 << PLoc.getFilename() << EC.message(); 2665 2666 DeviceID = ID.getDevice(); 2667 FileID = ID.getFile(); 2668 LineNum = PLoc.getLine(); 2669 } 2670 2671 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2672 if (CGM.getLangOpts().OpenMPSimd) 2673 return Address::invalid(); 2674 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2675 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2676 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2677 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2678 HasRequiresUnifiedSharedMemory))) { 2679 SmallString<64> PtrName; 2680 { 2681 llvm::raw_svector_ostream OS(PtrName); 2682 OS << CGM.getMangledName(GlobalDecl(VD)); 2683 if (!VD->isExternallyVisible()) { 2684 unsigned DeviceID, FileID, Line; 2685 getTargetEntryUniqueInfo(CGM.getContext(), 2686 VD->getCanonicalDecl()->getBeginLoc(), 2687 DeviceID, FileID, Line); 2688 OS << llvm::format("_%x", FileID); 2689 } 2690 OS << "_decl_tgt_ref_ptr"; 2691 } 2692 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2693 if (!Ptr) { 2694 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2695 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2696 PtrName); 2697 2698 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2699 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2700 2701 if (!CGM.getLangOpts().OpenMPIsDevice) 2702 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2703 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2704 } 2705 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2706 } 2707 return Address::invalid(); 2708 } 2709 2710 llvm::Constant * 2711 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2712 assert(!CGM.getLangOpts().OpenMPUseTLS || 2713 !CGM.getContext().getTargetInfo().isTLSSupported()); 2714 // Lookup the entry, lazily creating it if necessary. 2715 std::string Suffix = getName({"cache", ""}); 2716 return getOrCreateInternalVariable( 2717 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2718 } 2719 2720 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2721 const VarDecl *VD, 2722 Address VDAddr, 2723 SourceLocation Loc) { 2724 if (CGM.getLangOpts().OpenMPUseTLS && 2725 CGM.getContext().getTargetInfo().isTLSSupported()) 2726 return VDAddr; 2727 2728 llvm::Type *VarTy = VDAddr.getElementType(); 2729 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2730 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2731 CGM.Int8PtrTy), 2732 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2733 getOrCreateThreadPrivateCache(VD)}; 2734 return Address(CGF.EmitRuntimeCall( 2735 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2736 VDAddr.getAlignment()); 2737 } 2738 2739 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2740 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2741 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2742 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2743 // library. 2744 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2745 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2746 OMPLoc); 2747 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2748 // to register constructor/destructor for variable. 2749 llvm::Value *Args[] = { 2750 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2751 Ctor, CopyCtor, Dtor}; 2752 CGF.EmitRuntimeCall( 2753 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2754 } 2755 2756 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2757 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2758 bool PerformInit, CodeGenFunction *CGF) { 2759 if (CGM.getLangOpts().OpenMPUseTLS && 2760 CGM.getContext().getTargetInfo().isTLSSupported()) 2761 return nullptr; 2762 2763 VD = VD->getDefinition(CGM.getContext()); 2764 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2765 QualType ASTTy = VD->getType(); 2766 2767 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2768 const Expr *Init = VD->getAnyInitializer(); 2769 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2770 // Generate function that re-emits the declaration's initializer into the 2771 // threadprivate copy of the variable VD 2772 CodeGenFunction CtorCGF(CGM); 2773 FunctionArgList Args; 2774 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2775 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2776 ImplicitParamDecl::Other); 2777 Args.push_back(&Dst); 2778 2779 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2780 CGM.getContext().VoidPtrTy, Args); 2781 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2782 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2783 llvm::Function *Fn = 2784 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2785 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2786 Args, Loc, Loc); 2787 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2788 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2789 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2790 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2791 Arg = CtorCGF.Builder.CreateElementBitCast( 2792 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2793 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2794 /*IsInitializer=*/true); 2795 ArgVal = CtorCGF.EmitLoadOfScalar( 2796 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2797 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2798 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2799 CtorCGF.FinishFunction(); 2800 Ctor = Fn; 2801 } 2802 if (VD->getType().isDestructedType() != QualType::DK_none) { 2803 // Generate function that emits destructor call for the threadprivate copy 2804 // of the variable VD 2805 CodeGenFunction DtorCGF(CGM); 2806 FunctionArgList Args; 2807 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2808 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2809 ImplicitParamDecl::Other); 2810 Args.push_back(&Dst); 2811 2812 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2813 CGM.getContext().VoidTy, Args); 2814 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2815 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2816 llvm::Function *Fn = 2817 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2818 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2819 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2820 Loc, Loc); 2821 // Create a scope with an artificial location for the body of this function. 2822 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2823 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2824 DtorCGF.GetAddrOfLocalVar(&Dst), 2825 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2826 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2827 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2828 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2829 DtorCGF.FinishFunction(); 2830 Dtor = Fn; 2831 } 2832 // Do not emit init function if it is not required. 2833 if (!Ctor && !Dtor) 2834 return nullptr; 2835 2836 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2837 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2838 /*isVarArg=*/false) 2839 ->getPointerTo(); 2840 // Copying constructor for the threadprivate variable. 2841 // Must be NULL - reserved by runtime, but currently it requires that this 2842 // parameter is always NULL. Otherwise it fires assertion. 2843 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2844 if (Ctor == nullptr) { 2845 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2846 /*isVarArg=*/false) 2847 ->getPointerTo(); 2848 Ctor = llvm::Constant::getNullValue(CtorTy); 2849 } 2850 if (Dtor == nullptr) { 2851 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2852 /*isVarArg=*/false) 2853 ->getPointerTo(); 2854 Dtor = llvm::Constant::getNullValue(DtorTy); 2855 } 2856 if (!CGF) { 2857 auto *InitFunctionTy = 2858 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2859 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2860 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2861 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2862 CodeGenFunction InitCGF(CGM); 2863 FunctionArgList ArgList; 2864 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2865 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2866 Loc, Loc); 2867 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2868 InitCGF.FinishFunction(); 2869 return InitFunction; 2870 } 2871 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2872 } 2873 return nullptr; 2874 } 2875 2876 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2877 llvm::GlobalVariable *Addr, 2878 bool PerformInit) { 2879 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2880 !CGM.getLangOpts().OpenMPIsDevice) 2881 return false; 2882 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2883 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2884 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2885 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2886 HasRequiresUnifiedSharedMemory)) 2887 return CGM.getLangOpts().OpenMPIsDevice; 2888 VD = VD->getDefinition(CGM.getContext()); 2889 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2890 return CGM.getLangOpts().OpenMPIsDevice; 2891 2892 QualType ASTTy = VD->getType(); 2893 2894 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2895 // Produce the unique prefix to identify the new target regions. We use 2896 // the source location of the variable declaration which we know to not 2897 // conflict with any target region. 2898 unsigned DeviceID; 2899 unsigned FileID; 2900 unsigned Line; 2901 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2902 SmallString<128> Buffer, Out; 2903 { 2904 llvm::raw_svector_ostream OS(Buffer); 2905 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2906 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2907 } 2908 2909 const Expr *Init = VD->getAnyInitializer(); 2910 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2911 llvm::Constant *Ctor; 2912 llvm::Constant *ID; 2913 if (CGM.getLangOpts().OpenMPIsDevice) { 2914 // Generate function that re-emits the declaration's initializer into 2915 // the threadprivate copy of the variable VD 2916 CodeGenFunction CtorCGF(CGM); 2917 2918 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2919 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2920 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2921 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2922 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2923 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2924 FunctionArgList(), Loc, Loc); 2925 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2926 CtorCGF.EmitAnyExprToMem(Init, 2927 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2928 Init->getType().getQualifiers(), 2929 /*IsInitializer=*/true); 2930 CtorCGF.FinishFunction(); 2931 Ctor = Fn; 2932 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2933 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2934 } else { 2935 Ctor = new llvm::GlobalVariable( 2936 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2937 llvm::GlobalValue::PrivateLinkage, 2938 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2939 ID = Ctor; 2940 } 2941 2942 // Register the information for the entry associated with the constructor. 2943 Out.clear(); 2944 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2945 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2946 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2947 } 2948 if (VD->getType().isDestructedType() != QualType::DK_none) { 2949 llvm::Constant *Dtor; 2950 llvm::Constant *ID; 2951 if (CGM.getLangOpts().OpenMPIsDevice) { 2952 // Generate function that emits destructor call for the threadprivate 2953 // copy of the variable VD 2954 CodeGenFunction DtorCGF(CGM); 2955 2956 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2957 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2958 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2959 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2960 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2961 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2962 FunctionArgList(), Loc, Loc); 2963 // Create a scope with an artificial location for the body of this 2964 // function. 2965 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2966 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 2967 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2968 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2969 DtorCGF.FinishFunction(); 2970 Dtor = Fn; 2971 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2972 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 2973 } else { 2974 Dtor = new llvm::GlobalVariable( 2975 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2976 llvm::GlobalValue::PrivateLinkage, 2977 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 2978 ID = Dtor; 2979 } 2980 // Register the information for the entry associated with the destructor. 2981 Out.clear(); 2982 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2983 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2984 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2985 } 2986 return CGM.getLangOpts().OpenMPIsDevice; 2987 } 2988 2989 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2990 QualType VarType, 2991 StringRef Name) { 2992 std::string Suffix = getName({"artificial", ""}); 2993 std::string CacheSuffix = getName({"cache", ""}); 2994 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2995 llvm::Value *GAddr = 2996 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2997 llvm::Value *Args[] = { 2998 emitUpdateLocation(CGF, SourceLocation()), 2999 getThreadID(CGF, SourceLocation()), 3000 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 3001 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 3002 /*isSigned=*/false), 3003 getOrCreateInternalVariable( 3004 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 3005 return Address( 3006 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3007 CGF.EmitRuntimeCall( 3008 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3009 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3010 CGM.getPointerAlign()); 3011 } 3012 3013 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 3014 const RegionCodeGenTy &ThenGen, 3015 const RegionCodeGenTy &ElseGen) { 3016 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3017 3018 // If the condition constant folds and can be elided, try to avoid emitting 3019 // the condition and the dead arm of the if/else. 3020 bool CondConstant; 3021 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3022 if (CondConstant) 3023 ThenGen(CGF); 3024 else 3025 ElseGen(CGF); 3026 return; 3027 } 3028 3029 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3030 // emit the conditional branch. 3031 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3032 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3033 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3034 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3035 3036 // Emit the 'then' code. 3037 CGF.EmitBlock(ThenBlock); 3038 ThenGen(CGF); 3039 CGF.EmitBranch(ContBlock); 3040 // Emit the 'else' code if present. 3041 // There is no need to emit line number for unconditional branch. 3042 (void)ApplyDebugLocation::CreateEmpty(CGF); 3043 CGF.EmitBlock(ElseBlock); 3044 ElseGen(CGF); 3045 // There is no need to emit line number for unconditional branch. 3046 (void)ApplyDebugLocation::CreateEmpty(CGF); 3047 CGF.EmitBranch(ContBlock); 3048 // Emit the continuation block for code after the if. 3049 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3050 } 3051 3052 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3053 llvm::Function *OutlinedFn, 3054 ArrayRef<llvm::Value *> CapturedVars, 3055 const Expr *IfCond) { 3056 if (!CGF.HaveInsertPoint()) 3057 return; 3058 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3059 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3060 PrePostActionTy &) { 3061 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3062 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3063 llvm::Value *Args[] = { 3064 RTLoc, 3065 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3066 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3067 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3068 RealArgs.append(std::begin(Args), std::end(Args)); 3069 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3070 3071 llvm::FunctionCallee RTLFn = 3072 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3073 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3074 }; 3075 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3076 PrePostActionTy &) { 3077 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3078 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3079 // Build calls: 3080 // __kmpc_serialized_parallel(&Loc, GTid); 3081 llvm::Value *Args[] = {RTLoc, ThreadID}; 3082 CGF.EmitRuntimeCall( 3083 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3084 3085 // OutlinedFn(>id, &zero_bound, CapturedStruct); 3086 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 3087 Address ZeroAddrBound = 3088 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3089 /*Name=*/".bound.zero.addr"); 3090 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 3091 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3092 // ThreadId for serialized parallels is 0. 3093 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 3094 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 3095 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3096 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3097 3098 // __kmpc_end_serialized_parallel(&Loc, GTid); 3099 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3100 CGF.EmitRuntimeCall( 3101 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3102 EndArgs); 3103 }; 3104 if (IfCond) { 3105 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 3106 } else { 3107 RegionCodeGenTy ThenRCG(ThenGen); 3108 ThenRCG(CGF); 3109 } 3110 } 3111 3112 // If we're inside an (outlined) parallel region, use the region info's 3113 // thread-ID variable (it is passed in a first argument of the outlined function 3114 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3115 // regular serial code region, get thread ID by calling kmp_int32 3116 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3117 // return the address of that temp. 3118 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3119 SourceLocation Loc) { 3120 if (auto *OMPRegionInfo = 3121 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3122 if (OMPRegionInfo->getThreadIDVariable()) 3123 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 3124 3125 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3126 QualType Int32Ty = 3127 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3128 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3129 CGF.EmitStoreOfScalar(ThreadID, 3130 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3131 3132 return ThreadIDTemp; 3133 } 3134 3135 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3136 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3137 SmallString<256> Buffer; 3138 llvm::raw_svector_ostream Out(Buffer); 3139 Out << Name; 3140 StringRef RuntimeName = Out.str(); 3141 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3142 if (Elem.second) { 3143 assert(Elem.second->getType()->getPointerElementType() == Ty && 3144 "OMP internal variable has different type than requested"); 3145 return &*Elem.second; 3146 } 3147 3148 return Elem.second = new llvm::GlobalVariable( 3149 CGM.getModule(), Ty, /*IsConstant*/ false, 3150 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3151 Elem.first(), /*InsertBefore=*/nullptr, 3152 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3153 } 3154 3155 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3156 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3157 std::string Name = getName({Prefix, "var"}); 3158 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3159 } 3160 3161 namespace { 3162 /// Common pre(post)-action for different OpenMP constructs. 3163 class CommonActionTy final : public PrePostActionTy { 3164 llvm::FunctionCallee EnterCallee; 3165 ArrayRef<llvm::Value *> EnterArgs; 3166 llvm::FunctionCallee ExitCallee; 3167 ArrayRef<llvm::Value *> ExitArgs; 3168 bool Conditional; 3169 llvm::BasicBlock *ContBlock = nullptr; 3170 3171 public: 3172 CommonActionTy(llvm::FunctionCallee EnterCallee, 3173 ArrayRef<llvm::Value *> EnterArgs, 3174 llvm::FunctionCallee ExitCallee, 3175 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3176 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3177 ExitArgs(ExitArgs), Conditional(Conditional) {} 3178 void Enter(CodeGenFunction &CGF) override { 3179 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3180 if (Conditional) { 3181 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3182 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3183 ContBlock = CGF.createBasicBlock("omp_if.end"); 3184 // Generate the branch (If-stmt) 3185 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3186 CGF.EmitBlock(ThenBlock); 3187 } 3188 } 3189 void Done(CodeGenFunction &CGF) { 3190 // Emit the rest of blocks/branches 3191 CGF.EmitBranch(ContBlock); 3192 CGF.EmitBlock(ContBlock, true); 3193 } 3194 void Exit(CodeGenFunction &CGF) override { 3195 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3196 } 3197 }; 3198 } // anonymous namespace 3199 3200 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3201 StringRef CriticalName, 3202 const RegionCodeGenTy &CriticalOpGen, 3203 SourceLocation Loc, const Expr *Hint) { 3204 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3205 // CriticalOpGen(); 3206 // __kmpc_end_critical(ident_t *, gtid, Lock); 3207 // Prepare arguments and build a call to __kmpc_critical 3208 if (!CGF.HaveInsertPoint()) 3209 return; 3210 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3211 getCriticalRegionLock(CriticalName)}; 3212 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3213 std::end(Args)); 3214 if (Hint) { 3215 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3216 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3217 } 3218 CommonActionTy Action( 3219 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3220 : OMPRTL__kmpc_critical), 3221 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3222 CriticalOpGen.setAction(Action); 3223 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3224 } 3225 3226 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3227 const RegionCodeGenTy &MasterOpGen, 3228 SourceLocation Loc) { 3229 if (!CGF.HaveInsertPoint()) 3230 return; 3231 // if(__kmpc_master(ident_t *, gtid)) { 3232 // MasterOpGen(); 3233 // __kmpc_end_master(ident_t *, gtid); 3234 // } 3235 // Prepare arguments and build a call to __kmpc_master 3236 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3237 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3238 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3239 /*Conditional=*/true); 3240 MasterOpGen.setAction(Action); 3241 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3242 Action.Done(CGF); 3243 } 3244 3245 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3246 SourceLocation Loc) { 3247 if (!CGF.HaveInsertPoint()) 3248 return; 3249 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3250 llvm::Value *Args[] = { 3251 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3252 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3253 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3254 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3255 Region->emitUntiedSwitch(CGF); 3256 } 3257 3258 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3259 const RegionCodeGenTy &TaskgroupOpGen, 3260 SourceLocation Loc) { 3261 if (!CGF.HaveInsertPoint()) 3262 return; 3263 // __kmpc_taskgroup(ident_t *, gtid); 3264 // TaskgroupOpGen(); 3265 // __kmpc_end_taskgroup(ident_t *, gtid); 3266 // Prepare arguments and build a call to __kmpc_taskgroup 3267 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3268 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3269 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3270 Args); 3271 TaskgroupOpGen.setAction(Action); 3272 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3273 } 3274 3275 /// Given an array of pointers to variables, project the address of a 3276 /// given variable. 3277 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3278 unsigned Index, const VarDecl *Var) { 3279 // Pull out the pointer to the variable. 3280 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3281 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3282 3283 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3284 Addr = CGF.Builder.CreateElementBitCast( 3285 Addr, CGF.ConvertTypeForMem(Var->getType())); 3286 return Addr; 3287 } 3288 3289 static llvm::Value *emitCopyprivateCopyFunction( 3290 CodeGenModule &CGM, llvm::Type *ArgsType, 3291 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3292 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3293 SourceLocation Loc) { 3294 ASTContext &C = CGM.getContext(); 3295 // void copy_func(void *LHSArg, void *RHSArg); 3296 FunctionArgList Args; 3297 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3298 ImplicitParamDecl::Other); 3299 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3300 ImplicitParamDecl::Other); 3301 Args.push_back(&LHSArg); 3302 Args.push_back(&RHSArg); 3303 const auto &CGFI = 3304 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3305 std::string Name = 3306 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3307 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3308 llvm::GlobalValue::InternalLinkage, Name, 3309 &CGM.getModule()); 3310 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3311 Fn->setDoesNotRecurse(); 3312 CodeGenFunction CGF(CGM); 3313 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3314 // Dest = (void*[n])(LHSArg); 3315 // Src = (void*[n])(RHSArg); 3316 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3317 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3318 ArgsType), CGF.getPointerAlign()); 3319 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3320 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3321 ArgsType), CGF.getPointerAlign()); 3322 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3323 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3324 // ... 3325 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3326 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3327 const auto *DestVar = 3328 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3329 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3330 3331 const auto *SrcVar = 3332 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3333 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3334 3335 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3336 QualType Type = VD->getType(); 3337 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3338 } 3339 CGF.FinishFunction(); 3340 return Fn; 3341 } 3342 3343 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3344 const RegionCodeGenTy &SingleOpGen, 3345 SourceLocation Loc, 3346 ArrayRef<const Expr *> CopyprivateVars, 3347 ArrayRef<const Expr *> SrcExprs, 3348 ArrayRef<const Expr *> DstExprs, 3349 ArrayRef<const Expr *> AssignmentOps) { 3350 if (!CGF.HaveInsertPoint()) 3351 return; 3352 assert(CopyprivateVars.size() == SrcExprs.size() && 3353 CopyprivateVars.size() == DstExprs.size() && 3354 CopyprivateVars.size() == AssignmentOps.size()); 3355 ASTContext &C = CGM.getContext(); 3356 // int32 did_it = 0; 3357 // if(__kmpc_single(ident_t *, gtid)) { 3358 // SingleOpGen(); 3359 // __kmpc_end_single(ident_t *, gtid); 3360 // did_it = 1; 3361 // } 3362 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3363 // <copy_func>, did_it); 3364 3365 Address DidIt = Address::invalid(); 3366 if (!CopyprivateVars.empty()) { 3367 // int32 did_it = 0; 3368 QualType KmpInt32Ty = 3369 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3370 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3371 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3372 } 3373 // Prepare arguments and build a call to __kmpc_single 3374 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3375 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3376 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3377 /*Conditional=*/true); 3378 SingleOpGen.setAction(Action); 3379 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3380 if (DidIt.isValid()) { 3381 // did_it = 1; 3382 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3383 } 3384 Action.Done(CGF); 3385 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3386 // <copy_func>, did_it); 3387 if (DidIt.isValid()) { 3388 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3389 QualType CopyprivateArrayTy = C.getConstantArrayType( 3390 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3391 /*IndexTypeQuals=*/0); 3392 // Create a list of all private variables for copyprivate. 3393 Address CopyprivateList = 3394 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3395 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3396 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3397 CGF.Builder.CreateStore( 3398 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3399 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 3400 CGF.VoidPtrTy), 3401 Elem); 3402 } 3403 // Build function that copies private values from single region to all other 3404 // threads in the corresponding parallel region. 3405 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3406 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3407 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3408 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3409 Address CL = 3410 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3411 CGF.VoidPtrTy); 3412 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3413 llvm::Value *Args[] = { 3414 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3415 getThreadID(CGF, Loc), // i32 <gtid> 3416 BufSize, // size_t <buf_size> 3417 CL.getPointer(), // void *<copyprivate list> 3418 CpyFn, // void (*) (void *, void *) <copy_func> 3419 DidItVal // i32 did_it 3420 }; 3421 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3422 } 3423 } 3424 3425 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3426 const RegionCodeGenTy &OrderedOpGen, 3427 SourceLocation Loc, bool IsThreads) { 3428 if (!CGF.HaveInsertPoint()) 3429 return; 3430 // __kmpc_ordered(ident_t *, gtid); 3431 // OrderedOpGen(); 3432 // __kmpc_end_ordered(ident_t *, gtid); 3433 // Prepare arguments and build a call to __kmpc_ordered 3434 if (IsThreads) { 3435 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3436 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3437 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3438 Args); 3439 OrderedOpGen.setAction(Action); 3440 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3441 return; 3442 } 3443 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3444 } 3445 3446 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3447 unsigned Flags; 3448 if (Kind == OMPD_for) 3449 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3450 else if (Kind == OMPD_sections) 3451 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3452 else if (Kind == OMPD_single) 3453 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3454 else if (Kind == OMPD_barrier) 3455 Flags = OMP_IDENT_BARRIER_EXPL; 3456 else 3457 Flags = OMP_IDENT_BARRIER_IMPL; 3458 return Flags; 3459 } 3460 3461 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3462 CodeGenFunction &CGF, const OMPLoopDirective &S, 3463 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3464 // Check if the loop directive is actually a doacross loop directive. In this 3465 // case choose static, 1 schedule. 3466 if (llvm::any_of( 3467 S.getClausesOfKind<OMPOrderedClause>(), 3468 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3469 ScheduleKind = OMPC_SCHEDULE_static; 3470 // Chunk size is 1 in this case. 3471 llvm::APInt ChunkSize(32, 1); 3472 ChunkExpr = IntegerLiteral::Create( 3473 CGF.getContext(), ChunkSize, 3474 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3475 SourceLocation()); 3476 } 3477 } 3478 3479 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3480 OpenMPDirectiveKind Kind, bool EmitChecks, 3481 bool ForceSimpleCall) { 3482 if (!CGF.HaveInsertPoint()) 3483 return; 3484 // Build call __kmpc_cancel_barrier(loc, thread_id); 3485 // Build call __kmpc_barrier(loc, thread_id); 3486 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3487 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3488 // thread_id); 3489 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3490 getThreadID(CGF, Loc)}; 3491 if (auto *OMPRegionInfo = 3492 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 3493 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3494 llvm::Value *Result = CGF.EmitRuntimeCall( 3495 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3496 if (EmitChecks) { 3497 // if (__kmpc_cancel_barrier()) { 3498 // exit from construct; 3499 // } 3500 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3501 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3502 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3503 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3504 CGF.EmitBlock(ExitBB); 3505 // exit from construct; 3506 CodeGenFunction::JumpDest CancelDestination = 3507 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3508 CGF.EmitBranchThroughCleanup(CancelDestination); 3509 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3510 } 3511 return; 3512 } 3513 } 3514 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3515 } 3516 3517 /// Map the OpenMP loop schedule to the runtime enumeration. 3518 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3519 bool Chunked, bool Ordered) { 3520 switch (ScheduleKind) { 3521 case OMPC_SCHEDULE_static: 3522 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3523 : (Ordered ? OMP_ord_static : OMP_sch_static); 3524 case OMPC_SCHEDULE_dynamic: 3525 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3526 case OMPC_SCHEDULE_guided: 3527 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3528 case OMPC_SCHEDULE_runtime: 3529 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3530 case OMPC_SCHEDULE_auto: 3531 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3532 case OMPC_SCHEDULE_unknown: 3533 assert(!Chunked && "chunk was specified but schedule kind not known"); 3534 return Ordered ? OMP_ord_static : OMP_sch_static; 3535 } 3536 llvm_unreachable("Unexpected runtime schedule"); 3537 } 3538 3539 /// Map the OpenMP distribute schedule to the runtime enumeration. 3540 static OpenMPSchedType 3541 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3542 // only static is allowed for dist_schedule 3543 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3544 } 3545 3546 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3547 bool Chunked) const { 3548 OpenMPSchedType Schedule = 3549 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3550 return Schedule == OMP_sch_static; 3551 } 3552 3553 bool CGOpenMPRuntime::isStaticNonchunked( 3554 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3555 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3556 return Schedule == OMP_dist_sch_static; 3557 } 3558 3559 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3560 bool Chunked) const { 3561 OpenMPSchedType Schedule = 3562 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3563 return Schedule == OMP_sch_static_chunked; 3564 } 3565 3566 bool CGOpenMPRuntime::isStaticChunked( 3567 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3568 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3569 return Schedule == OMP_dist_sch_static_chunked; 3570 } 3571 3572 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3573 OpenMPSchedType Schedule = 3574 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3575 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3576 return Schedule != OMP_sch_static; 3577 } 3578 3579 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3580 OpenMPScheduleClauseModifier M1, 3581 OpenMPScheduleClauseModifier M2) { 3582 int Modifier = 0; 3583 switch (M1) { 3584 case OMPC_SCHEDULE_MODIFIER_monotonic: 3585 Modifier = OMP_sch_modifier_monotonic; 3586 break; 3587 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3588 Modifier = OMP_sch_modifier_nonmonotonic; 3589 break; 3590 case OMPC_SCHEDULE_MODIFIER_simd: 3591 if (Schedule == OMP_sch_static_chunked) 3592 Schedule = OMP_sch_static_balanced_chunked; 3593 break; 3594 case OMPC_SCHEDULE_MODIFIER_last: 3595 case OMPC_SCHEDULE_MODIFIER_unknown: 3596 break; 3597 } 3598 switch (M2) { 3599 case OMPC_SCHEDULE_MODIFIER_monotonic: 3600 Modifier = OMP_sch_modifier_monotonic; 3601 break; 3602 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3603 Modifier = OMP_sch_modifier_nonmonotonic; 3604 break; 3605 case OMPC_SCHEDULE_MODIFIER_simd: 3606 if (Schedule == OMP_sch_static_chunked) 3607 Schedule = OMP_sch_static_balanced_chunked; 3608 break; 3609 case OMPC_SCHEDULE_MODIFIER_last: 3610 case OMPC_SCHEDULE_MODIFIER_unknown: 3611 break; 3612 } 3613 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3614 // If the static schedule kind is specified or if the ordered clause is 3615 // specified, and if the nonmonotonic modifier is not specified, the effect is 3616 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3617 // modifier is specified, the effect is as if the nonmonotonic modifier is 3618 // specified. 3619 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3620 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3621 Schedule == OMP_sch_static_balanced_chunked || 3622 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 3623 Schedule == OMP_dist_sch_static_chunked || 3624 Schedule == OMP_dist_sch_static)) 3625 Modifier = OMP_sch_modifier_nonmonotonic; 3626 } 3627 return Schedule | Modifier; 3628 } 3629 3630 void CGOpenMPRuntime::emitForDispatchInit( 3631 CodeGenFunction &CGF, SourceLocation Loc, 3632 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3633 bool Ordered, const DispatchRTInput &DispatchValues) { 3634 if (!CGF.HaveInsertPoint()) 3635 return; 3636 OpenMPSchedType Schedule = getRuntimeSchedule( 3637 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3638 assert(Ordered || 3639 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3640 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3641 Schedule != OMP_sch_static_balanced_chunked)); 3642 // Call __kmpc_dispatch_init( 3643 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3644 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3645 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3646 3647 // If the Chunk was not specified in the clause - use default value 1. 3648 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3649 : CGF.Builder.getIntN(IVSize, 1); 3650 llvm::Value *Args[] = { 3651 emitUpdateLocation(CGF, Loc), 3652 getThreadID(CGF, Loc), 3653 CGF.Builder.getInt32(addMonoNonMonoModifier( 3654 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3655 DispatchValues.LB, // Lower 3656 DispatchValues.UB, // Upper 3657 CGF.Builder.getIntN(IVSize, 1), // Stride 3658 Chunk // Chunk 3659 }; 3660 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3661 } 3662 3663 static void emitForStaticInitCall( 3664 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3665 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3666 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3667 const CGOpenMPRuntime::StaticRTInput &Values) { 3668 if (!CGF.HaveInsertPoint()) 3669 return; 3670 3671 assert(!Values.Ordered); 3672 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3673 Schedule == OMP_sch_static_balanced_chunked || 3674 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3675 Schedule == OMP_dist_sch_static || 3676 Schedule == OMP_dist_sch_static_chunked); 3677 3678 // Call __kmpc_for_static_init( 3679 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3680 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3681 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3682 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3683 llvm::Value *Chunk = Values.Chunk; 3684 if (Chunk == nullptr) { 3685 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3686 Schedule == OMP_dist_sch_static) && 3687 "expected static non-chunked schedule"); 3688 // If the Chunk was not specified in the clause - use default value 1. 3689 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3690 } else { 3691 assert((Schedule == OMP_sch_static_chunked || 3692 Schedule == OMP_sch_static_balanced_chunked || 3693 Schedule == OMP_ord_static_chunked || 3694 Schedule == OMP_dist_sch_static_chunked) && 3695 "expected static chunked schedule"); 3696 } 3697 llvm::Value *Args[] = { 3698 UpdateLocation, 3699 ThreadId, 3700 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3701 M2)), // Schedule type 3702 Values.IL.getPointer(), // &isLastIter 3703 Values.LB.getPointer(), // &LB 3704 Values.UB.getPointer(), // &UB 3705 Values.ST.getPointer(), // &Stride 3706 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3707 Chunk // Chunk 3708 }; 3709 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3710 } 3711 3712 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3713 SourceLocation Loc, 3714 OpenMPDirectiveKind DKind, 3715 const OpenMPScheduleTy &ScheduleKind, 3716 const StaticRTInput &Values) { 3717 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3718 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3719 assert(isOpenMPWorksharingDirective(DKind) && 3720 "Expected loop-based or sections-based directive."); 3721 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3722 isOpenMPLoopDirective(DKind) 3723 ? OMP_IDENT_WORK_LOOP 3724 : OMP_IDENT_WORK_SECTIONS); 3725 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3726 llvm::FunctionCallee StaticInitFunction = 3727 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3728 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3729 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3730 } 3731 3732 void CGOpenMPRuntime::emitDistributeStaticInit( 3733 CodeGenFunction &CGF, SourceLocation Loc, 3734 OpenMPDistScheduleClauseKind SchedKind, 3735 const CGOpenMPRuntime::StaticRTInput &Values) { 3736 OpenMPSchedType ScheduleNum = 3737 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3738 llvm::Value *UpdatedLocation = 3739 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3740 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3741 llvm::FunctionCallee StaticInitFunction = 3742 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3743 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3744 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3745 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3746 } 3747 3748 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3749 SourceLocation Loc, 3750 OpenMPDirectiveKind DKind) { 3751 if (!CGF.HaveInsertPoint()) 3752 return; 3753 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3754 llvm::Value *Args[] = { 3755 emitUpdateLocation(CGF, Loc, 3756 isOpenMPDistributeDirective(DKind) 3757 ? OMP_IDENT_WORK_DISTRIBUTE 3758 : isOpenMPLoopDirective(DKind) 3759 ? OMP_IDENT_WORK_LOOP 3760 : OMP_IDENT_WORK_SECTIONS), 3761 getThreadID(CGF, Loc)}; 3762 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3763 Args); 3764 } 3765 3766 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3767 SourceLocation Loc, 3768 unsigned IVSize, 3769 bool IVSigned) { 3770 if (!CGF.HaveInsertPoint()) 3771 return; 3772 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3773 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3774 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3775 } 3776 3777 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3778 SourceLocation Loc, unsigned IVSize, 3779 bool IVSigned, Address IL, 3780 Address LB, Address UB, 3781 Address ST) { 3782 // Call __kmpc_dispatch_next( 3783 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3784 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3785 // kmp_int[32|64] *p_stride); 3786 llvm::Value *Args[] = { 3787 emitUpdateLocation(CGF, Loc), 3788 getThreadID(CGF, Loc), 3789 IL.getPointer(), // &isLastIter 3790 LB.getPointer(), // &Lower 3791 UB.getPointer(), // &Upper 3792 ST.getPointer() // &Stride 3793 }; 3794 llvm::Value *Call = 3795 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3796 return CGF.EmitScalarConversion( 3797 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3798 CGF.getContext().BoolTy, Loc); 3799 } 3800 3801 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3802 llvm::Value *NumThreads, 3803 SourceLocation Loc) { 3804 if (!CGF.HaveInsertPoint()) 3805 return; 3806 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3807 llvm::Value *Args[] = { 3808 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3809 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3810 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3811 Args); 3812 } 3813 3814 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3815 OpenMPProcBindClauseKind ProcBind, 3816 SourceLocation Loc) { 3817 if (!CGF.HaveInsertPoint()) 3818 return; 3819 // Constants for proc bind value accepted by the runtime. 3820 enum ProcBindTy { 3821 ProcBindFalse = 0, 3822 ProcBindTrue, 3823 ProcBindMaster, 3824 ProcBindClose, 3825 ProcBindSpread, 3826 ProcBindIntel, 3827 ProcBindDefault 3828 } RuntimeProcBind; 3829 switch (ProcBind) { 3830 case OMPC_PROC_BIND_master: 3831 RuntimeProcBind = ProcBindMaster; 3832 break; 3833 case OMPC_PROC_BIND_close: 3834 RuntimeProcBind = ProcBindClose; 3835 break; 3836 case OMPC_PROC_BIND_spread: 3837 RuntimeProcBind = ProcBindSpread; 3838 break; 3839 case OMPC_PROC_BIND_unknown: 3840 llvm_unreachable("Unsupported proc_bind value."); 3841 } 3842 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3843 llvm::Value *Args[] = { 3844 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3845 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 3846 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3847 } 3848 3849 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3850 SourceLocation Loc) { 3851 if (!CGF.HaveInsertPoint()) 3852 return; 3853 // Build call void __kmpc_flush(ident_t *loc) 3854 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3855 emitUpdateLocation(CGF, Loc)); 3856 } 3857 3858 namespace { 3859 /// Indexes of fields for type kmp_task_t. 3860 enum KmpTaskTFields { 3861 /// List of shared variables. 3862 KmpTaskTShareds, 3863 /// Task routine. 3864 KmpTaskTRoutine, 3865 /// Partition id for the untied tasks. 3866 KmpTaskTPartId, 3867 /// Function with call of destructors for private variables. 3868 Data1, 3869 /// Task priority. 3870 Data2, 3871 /// (Taskloops only) Lower bound. 3872 KmpTaskTLowerBound, 3873 /// (Taskloops only) Upper bound. 3874 KmpTaskTUpperBound, 3875 /// (Taskloops only) Stride. 3876 KmpTaskTStride, 3877 /// (Taskloops only) Is last iteration flag. 3878 KmpTaskTLastIter, 3879 /// (Taskloops only) Reduction data. 3880 KmpTaskTReductions, 3881 }; 3882 } // anonymous namespace 3883 3884 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3885 return OffloadEntriesTargetRegion.empty() && 3886 OffloadEntriesDeviceGlobalVar.empty(); 3887 } 3888 3889 /// Initialize target region entry. 3890 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3891 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3892 StringRef ParentName, unsigned LineNum, 3893 unsigned Order) { 3894 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3895 "only required for the device " 3896 "code generation."); 3897 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3898 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3899 OMPTargetRegionEntryTargetRegion); 3900 ++OffloadingEntriesNum; 3901 } 3902 3903 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3904 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3905 StringRef ParentName, unsigned LineNum, 3906 llvm::Constant *Addr, llvm::Constant *ID, 3907 OMPTargetRegionEntryKind Flags) { 3908 // If we are emitting code for a target, the entry is already initialized, 3909 // only has to be registered. 3910 if (CGM.getLangOpts().OpenMPIsDevice) { 3911 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3912 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3913 DiagnosticsEngine::Error, 3914 "Unable to find target region on line '%0' in the device code."); 3915 CGM.getDiags().Report(DiagID) << LineNum; 3916 return; 3917 } 3918 auto &Entry = 3919 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3920 assert(Entry.isValid() && "Entry not initialized!"); 3921 Entry.setAddress(Addr); 3922 Entry.setID(ID); 3923 Entry.setFlags(Flags); 3924 } else { 3925 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3926 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3927 ++OffloadingEntriesNum; 3928 } 3929 } 3930 3931 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3932 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3933 unsigned LineNum) const { 3934 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3935 if (PerDevice == OffloadEntriesTargetRegion.end()) 3936 return false; 3937 auto PerFile = PerDevice->second.find(FileID); 3938 if (PerFile == PerDevice->second.end()) 3939 return false; 3940 auto PerParentName = PerFile->second.find(ParentName); 3941 if (PerParentName == PerFile->second.end()) 3942 return false; 3943 auto PerLine = PerParentName->second.find(LineNum); 3944 if (PerLine == PerParentName->second.end()) 3945 return false; 3946 // Fail if this entry is already registered. 3947 if (PerLine->second.getAddress() || PerLine->second.getID()) 3948 return false; 3949 return true; 3950 } 3951 3952 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3953 const OffloadTargetRegionEntryInfoActTy &Action) { 3954 // Scan all target region entries and perform the provided action. 3955 for (const auto &D : OffloadEntriesTargetRegion) 3956 for (const auto &F : D.second) 3957 for (const auto &P : F.second) 3958 for (const auto &L : P.second) 3959 Action(D.first, F.first, P.first(), L.first, L.second); 3960 } 3961 3962 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3963 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3964 OMPTargetGlobalVarEntryKind Flags, 3965 unsigned Order) { 3966 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3967 "only required for the device " 3968 "code generation."); 3969 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3970 ++OffloadingEntriesNum; 3971 } 3972 3973 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3974 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3975 CharUnits VarSize, 3976 OMPTargetGlobalVarEntryKind Flags, 3977 llvm::GlobalValue::LinkageTypes Linkage) { 3978 if (CGM.getLangOpts().OpenMPIsDevice) { 3979 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3980 assert(Entry.isValid() && Entry.getFlags() == Flags && 3981 "Entry not initialized!"); 3982 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3983 "Resetting with the new address."); 3984 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3985 if (Entry.getVarSize().isZero()) { 3986 Entry.setVarSize(VarSize); 3987 Entry.setLinkage(Linkage); 3988 } 3989 return; 3990 } 3991 Entry.setVarSize(VarSize); 3992 Entry.setLinkage(Linkage); 3993 Entry.setAddress(Addr); 3994 } else { 3995 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3996 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3997 assert(Entry.isValid() && Entry.getFlags() == Flags && 3998 "Entry not initialized!"); 3999 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4000 "Resetting with the new address."); 4001 if (Entry.getVarSize().isZero()) { 4002 Entry.setVarSize(VarSize); 4003 Entry.setLinkage(Linkage); 4004 } 4005 return; 4006 } 4007 OffloadEntriesDeviceGlobalVar.try_emplace( 4008 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 4009 ++OffloadingEntriesNum; 4010 } 4011 } 4012 4013 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4014 actOnDeviceGlobalVarEntriesInfo( 4015 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4016 // Scan all target region entries and perform the provided action. 4017 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4018 Action(E.getKey(), E.getValue()); 4019 } 4020 4021 void CGOpenMPRuntime::createOffloadEntry( 4022 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4023 llvm::GlobalValue::LinkageTypes Linkage) { 4024 StringRef Name = Addr->getName(); 4025 llvm::Module &M = CGM.getModule(); 4026 llvm::LLVMContext &C = M.getContext(); 4027 4028 // Create constant string with the name. 4029 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4030 4031 std::string StringName = getName({"omp_offloading", "entry_name"}); 4032 auto *Str = new llvm::GlobalVariable( 4033 M, StrPtrInit->getType(), /*isConstant=*/true, 4034 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4035 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4036 4037 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4038 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4039 llvm::ConstantInt::get(CGM.SizeTy, Size), 4040 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4041 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4042 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4043 llvm::GlobalVariable *Entry = createGlobalStruct( 4044 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4045 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4046 4047 // The entry has to be created in the section the linker expects it to be. 4048 Entry->setSection("omp_offloading_entries"); 4049 } 4050 4051 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4052 // Emit the offloading entries and metadata so that the device codegen side 4053 // can easily figure out what to emit. The produced metadata looks like 4054 // this: 4055 // 4056 // !omp_offload.info = !{!1, ...} 4057 // 4058 // Right now we only generate metadata for function that contain target 4059 // regions. 4060 4061 // If we are in simd mode or there are no entries, we don't need to do 4062 // anything. 4063 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4064 return; 4065 4066 llvm::Module &M = CGM.getModule(); 4067 llvm::LLVMContext &C = M.getContext(); 4068 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4069 SourceLocation, StringRef>, 4070 16> 4071 OrderedEntries(OffloadEntriesInfoManager.size()); 4072 llvm::SmallVector<StringRef, 16> ParentFunctions( 4073 OffloadEntriesInfoManager.size()); 4074 4075 // Auxiliary methods to create metadata values and strings. 4076 auto &&GetMDInt = [this](unsigned V) { 4077 return llvm::ConstantAsMetadata::get( 4078 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4079 }; 4080 4081 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4082 4083 // Create the offloading info metadata node. 4084 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4085 4086 // Create function that emits metadata for each target region entry; 4087 auto &&TargetRegionMetadataEmitter = 4088 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4089 &GetMDString]( 4090 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4091 unsigned Line, 4092 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4093 // Generate metadata for target regions. Each entry of this metadata 4094 // contains: 4095 // - Entry 0 -> Kind of this type of metadata (0). 4096 // - Entry 1 -> Device ID of the file where the entry was identified. 4097 // - Entry 2 -> File ID of the file where the entry was identified. 4098 // - Entry 3 -> Mangled name of the function where the entry was 4099 // identified. 4100 // - Entry 4 -> Line in the file where the entry was identified. 4101 // - Entry 5 -> Order the entry was created. 4102 // The first element of the metadata node is the kind. 4103 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4104 GetMDInt(FileID), GetMDString(ParentName), 4105 GetMDInt(Line), GetMDInt(E.getOrder())}; 4106 4107 SourceLocation Loc; 4108 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4109 E = CGM.getContext().getSourceManager().fileinfo_end(); 4110 I != E; ++I) { 4111 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4112 I->getFirst()->getUniqueID().getFile() == FileID) { 4113 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4114 I->getFirst(), Line, 1); 4115 break; 4116 } 4117 } 4118 // Save this entry in the right position of the ordered entries array. 4119 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4120 ParentFunctions[E.getOrder()] = ParentName; 4121 4122 // Add metadata to the named metadata node. 4123 MD->addOperand(llvm::MDNode::get(C, Ops)); 4124 }; 4125 4126 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4127 TargetRegionMetadataEmitter); 4128 4129 // Create function that emits metadata for each device global variable entry; 4130 auto &&DeviceGlobalVarMetadataEmitter = 4131 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4132 MD](StringRef MangledName, 4133 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4134 &E) { 4135 // Generate metadata for global variables. Each entry of this metadata 4136 // contains: 4137 // - Entry 0 -> Kind of this type of metadata (1). 4138 // - Entry 1 -> Mangled name of the variable. 4139 // - Entry 2 -> Declare target kind. 4140 // - Entry 3 -> Order the entry was created. 4141 // The first element of the metadata node is the kind. 4142 llvm::Metadata *Ops[] = { 4143 GetMDInt(E.getKind()), GetMDString(MangledName), 4144 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4145 4146 // Save this entry in the right position of the ordered entries array. 4147 OrderedEntries[E.getOrder()] = 4148 std::make_tuple(&E, SourceLocation(), MangledName); 4149 4150 // Add metadata to the named metadata node. 4151 MD->addOperand(llvm::MDNode::get(C, Ops)); 4152 }; 4153 4154 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4155 DeviceGlobalVarMetadataEmitter); 4156 4157 for (const auto &E : OrderedEntries) { 4158 assert(std::get<0>(E) && "All ordered entries must exist!"); 4159 if (const auto *CE = 4160 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4161 std::get<0>(E))) { 4162 if (!CE->getID() || !CE->getAddress()) { 4163 // Do not blame the entry if the parent funtion is not emitted. 4164 StringRef FnName = ParentFunctions[CE->getOrder()]; 4165 if (!CGM.GetGlobalValue(FnName)) 4166 continue; 4167 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4168 DiagnosticsEngine::Error, 4169 "Offloading entry for target region in %0 is incorrect: either the " 4170 "address or the ID is invalid."); 4171 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4172 continue; 4173 } 4174 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4175 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4176 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4177 OffloadEntryInfoDeviceGlobalVar>( 4178 std::get<0>(E))) { 4179 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4180 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4181 CE->getFlags()); 4182 switch (Flags) { 4183 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4184 if (CGM.getLangOpts().OpenMPIsDevice && 4185 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4186 continue; 4187 if (!CE->getAddress()) { 4188 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4189 DiagnosticsEngine::Error, "Offloading entry for declare target " 4190 "variable %0 is incorrect: the " 4191 "address is invalid."); 4192 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4193 continue; 4194 } 4195 // The vaiable has no definition - no need to add the entry. 4196 if (CE->getVarSize().isZero()) 4197 continue; 4198 break; 4199 } 4200 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4201 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4202 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4203 "Declaret target link address is set."); 4204 if (CGM.getLangOpts().OpenMPIsDevice) 4205 continue; 4206 if (!CE->getAddress()) { 4207 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4208 DiagnosticsEngine::Error, 4209 "Offloading entry for declare target variable is incorrect: the " 4210 "address is invalid."); 4211 CGM.getDiags().Report(DiagID); 4212 continue; 4213 } 4214 break; 4215 } 4216 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4217 CE->getVarSize().getQuantity(), Flags, 4218 CE->getLinkage()); 4219 } else { 4220 llvm_unreachable("Unsupported entry kind."); 4221 } 4222 } 4223 } 4224 4225 /// Loads all the offload entries information from the host IR 4226 /// metadata. 4227 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4228 // If we are in target mode, load the metadata from the host IR. This code has 4229 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4230 4231 if (!CGM.getLangOpts().OpenMPIsDevice) 4232 return; 4233 4234 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4235 return; 4236 4237 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4238 if (auto EC = Buf.getError()) { 4239 CGM.getDiags().Report(diag::err_cannot_open_file) 4240 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4241 return; 4242 } 4243 4244 llvm::LLVMContext C; 4245 auto ME = expectedToErrorOrAndEmitErrors( 4246 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4247 4248 if (auto EC = ME.getError()) { 4249 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4250 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4251 CGM.getDiags().Report(DiagID) 4252 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4253 return; 4254 } 4255 4256 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4257 if (!MD) 4258 return; 4259 4260 for (llvm::MDNode *MN : MD->operands()) { 4261 auto &&GetMDInt = [MN](unsigned Idx) { 4262 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4263 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4264 }; 4265 4266 auto &&GetMDString = [MN](unsigned Idx) { 4267 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4268 return V->getString(); 4269 }; 4270 4271 switch (GetMDInt(0)) { 4272 default: 4273 llvm_unreachable("Unexpected metadata!"); 4274 break; 4275 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4276 OffloadingEntryInfoTargetRegion: 4277 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4278 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4279 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4280 /*Order=*/GetMDInt(5)); 4281 break; 4282 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4283 OffloadingEntryInfoDeviceGlobalVar: 4284 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4285 /*MangledName=*/GetMDString(1), 4286 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4287 /*Flags=*/GetMDInt(2)), 4288 /*Order=*/GetMDInt(3)); 4289 break; 4290 } 4291 } 4292 } 4293 4294 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4295 if (!KmpRoutineEntryPtrTy) { 4296 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4297 ASTContext &C = CGM.getContext(); 4298 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4299 FunctionProtoType::ExtProtoInfo EPI; 4300 KmpRoutineEntryPtrQTy = C.getPointerType( 4301 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4302 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4303 } 4304 } 4305 4306 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4307 // Make sure the type of the entry is already created. This is the type we 4308 // have to create: 4309 // struct __tgt_offload_entry{ 4310 // void *addr; // Pointer to the offload entry info. 4311 // // (function or global) 4312 // char *name; // Name of the function or global. 4313 // size_t size; // Size of the entry info (0 if it a function). 4314 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4315 // int32_t reserved; // Reserved, to use by the runtime library. 4316 // }; 4317 if (TgtOffloadEntryQTy.isNull()) { 4318 ASTContext &C = CGM.getContext(); 4319 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4320 RD->startDefinition(); 4321 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4322 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4323 addFieldToRecordDecl(C, RD, C.getSizeType()); 4324 addFieldToRecordDecl( 4325 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4326 addFieldToRecordDecl( 4327 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4328 RD->completeDefinition(); 4329 RD->addAttr(PackedAttr::CreateImplicit(C)); 4330 TgtOffloadEntryQTy = C.getRecordType(RD); 4331 } 4332 return TgtOffloadEntryQTy; 4333 } 4334 4335 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 4336 // These are the types we need to build: 4337 // struct __tgt_device_image{ 4338 // void *ImageStart; // Pointer to the target code start. 4339 // void *ImageEnd; // Pointer to the target code end. 4340 // // We also add the host entries to the device image, as it may be useful 4341 // // for the target runtime to have access to that information. 4342 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 4343 // // the entries. 4344 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4345 // // entries (non inclusive). 4346 // }; 4347 if (TgtDeviceImageQTy.isNull()) { 4348 ASTContext &C = CGM.getContext(); 4349 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image"); 4350 RD->startDefinition(); 4351 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4352 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4353 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4354 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4355 RD->completeDefinition(); 4356 TgtDeviceImageQTy = C.getRecordType(RD); 4357 } 4358 return TgtDeviceImageQTy; 4359 } 4360 4361 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 4362 // struct __tgt_bin_desc{ 4363 // int32_t NumDevices; // Number of devices supported. 4364 // __tgt_device_image *DeviceImages; // Arrays of device images 4365 // // (one per device). 4366 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 4367 // // entries. 4368 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4369 // // entries (non inclusive). 4370 // }; 4371 if (TgtBinaryDescriptorQTy.isNull()) { 4372 ASTContext &C = CGM.getContext(); 4373 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc"); 4374 RD->startDefinition(); 4375 addFieldToRecordDecl( 4376 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4377 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 4378 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4379 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4380 RD->completeDefinition(); 4381 TgtBinaryDescriptorQTy = C.getRecordType(RD); 4382 } 4383 return TgtBinaryDescriptorQTy; 4384 } 4385 4386 namespace { 4387 struct PrivateHelpersTy { 4388 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4389 const VarDecl *PrivateElemInit) 4390 : Original(Original), PrivateCopy(PrivateCopy), 4391 PrivateElemInit(PrivateElemInit) {} 4392 const VarDecl *Original; 4393 const VarDecl *PrivateCopy; 4394 const VarDecl *PrivateElemInit; 4395 }; 4396 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4397 } // anonymous namespace 4398 4399 static RecordDecl * 4400 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4401 if (!Privates.empty()) { 4402 ASTContext &C = CGM.getContext(); 4403 // Build struct .kmp_privates_t. { 4404 // /* private vars */ 4405 // }; 4406 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4407 RD->startDefinition(); 4408 for (const auto &Pair : Privates) { 4409 const VarDecl *VD = Pair.second.Original; 4410 QualType Type = VD->getType().getNonReferenceType(); 4411 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4412 if (VD->hasAttrs()) { 4413 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4414 E(VD->getAttrs().end()); 4415 I != E; ++I) 4416 FD->addAttr(*I); 4417 } 4418 } 4419 RD->completeDefinition(); 4420 return RD; 4421 } 4422 return nullptr; 4423 } 4424 4425 static RecordDecl * 4426 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4427 QualType KmpInt32Ty, 4428 QualType KmpRoutineEntryPointerQTy) { 4429 ASTContext &C = CGM.getContext(); 4430 // Build struct kmp_task_t { 4431 // void * shareds; 4432 // kmp_routine_entry_t routine; 4433 // kmp_int32 part_id; 4434 // kmp_cmplrdata_t data1; 4435 // kmp_cmplrdata_t data2; 4436 // For taskloops additional fields: 4437 // kmp_uint64 lb; 4438 // kmp_uint64 ub; 4439 // kmp_int64 st; 4440 // kmp_int32 liter; 4441 // void * reductions; 4442 // }; 4443 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4444 UD->startDefinition(); 4445 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4446 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4447 UD->completeDefinition(); 4448 QualType KmpCmplrdataTy = C.getRecordType(UD); 4449 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4450 RD->startDefinition(); 4451 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4452 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4453 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4454 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4455 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4456 if (isOpenMPTaskLoopDirective(Kind)) { 4457 QualType KmpUInt64Ty = 4458 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4459 QualType KmpInt64Ty = 4460 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4461 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4462 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4463 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4464 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4465 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4466 } 4467 RD->completeDefinition(); 4468 return RD; 4469 } 4470 4471 static RecordDecl * 4472 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4473 ArrayRef<PrivateDataTy> Privates) { 4474 ASTContext &C = CGM.getContext(); 4475 // Build struct kmp_task_t_with_privates { 4476 // kmp_task_t task_data; 4477 // .kmp_privates_t. privates; 4478 // }; 4479 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4480 RD->startDefinition(); 4481 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4482 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4483 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4484 RD->completeDefinition(); 4485 return RD; 4486 } 4487 4488 /// Emit a proxy function which accepts kmp_task_t as the second 4489 /// argument. 4490 /// \code 4491 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4492 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4493 /// For taskloops: 4494 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4495 /// tt->reductions, tt->shareds); 4496 /// return 0; 4497 /// } 4498 /// \endcode 4499 static llvm::Function * 4500 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4501 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4502 QualType KmpTaskTWithPrivatesPtrQTy, 4503 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4504 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4505 llvm::Value *TaskPrivatesMap) { 4506 ASTContext &C = CGM.getContext(); 4507 FunctionArgList Args; 4508 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4509 ImplicitParamDecl::Other); 4510 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4511 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4512 ImplicitParamDecl::Other); 4513 Args.push_back(&GtidArg); 4514 Args.push_back(&TaskTypeArg); 4515 const auto &TaskEntryFnInfo = 4516 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4517 llvm::FunctionType *TaskEntryTy = 4518 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4519 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4520 auto *TaskEntry = llvm::Function::Create( 4521 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4522 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4523 TaskEntry->setDoesNotRecurse(); 4524 CodeGenFunction CGF(CGM); 4525 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4526 Loc, Loc); 4527 4528 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4529 // tt, 4530 // For taskloops: 4531 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4532 // tt->task_data.shareds); 4533 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4534 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4535 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4536 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4537 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4538 const auto *KmpTaskTWithPrivatesQTyRD = 4539 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4540 LValue Base = 4541 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4542 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4543 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4544 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4545 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 4546 4547 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4548 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4549 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4550 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4551 CGF.ConvertTypeForMem(SharedsPtrTy)); 4552 4553 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4554 llvm::Value *PrivatesParam; 4555 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4556 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4557 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4558 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 4559 } else { 4560 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4561 } 4562 4563 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4564 TaskPrivatesMap, 4565 CGF.Builder 4566 .CreatePointerBitCastOrAddrSpaceCast( 4567 TDBase.getAddress(CGF), CGF.VoidPtrTy) 4568 .getPointer()}; 4569 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4570 std::end(CommonArgs)); 4571 if (isOpenMPTaskLoopDirective(Kind)) { 4572 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4573 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4574 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4575 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4576 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4577 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4578 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4579 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4580 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4581 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4582 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4583 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4584 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4585 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4586 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4587 CallArgs.push_back(LBParam); 4588 CallArgs.push_back(UBParam); 4589 CallArgs.push_back(StParam); 4590 CallArgs.push_back(LIParam); 4591 CallArgs.push_back(RParam); 4592 } 4593 CallArgs.push_back(SharedsParam); 4594 4595 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4596 CallArgs); 4597 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4598 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4599 CGF.FinishFunction(); 4600 return TaskEntry; 4601 } 4602 4603 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4604 SourceLocation Loc, 4605 QualType KmpInt32Ty, 4606 QualType KmpTaskTWithPrivatesPtrQTy, 4607 QualType KmpTaskTWithPrivatesQTy) { 4608 ASTContext &C = CGM.getContext(); 4609 FunctionArgList Args; 4610 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4611 ImplicitParamDecl::Other); 4612 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4613 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4614 ImplicitParamDecl::Other); 4615 Args.push_back(&GtidArg); 4616 Args.push_back(&TaskTypeArg); 4617 const auto &DestructorFnInfo = 4618 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4619 llvm::FunctionType *DestructorFnTy = 4620 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4621 std::string Name = 4622 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4623 auto *DestructorFn = 4624 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4625 Name, &CGM.getModule()); 4626 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4627 DestructorFnInfo); 4628 DestructorFn->setDoesNotRecurse(); 4629 CodeGenFunction CGF(CGM); 4630 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4631 Args, Loc, Loc); 4632 4633 LValue Base = CGF.EmitLoadOfPointerLValue( 4634 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4635 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4636 const auto *KmpTaskTWithPrivatesQTyRD = 4637 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4638 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4639 Base = CGF.EmitLValueForField(Base, *FI); 4640 for (const auto *Field : 4641 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4642 if (QualType::DestructionKind DtorKind = 4643 Field->getType().isDestructedType()) { 4644 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4645 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 4646 } 4647 } 4648 CGF.FinishFunction(); 4649 return DestructorFn; 4650 } 4651 4652 /// Emit a privates mapping function for correct handling of private and 4653 /// firstprivate variables. 4654 /// \code 4655 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4656 /// **noalias priv1,..., <tyn> **noalias privn) { 4657 /// *priv1 = &.privates.priv1; 4658 /// ...; 4659 /// *privn = &.privates.privn; 4660 /// } 4661 /// \endcode 4662 static llvm::Value * 4663 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4664 ArrayRef<const Expr *> PrivateVars, 4665 ArrayRef<const Expr *> FirstprivateVars, 4666 ArrayRef<const Expr *> LastprivateVars, 4667 QualType PrivatesQTy, 4668 ArrayRef<PrivateDataTy> Privates) { 4669 ASTContext &C = CGM.getContext(); 4670 FunctionArgList Args; 4671 ImplicitParamDecl TaskPrivatesArg( 4672 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4673 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4674 ImplicitParamDecl::Other); 4675 Args.push_back(&TaskPrivatesArg); 4676 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4677 unsigned Counter = 1; 4678 for (const Expr *E : PrivateVars) { 4679 Args.push_back(ImplicitParamDecl::Create( 4680 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4681 C.getPointerType(C.getPointerType(E->getType())) 4682 .withConst() 4683 .withRestrict(), 4684 ImplicitParamDecl::Other)); 4685 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4686 PrivateVarsPos[VD] = Counter; 4687 ++Counter; 4688 } 4689 for (const Expr *E : FirstprivateVars) { 4690 Args.push_back(ImplicitParamDecl::Create( 4691 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4692 C.getPointerType(C.getPointerType(E->getType())) 4693 .withConst() 4694 .withRestrict(), 4695 ImplicitParamDecl::Other)); 4696 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4697 PrivateVarsPos[VD] = Counter; 4698 ++Counter; 4699 } 4700 for (const Expr *E : LastprivateVars) { 4701 Args.push_back(ImplicitParamDecl::Create( 4702 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4703 C.getPointerType(C.getPointerType(E->getType())) 4704 .withConst() 4705 .withRestrict(), 4706 ImplicitParamDecl::Other)); 4707 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4708 PrivateVarsPos[VD] = Counter; 4709 ++Counter; 4710 } 4711 const auto &TaskPrivatesMapFnInfo = 4712 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4713 llvm::FunctionType *TaskPrivatesMapTy = 4714 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4715 std::string Name = 4716 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4717 auto *TaskPrivatesMap = llvm::Function::Create( 4718 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4719 &CGM.getModule()); 4720 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4721 TaskPrivatesMapFnInfo); 4722 if (CGM.getLangOpts().Optimize) { 4723 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4724 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4725 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4726 } 4727 CodeGenFunction CGF(CGM); 4728 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4729 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4730 4731 // *privi = &.privates.privi; 4732 LValue Base = CGF.EmitLoadOfPointerLValue( 4733 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4734 TaskPrivatesArg.getType()->castAs<PointerType>()); 4735 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4736 Counter = 0; 4737 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4738 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4739 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4740 LValue RefLVal = 4741 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4742 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4743 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 4744 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 4745 ++Counter; 4746 } 4747 CGF.FinishFunction(); 4748 return TaskPrivatesMap; 4749 } 4750 4751 /// Emit initialization for private variables in task-based directives. 4752 static void emitPrivatesInit(CodeGenFunction &CGF, 4753 const OMPExecutableDirective &D, 4754 Address KmpTaskSharedsPtr, LValue TDBase, 4755 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4756 QualType SharedsTy, QualType SharedsPtrTy, 4757 const OMPTaskDataTy &Data, 4758 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4759 ASTContext &C = CGF.getContext(); 4760 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4761 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4762 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4763 ? OMPD_taskloop 4764 : OMPD_task; 4765 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4766 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4767 LValue SrcBase; 4768 bool IsTargetTask = 4769 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4770 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4771 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4772 // PointersArray and SizesArray. The original variables for these arrays are 4773 // not captured and we get their addresses explicitly. 4774 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4775 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4776 SrcBase = CGF.MakeAddrLValue( 4777 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4778 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4779 SharedsTy); 4780 } 4781 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4782 for (const PrivateDataTy &Pair : Privates) { 4783 const VarDecl *VD = Pair.second.PrivateCopy; 4784 const Expr *Init = VD->getAnyInitializer(); 4785 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4786 !CGF.isTrivialInitializer(Init)))) { 4787 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4788 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4789 const VarDecl *OriginalVD = Pair.second.Original; 4790 // Check if the variable is the target-based BasePointersArray, 4791 // PointersArray or SizesArray. 4792 LValue SharedRefLValue; 4793 QualType Type = PrivateLValue.getType(); 4794 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4795 if (IsTargetTask && !SharedField) { 4796 assert(isa<ImplicitParamDecl>(OriginalVD) && 4797 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4798 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4799 ->getNumParams() == 0 && 4800 isa<TranslationUnitDecl>( 4801 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4802 ->getDeclContext()) && 4803 "Expected artificial target data variable."); 4804 SharedRefLValue = 4805 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4806 } else { 4807 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4808 SharedRefLValue = CGF.MakeAddrLValue( 4809 Address(SharedRefLValue.getPointer(CGF), 4810 C.getDeclAlign(OriginalVD)), 4811 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4812 SharedRefLValue.getTBAAInfo()); 4813 } 4814 if (Type->isArrayType()) { 4815 // Initialize firstprivate array. 4816 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4817 // Perform simple memcpy. 4818 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4819 } else { 4820 // Initialize firstprivate array using element-by-element 4821 // initialization. 4822 CGF.EmitOMPAggregateAssign( 4823 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 4824 Type, 4825 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4826 Address SrcElement) { 4827 // Clean up any temporaries needed by the initialization. 4828 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4829 InitScope.addPrivate( 4830 Elem, [SrcElement]() -> Address { return SrcElement; }); 4831 (void)InitScope.Privatize(); 4832 // Emit initialization for single element. 4833 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4834 CGF, &CapturesInfo); 4835 CGF.EmitAnyExprToMem(Init, DestElement, 4836 Init->getType().getQualifiers(), 4837 /*IsInitializer=*/false); 4838 }); 4839 } 4840 } else { 4841 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4842 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 4843 return SharedRefLValue.getAddress(CGF); 4844 }); 4845 (void)InitScope.Privatize(); 4846 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4847 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4848 /*capturedByInit=*/false); 4849 } 4850 } else { 4851 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4852 } 4853 } 4854 ++FI; 4855 } 4856 } 4857 4858 /// Check if duplication function is required for taskloops. 4859 static bool checkInitIsRequired(CodeGenFunction &CGF, 4860 ArrayRef<PrivateDataTy> Privates) { 4861 bool InitRequired = false; 4862 for (const PrivateDataTy &Pair : Privates) { 4863 const VarDecl *VD = Pair.second.PrivateCopy; 4864 const Expr *Init = VD->getAnyInitializer(); 4865 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4866 !CGF.isTrivialInitializer(Init)); 4867 if (InitRequired) 4868 break; 4869 } 4870 return InitRequired; 4871 } 4872 4873 4874 /// Emit task_dup function (for initialization of 4875 /// private/firstprivate/lastprivate vars and last_iter flag) 4876 /// \code 4877 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4878 /// lastpriv) { 4879 /// // setup lastprivate flag 4880 /// task_dst->last = lastpriv; 4881 /// // could be constructor calls here... 4882 /// } 4883 /// \endcode 4884 static llvm::Value * 4885 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4886 const OMPExecutableDirective &D, 4887 QualType KmpTaskTWithPrivatesPtrQTy, 4888 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4889 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4890 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4891 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4892 ASTContext &C = CGM.getContext(); 4893 FunctionArgList Args; 4894 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4895 KmpTaskTWithPrivatesPtrQTy, 4896 ImplicitParamDecl::Other); 4897 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4898 KmpTaskTWithPrivatesPtrQTy, 4899 ImplicitParamDecl::Other); 4900 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4901 ImplicitParamDecl::Other); 4902 Args.push_back(&DstArg); 4903 Args.push_back(&SrcArg); 4904 Args.push_back(&LastprivArg); 4905 const auto &TaskDupFnInfo = 4906 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4907 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4908 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4909 auto *TaskDup = llvm::Function::Create( 4910 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4911 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4912 TaskDup->setDoesNotRecurse(); 4913 CodeGenFunction CGF(CGM); 4914 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4915 Loc); 4916 4917 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4918 CGF.GetAddrOfLocalVar(&DstArg), 4919 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4920 // task_dst->liter = lastpriv; 4921 if (WithLastIter) { 4922 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4923 LValue Base = CGF.EmitLValueForField( 4924 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4925 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4926 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4927 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4928 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4929 } 4930 4931 // Emit initial values for private copies (if any). 4932 assert(!Privates.empty()); 4933 Address KmpTaskSharedsPtr = Address::invalid(); 4934 if (!Data.FirstprivateVars.empty()) { 4935 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4936 CGF.GetAddrOfLocalVar(&SrcArg), 4937 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4938 LValue Base = CGF.EmitLValueForField( 4939 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4940 KmpTaskSharedsPtr = Address( 4941 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4942 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4943 KmpTaskTShareds)), 4944 Loc), 4945 CGF.getNaturalTypeAlignment(SharedsTy)); 4946 } 4947 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4948 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4949 CGF.FinishFunction(); 4950 return TaskDup; 4951 } 4952 4953 /// Checks if destructor function is required to be generated. 4954 /// \return true if cleanups are required, false otherwise. 4955 static bool 4956 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4957 bool NeedsCleanup = false; 4958 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4959 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4960 for (const FieldDecl *FD : PrivateRD->fields()) { 4961 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4962 if (NeedsCleanup) 4963 break; 4964 } 4965 return NeedsCleanup; 4966 } 4967 4968 CGOpenMPRuntime::TaskResultTy 4969 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4970 const OMPExecutableDirective &D, 4971 llvm::Function *TaskFunction, QualType SharedsTy, 4972 Address Shareds, const OMPTaskDataTy &Data) { 4973 ASTContext &C = CGM.getContext(); 4974 llvm::SmallVector<PrivateDataTy, 4> Privates; 4975 // Aggregate privates and sort them by the alignment. 4976 auto I = Data.PrivateCopies.begin(); 4977 for (const Expr *E : Data.PrivateVars) { 4978 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4979 Privates.emplace_back( 4980 C.getDeclAlign(VD), 4981 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4982 /*PrivateElemInit=*/nullptr)); 4983 ++I; 4984 } 4985 I = Data.FirstprivateCopies.begin(); 4986 auto IElemInitRef = Data.FirstprivateInits.begin(); 4987 for (const Expr *E : Data.FirstprivateVars) { 4988 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4989 Privates.emplace_back( 4990 C.getDeclAlign(VD), 4991 PrivateHelpersTy( 4992 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4993 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4994 ++I; 4995 ++IElemInitRef; 4996 } 4997 I = Data.LastprivateCopies.begin(); 4998 for (const Expr *E : Data.LastprivateVars) { 4999 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5000 Privates.emplace_back( 5001 C.getDeclAlign(VD), 5002 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5003 /*PrivateElemInit=*/nullptr)); 5004 ++I; 5005 } 5006 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 5007 return L.first > R.first; 5008 }); 5009 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 5010 // Build type kmp_routine_entry_t (if not built yet). 5011 emitKmpRoutineEntryT(KmpInt32Ty); 5012 // Build type kmp_task_t (if not built yet). 5013 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5014 if (SavedKmpTaskloopTQTy.isNull()) { 5015 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5016 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5017 } 5018 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5019 } else { 5020 assert((D.getDirectiveKind() == OMPD_task || 5021 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5022 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5023 "Expected taskloop, task or target directive"); 5024 if (SavedKmpTaskTQTy.isNull()) { 5025 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5026 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5027 } 5028 KmpTaskTQTy = SavedKmpTaskTQTy; 5029 } 5030 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5031 // Build particular struct kmp_task_t for the given task. 5032 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5033 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5034 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5035 QualType KmpTaskTWithPrivatesPtrQTy = 5036 C.getPointerType(KmpTaskTWithPrivatesQTy); 5037 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5038 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5039 KmpTaskTWithPrivatesTy->getPointerTo(); 5040 llvm::Value *KmpTaskTWithPrivatesTySize = 5041 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5042 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5043 5044 // Emit initial values for private copies (if any). 5045 llvm::Value *TaskPrivatesMap = nullptr; 5046 llvm::Type *TaskPrivatesMapTy = 5047 std::next(TaskFunction->arg_begin(), 3)->getType(); 5048 if (!Privates.empty()) { 5049 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5050 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5051 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5052 FI->getType(), Privates); 5053 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5054 TaskPrivatesMap, TaskPrivatesMapTy); 5055 } else { 5056 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5057 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5058 } 5059 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5060 // kmp_task_t *tt); 5061 llvm::Function *TaskEntry = emitProxyTaskFunction( 5062 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5063 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5064 TaskPrivatesMap); 5065 5066 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5067 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5068 // kmp_routine_entry_t *task_entry); 5069 // Task flags. Format is taken from 5070 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5071 // description of kmp_tasking_flags struct. 5072 enum { 5073 TiedFlag = 0x1, 5074 FinalFlag = 0x2, 5075 DestructorsFlag = 0x8, 5076 PriorityFlag = 0x20 5077 }; 5078 unsigned Flags = Data.Tied ? TiedFlag : 0; 5079 bool NeedsCleanup = false; 5080 if (!Privates.empty()) { 5081 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5082 if (NeedsCleanup) 5083 Flags = Flags | DestructorsFlag; 5084 } 5085 if (Data.Priority.getInt()) 5086 Flags = Flags | PriorityFlag; 5087 llvm::Value *TaskFlags = 5088 Data.Final.getPointer() 5089 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5090 CGF.Builder.getInt32(FinalFlag), 5091 CGF.Builder.getInt32(/*C=*/0)) 5092 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5093 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5094 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5095 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5096 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5097 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5098 TaskEntry, KmpRoutineEntryPtrTy)}; 5099 llvm::Value *NewTask; 5100 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5101 // Check if we have any device clause associated with the directive. 5102 const Expr *Device = nullptr; 5103 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5104 Device = C->getDevice(); 5105 // Emit device ID if any otherwise use default value. 5106 llvm::Value *DeviceID; 5107 if (Device) 5108 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5109 CGF.Int64Ty, /*isSigned=*/true); 5110 else 5111 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5112 AllocArgs.push_back(DeviceID); 5113 NewTask = CGF.EmitRuntimeCall( 5114 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5115 } else { 5116 NewTask = CGF.EmitRuntimeCall( 5117 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5118 } 5119 llvm::Value *NewTaskNewTaskTTy = 5120 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5121 NewTask, KmpTaskTWithPrivatesPtrTy); 5122 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5123 KmpTaskTWithPrivatesQTy); 5124 LValue TDBase = 5125 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5126 // Fill the data in the resulting kmp_task_t record. 5127 // Copy shareds if there are any. 5128 Address KmpTaskSharedsPtr = Address::invalid(); 5129 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5130 KmpTaskSharedsPtr = 5131 Address(CGF.EmitLoadOfScalar( 5132 CGF.EmitLValueForField( 5133 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5134 KmpTaskTShareds)), 5135 Loc), 5136 CGF.getNaturalTypeAlignment(SharedsTy)); 5137 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5138 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5139 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5140 } 5141 // Emit initial values for private copies (if any). 5142 TaskResultTy Result; 5143 if (!Privates.empty()) { 5144 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5145 SharedsTy, SharedsPtrTy, Data, Privates, 5146 /*ForDup=*/false); 5147 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5148 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5149 Result.TaskDupFn = emitTaskDupFunction( 5150 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5151 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5152 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5153 } 5154 } 5155 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5156 enum { Priority = 0, Destructors = 1 }; 5157 // Provide pointer to function with destructors for privates. 5158 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5159 const RecordDecl *KmpCmplrdataUD = 5160 (*FI)->getType()->getAsUnionType()->getDecl(); 5161 if (NeedsCleanup) { 5162 llvm::Value *DestructorFn = emitDestructorsFunction( 5163 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5164 KmpTaskTWithPrivatesQTy); 5165 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5166 LValue DestructorsLV = CGF.EmitLValueForField( 5167 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5168 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5169 DestructorFn, KmpRoutineEntryPtrTy), 5170 DestructorsLV); 5171 } 5172 // Set priority. 5173 if (Data.Priority.getInt()) { 5174 LValue Data2LV = CGF.EmitLValueForField( 5175 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5176 LValue PriorityLV = CGF.EmitLValueForField( 5177 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5178 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5179 } 5180 Result.NewTask = NewTask; 5181 Result.TaskEntry = TaskEntry; 5182 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5183 Result.TDBase = TDBase; 5184 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5185 return Result; 5186 } 5187 5188 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5189 const OMPExecutableDirective &D, 5190 llvm::Function *TaskFunction, 5191 QualType SharedsTy, Address Shareds, 5192 const Expr *IfCond, 5193 const OMPTaskDataTy &Data) { 5194 if (!CGF.HaveInsertPoint()) 5195 return; 5196 5197 TaskResultTy Result = 5198 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5199 llvm::Value *NewTask = Result.NewTask; 5200 llvm::Function *TaskEntry = Result.TaskEntry; 5201 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5202 LValue TDBase = Result.TDBase; 5203 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5204 ASTContext &C = CGM.getContext(); 5205 // Process list of dependences. 5206 Address DependenciesArray = Address::invalid(); 5207 unsigned NumDependencies = Data.Dependences.size(); 5208 if (NumDependencies) { 5209 // Dependence kind for RTL. 5210 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5211 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5212 RecordDecl *KmpDependInfoRD; 5213 QualType FlagsTy = 5214 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5215 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5216 if (KmpDependInfoTy.isNull()) { 5217 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5218 KmpDependInfoRD->startDefinition(); 5219 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5220 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5221 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5222 KmpDependInfoRD->completeDefinition(); 5223 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5224 } else { 5225 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5226 } 5227 // Define type kmp_depend_info[<Dependences.size()>]; 5228 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5229 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5230 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5231 // kmp_depend_info[<Dependences.size()>] deps; 5232 DependenciesArray = 5233 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5234 for (unsigned I = 0; I < NumDependencies; ++I) { 5235 const Expr *E = Data.Dependences[I].second; 5236 LValue Addr = CGF.EmitLValue(E); 5237 llvm::Value *Size; 5238 QualType Ty = E->getType(); 5239 if (const auto *ASE = 5240 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5241 LValue UpAddrLVal = 5242 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5243 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 5244 UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 5245 llvm::Value *LowIntPtr = 5246 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy); 5247 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5248 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5249 } else { 5250 Size = CGF.getTypeSize(Ty); 5251 } 5252 LValue Base = CGF.MakeAddrLValue( 5253 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5254 KmpDependInfoTy); 5255 // deps[i].base_addr = &<Dependences[i].second>; 5256 LValue BaseAddrLVal = CGF.EmitLValueForField( 5257 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5258 CGF.EmitStoreOfScalar( 5259 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy), 5260 BaseAddrLVal); 5261 // deps[i].len = sizeof(<Dependences[i].second>); 5262 LValue LenLVal = CGF.EmitLValueForField( 5263 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5264 CGF.EmitStoreOfScalar(Size, LenLVal); 5265 // deps[i].flags = <Dependences[i].first>; 5266 RTLDependenceKindTy DepKind; 5267 switch (Data.Dependences[I].first) { 5268 case OMPC_DEPEND_in: 5269 DepKind = DepIn; 5270 break; 5271 // Out and InOut dependencies must use the same code. 5272 case OMPC_DEPEND_out: 5273 case OMPC_DEPEND_inout: 5274 DepKind = DepInOut; 5275 break; 5276 case OMPC_DEPEND_mutexinoutset: 5277 DepKind = DepMutexInOutSet; 5278 break; 5279 case OMPC_DEPEND_source: 5280 case OMPC_DEPEND_sink: 5281 case OMPC_DEPEND_unknown: 5282 llvm_unreachable("Unknown task dependence type"); 5283 } 5284 LValue FlagsLVal = CGF.EmitLValueForField( 5285 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5286 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5287 FlagsLVal); 5288 } 5289 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5290 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5291 } 5292 5293 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5294 // libcall. 5295 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5296 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5297 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5298 // list is not empty 5299 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5300 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5301 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5302 llvm::Value *DepTaskArgs[7]; 5303 if (NumDependencies) { 5304 DepTaskArgs[0] = UpLoc; 5305 DepTaskArgs[1] = ThreadID; 5306 DepTaskArgs[2] = NewTask; 5307 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5308 DepTaskArgs[4] = DependenciesArray.getPointer(); 5309 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5310 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5311 } 5312 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5313 &TaskArgs, 5314 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5315 if (!Data.Tied) { 5316 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5317 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5318 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5319 } 5320 if (NumDependencies) { 5321 CGF.EmitRuntimeCall( 5322 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5323 } else { 5324 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5325 TaskArgs); 5326 } 5327 // Check if parent region is untied and build return for untied task; 5328 if (auto *Region = 5329 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5330 Region->emitUntiedSwitch(CGF); 5331 }; 5332 5333 llvm::Value *DepWaitTaskArgs[6]; 5334 if (NumDependencies) { 5335 DepWaitTaskArgs[0] = UpLoc; 5336 DepWaitTaskArgs[1] = ThreadID; 5337 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5338 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5339 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5340 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5341 } 5342 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5343 NumDependencies, &DepWaitTaskArgs, 5344 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5345 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5346 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5347 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5348 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5349 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5350 // is specified. 5351 if (NumDependencies) 5352 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5353 DepWaitTaskArgs); 5354 // Call proxy_task_entry(gtid, new_task); 5355 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5356 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5357 Action.Enter(CGF); 5358 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5359 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5360 OutlinedFnArgs); 5361 }; 5362 5363 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5364 // kmp_task_t *new_task); 5365 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5366 // kmp_task_t *new_task); 5367 RegionCodeGenTy RCG(CodeGen); 5368 CommonActionTy Action( 5369 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5370 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5371 RCG.setAction(Action); 5372 RCG(CGF); 5373 }; 5374 5375 if (IfCond) { 5376 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5377 } else { 5378 RegionCodeGenTy ThenRCG(ThenCodeGen); 5379 ThenRCG(CGF); 5380 } 5381 } 5382 5383 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5384 const OMPLoopDirective &D, 5385 llvm::Function *TaskFunction, 5386 QualType SharedsTy, Address Shareds, 5387 const Expr *IfCond, 5388 const OMPTaskDataTy &Data) { 5389 if (!CGF.HaveInsertPoint()) 5390 return; 5391 TaskResultTy Result = 5392 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5393 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5394 // libcall. 5395 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5396 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5397 // sched, kmp_uint64 grainsize, void *task_dup); 5398 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5399 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5400 llvm::Value *IfVal; 5401 if (IfCond) { 5402 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5403 /*isSigned=*/true); 5404 } else { 5405 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5406 } 5407 5408 LValue LBLVal = CGF.EmitLValueForField( 5409 Result.TDBase, 5410 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5411 const auto *LBVar = 5412 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5413 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5414 LBLVal.getQuals(), 5415 /*IsInitializer=*/true); 5416 LValue UBLVal = CGF.EmitLValueForField( 5417 Result.TDBase, 5418 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5419 const auto *UBVar = 5420 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5421 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5422 UBLVal.getQuals(), 5423 /*IsInitializer=*/true); 5424 LValue StLVal = CGF.EmitLValueForField( 5425 Result.TDBase, 5426 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5427 const auto *StVar = 5428 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5429 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5430 StLVal.getQuals(), 5431 /*IsInitializer=*/true); 5432 // Store reductions address. 5433 LValue RedLVal = CGF.EmitLValueForField( 5434 Result.TDBase, 5435 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5436 if (Data.Reductions) { 5437 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5438 } else { 5439 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5440 CGF.getContext().VoidPtrTy); 5441 } 5442 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5443 llvm::Value *TaskArgs[] = { 5444 UpLoc, 5445 ThreadID, 5446 Result.NewTask, 5447 IfVal, 5448 LBLVal.getPointer(CGF), 5449 UBLVal.getPointer(CGF), 5450 CGF.EmitLoadOfScalar(StLVal, Loc), 5451 llvm::ConstantInt::getSigned( 5452 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5453 llvm::ConstantInt::getSigned( 5454 CGF.IntTy, Data.Schedule.getPointer() 5455 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5456 : NoSchedule), 5457 Data.Schedule.getPointer() 5458 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5459 /*isSigned=*/false) 5460 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5461 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5462 Result.TaskDupFn, CGF.VoidPtrTy) 5463 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5464 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5465 } 5466 5467 /// Emit reduction operation for each element of array (required for 5468 /// array sections) LHS op = RHS. 5469 /// \param Type Type of array. 5470 /// \param LHSVar Variable on the left side of the reduction operation 5471 /// (references element of array in original variable). 5472 /// \param RHSVar Variable on the right side of the reduction operation 5473 /// (references element of array in original variable). 5474 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5475 /// RHSVar. 5476 static void EmitOMPAggregateReduction( 5477 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5478 const VarDecl *RHSVar, 5479 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5480 const Expr *, const Expr *)> &RedOpGen, 5481 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5482 const Expr *UpExpr = nullptr) { 5483 // Perform element-by-element initialization. 5484 QualType ElementTy; 5485 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5486 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5487 5488 // Drill down to the base element type on both arrays. 5489 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5490 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5491 5492 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5493 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5494 // Cast from pointer to array type to pointer to single element. 5495 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5496 // The basic structure here is a while-do loop. 5497 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5498 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5499 llvm::Value *IsEmpty = 5500 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5501 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5502 5503 // Enter the loop body, making that address the current address. 5504 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5505 CGF.EmitBlock(BodyBB); 5506 5507 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5508 5509 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5510 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5511 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5512 Address RHSElementCurrent = 5513 Address(RHSElementPHI, 5514 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5515 5516 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5517 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5518 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5519 Address LHSElementCurrent = 5520 Address(LHSElementPHI, 5521 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5522 5523 // Emit copy. 5524 CodeGenFunction::OMPPrivateScope Scope(CGF); 5525 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5526 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5527 Scope.Privatize(); 5528 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5529 Scope.ForceCleanup(); 5530 5531 // Shift the address forward by one element. 5532 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5533 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5534 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5535 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5536 // Check whether we've reached the end. 5537 llvm::Value *Done = 5538 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5539 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5540 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5541 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5542 5543 // Done. 5544 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5545 } 5546 5547 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5548 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5549 /// UDR combiner function. 5550 static void emitReductionCombiner(CodeGenFunction &CGF, 5551 const Expr *ReductionOp) { 5552 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5553 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5554 if (const auto *DRE = 5555 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5556 if (const auto *DRD = 5557 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5558 std::pair<llvm::Function *, llvm::Function *> Reduction = 5559 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5560 RValue Func = RValue::get(Reduction.first); 5561 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5562 CGF.EmitIgnoredExpr(ReductionOp); 5563 return; 5564 } 5565 CGF.EmitIgnoredExpr(ReductionOp); 5566 } 5567 5568 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5569 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5570 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5571 ArrayRef<const Expr *> ReductionOps) { 5572 ASTContext &C = CGM.getContext(); 5573 5574 // void reduction_func(void *LHSArg, void *RHSArg); 5575 FunctionArgList Args; 5576 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5577 ImplicitParamDecl::Other); 5578 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5579 ImplicitParamDecl::Other); 5580 Args.push_back(&LHSArg); 5581 Args.push_back(&RHSArg); 5582 const auto &CGFI = 5583 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5584 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5585 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5586 llvm::GlobalValue::InternalLinkage, Name, 5587 &CGM.getModule()); 5588 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5589 Fn->setDoesNotRecurse(); 5590 CodeGenFunction CGF(CGM); 5591 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5592 5593 // Dst = (void*[n])(LHSArg); 5594 // Src = (void*[n])(RHSArg); 5595 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5596 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5597 ArgsType), CGF.getPointerAlign()); 5598 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5599 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5600 ArgsType), CGF.getPointerAlign()); 5601 5602 // ... 5603 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5604 // ... 5605 CodeGenFunction::OMPPrivateScope Scope(CGF); 5606 auto IPriv = Privates.begin(); 5607 unsigned Idx = 0; 5608 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5609 const auto *RHSVar = 5610 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5611 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5612 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5613 }); 5614 const auto *LHSVar = 5615 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5616 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5617 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5618 }); 5619 QualType PrivTy = (*IPriv)->getType(); 5620 if (PrivTy->isVariablyModifiedType()) { 5621 // Get array size and emit VLA type. 5622 ++Idx; 5623 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5624 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5625 const VariableArrayType *VLA = 5626 CGF.getContext().getAsVariableArrayType(PrivTy); 5627 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5628 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5629 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5630 CGF.EmitVariablyModifiedType(PrivTy); 5631 } 5632 } 5633 Scope.Privatize(); 5634 IPriv = Privates.begin(); 5635 auto ILHS = LHSExprs.begin(); 5636 auto IRHS = RHSExprs.begin(); 5637 for (const Expr *E : ReductionOps) { 5638 if ((*IPriv)->getType()->isArrayType()) { 5639 // Emit reduction for array section. 5640 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5641 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5642 EmitOMPAggregateReduction( 5643 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5644 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5645 emitReductionCombiner(CGF, E); 5646 }); 5647 } else { 5648 // Emit reduction for array subscript or single variable. 5649 emitReductionCombiner(CGF, E); 5650 } 5651 ++IPriv; 5652 ++ILHS; 5653 ++IRHS; 5654 } 5655 Scope.ForceCleanup(); 5656 CGF.FinishFunction(); 5657 return Fn; 5658 } 5659 5660 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5661 const Expr *ReductionOp, 5662 const Expr *PrivateRef, 5663 const DeclRefExpr *LHS, 5664 const DeclRefExpr *RHS) { 5665 if (PrivateRef->getType()->isArrayType()) { 5666 // Emit reduction for array section. 5667 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5668 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5669 EmitOMPAggregateReduction( 5670 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5671 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5672 emitReductionCombiner(CGF, ReductionOp); 5673 }); 5674 } else { 5675 // Emit reduction for array subscript or single variable. 5676 emitReductionCombiner(CGF, ReductionOp); 5677 } 5678 } 5679 5680 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5681 ArrayRef<const Expr *> Privates, 5682 ArrayRef<const Expr *> LHSExprs, 5683 ArrayRef<const Expr *> RHSExprs, 5684 ArrayRef<const Expr *> ReductionOps, 5685 ReductionOptionsTy Options) { 5686 if (!CGF.HaveInsertPoint()) 5687 return; 5688 5689 bool WithNowait = Options.WithNowait; 5690 bool SimpleReduction = Options.SimpleReduction; 5691 5692 // Next code should be emitted for reduction: 5693 // 5694 // static kmp_critical_name lock = { 0 }; 5695 // 5696 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5697 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5698 // ... 5699 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5700 // *(Type<n>-1*)rhs[<n>-1]); 5701 // } 5702 // 5703 // ... 5704 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5705 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5706 // RedList, reduce_func, &<lock>)) { 5707 // case 1: 5708 // ... 5709 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5710 // ... 5711 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5712 // break; 5713 // case 2: 5714 // ... 5715 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5716 // ... 5717 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5718 // break; 5719 // default:; 5720 // } 5721 // 5722 // if SimpleReduction is true, only the next code is generated: 5723 // ... 5724 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5725 // ... 5726 5727 ASTContext &C = CGM.getContext(); 5728 5729 if (SimpleReduction) { 5730 CodeGenFunction::RunCleanupsScope Scope(CGF); 5731 auto IPriv = Privates.begin(); 5732 auto ILHS = LHSExprs.begin(); 5733 auto IRHS = RHSExprs.begin(); 5734 for (const Expr *E : ReductionOps) { 5735 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5736 cast<DeclRefExpr>(*IRHS)); 5737 ++IPriv; 5738 ++ILHS; 5739 ++IRHS; 5740 } 5741 return; 5742 } 5743 5744 // 1. Build a list of reduction variables. 5745 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5746 auto Size = RHSExprs.size(); 5747 for (const Expr *E : Privates) { 5748 if (E->getType()->isVariablyModifiedType()) 5749 // Reserve place for array size. 5750 ++Size; 5751 } 5752 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5753 QualType ReductionArrayTy = 5754 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5755 /*IndexTypeQuals=*/0); 5756 Address ReductionList = 5757 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5758 auto IPriv = Privates.begin(); 5759 unsigned Idx = 0; 5760 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5761 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5762 CGF.Builder.CreateStore( 5763 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5764 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5765 Elem); 5766 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5767 // Store array size. 5768 ++Idx; 5769 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5770 llvm::Value *Size = CGF.Builder.CreateIntCast( 5771 CGF.getVLASize( 5772 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5773 .NumElts, 5774 CGF.SizeTy, /*isSigned=*/false); 5775 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5776 Elem); 5777 } 5778 } 5779 5780 // 2. Emit reduce_func(). 5781 llvm::Function *ReductionFn = emitReductionFunction( 5782 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5783 LHSExprs, RHSExprs, ReductionOps); 5784 5785 // 3. Create static kmp_critical_name lock = { 0 }; 5786 std::string Name = getName({"reduction"}); 5787 llvm::Value *Lock = getCriticalRegionLock(Name); 5788 5789 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5790 // RedList, reduce_func, &<lock>); 5791 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5792 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5793 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5794 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5795 ReductionList.getPointer(), CGF.VoidPtrTy); 5796 llvm::Value *Args[] = { 5797 IdentTLoc, // ident_t *<loc> 5798 ThreadId, // i32 <gtid> 5799 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5800 ReductionArrayTySize, // size_type sizeof(RedList) 5801 RL, // void *RedList 5802 ReductionFn, // void (*) (void *, void *) <reduce_func> 5803 Lock // kmp_critical_name *&<lock> 5804 }; 5805 llvm::Value *Res = CGF.EmitRuntimeCall( 5806 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5807 : OMPRTL__kmpc_reduce), 5808 Args); 5809 5810 // 5. Build switch(res) 5811 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5812 llvm::SwitchInst *SwInst = 5813 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5814 5815 // 6. Build case 1: 5816 // ... 5817 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5818 // ... 5819 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5820 // break; 5821 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5822 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5823 CGF.EmitBlock(Case1BB); 5824 5825 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5826 llvm::Value *EndArgs[] = { 5827 IdentTLoc, // ident_t *<loc> 5828 ThreadId, // i32 <gtid> 5829 Lock // kmp_critical_name *&<lock> 5830 }; 5831 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5832 CodeGenFunction &CGF, PrePostActionTy &Action) { 5833 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5834 auto IPriv = Privates.begin(); 5835 auto ILHS = LHSExprs.begin(); 5836 auto IRHS = RHSExprs.begin(); 5837 for (const Expr *E : ReductionOps) { 5838 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5839 cast<DeclRefExpr>(*IRHS)); 5840 ++IPriv; 5841 ++ILHS; 5842 ++IRHS; 5843 } 5844 }; 5845 RegionCodeGenTy RCG(CodeGen); 5846 CommonActionTy Action( 5847 nullptr, llvm::None, 5848 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5849 : OMPRTL__kmpc_end_reduce), 5850 EndArgs); 5851 RCG.setAction(Action); 5852 RCG(CGF); 5853 5854 CGF.EmitBranch(DefaultBB); 5855 5856 // 7. Build case 2: 5857 // ... 5858 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5859 // ... 5860 // break; 5861 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5862 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5863 CGF.EmitBlock(Case2BB); 5864 5865 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5866 CodeGenFunction &CGF, PrePostActionTy &Action) { 5867 auto ILHS = LHSExprs.begin(); 5868 auto IRHS = RHSExprs.begin(); 5869 auto IPriv = Privates.begin(); 5870 for (const Expr *E : ReductionOps) { 5871 const Expr *XExpr = nullptr; 5872 const Expr *EExpr = nullptr; 5873 const Expr *UpExpr = nullptr; 5874 BinaryOperatorKind BO = BO_Comma; 5875 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5876 if (BO->getOpcode() == BO_Assign) { 5877 XExpr = BO->getLHS(); 5878 UpExpr = BO->getRHS(); 5879 } 5880 } 5881 // Try to emit update expression as a simple atomic. 5882 const Expr *RHSExpr = UpExpr; 5883 if (RHSExpr) { 5884 // Analyze RHS part of the whole expression. 5885 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5886 RHSExpr->IgnoreParenImpCasts())) { 5887 // If this is a conditional operator, analyze its condition for 5888 // min/max reduction operator. 5889 RHSExpr = ACO->getCond(); 5890 } 5891 if (const auto *BORHS = 5892 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5893 EExpr = BORHS->getRHS(); 5894 BO = BORHS->getOpcode(); 5895 } 5896 } 5897 if (XExpr) { 5898 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5899 auto &&AtomicRedGen = [BO, VD, 5900 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5901 const Expr *EExpr, const Expr *UpExpr) { 5902 LValue X = CGF.EmitLValue(XExpr); 5903 RValue E; 5904 if (EExpr) 5905 E = CGF.EmitAnyExpr(EExpr); 5906 CGF.EmitOMPAtomicSimpleUpdateExpr( 5907 X, E, BO, /*IsXLHSInRHSPart=*/true, 5908 llvm::AtomicOrdering::Monotonic, Loc, 5909 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5910 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5911 PrivateScope.addPrivate( 5912 VD, [&CGF, VD, XRValue, Loc]() { 5913 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5914 CGF.emitOMPSimpleStore( 5915 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5916 VD->getType().getNonReferenceType(), Loc); 5917 return LHSTemp; 5918 }); 5919 (void)PrivateScope.Privatize(); 5920 return CGF.EmitAnyExpr(UpExpr); 5921 }); 5922 }; 5923 if ((*IPriv)->getType()->isArrayType()) { 5924 // Emit atomic reduction for array section. 5925 const auto *RHSVar = 5926 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5927 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5928 AtomicRedGen, XExpr, EExpr, UpExpr); 5929 } else { 5930 // Emit atomic reduction for array subscript or single variable. 5931 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5932 } 5933 } else { 5934 // Emit as a critical region. 5935 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5936 const Expr *, const Expr *) { 5937 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5938 std::string Name = RT.getName({"atomic_reduction"}); 5939 RT.emitCriticalRegion( 5940 CGF, Name, 5941 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5942 Action.Enter(CGF); 5943 emitReductionCombiner(CGF, E); 5944 }, 5945 Loc); 5946 }; 5947 if ((*IPriv)->getType()->isArrayType()) { 5948 const auto *LHSVar = 5949 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5950 const auto *RHSVar = 5951 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5952 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5953 CritRedGen); 5954 } else { 5955 CritRedGen(CGF, nullptr, nullptr, nullptr); 5956 } 5957 } 5958 ++ILHS; 5959 ++IRHS; 5960 ++IPriv; 5961 } 5962 }; 5963 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5964 if (!WithNowait) { 5965 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5966 llvm::Value *EndArgs[] = { 5967 IdentTLoc, // ident_t *<loc> 5968 ThreadId, // i32 <gtid> 5969 Lock // kmp_critical_name *&<lock> 5970 }; 5971 CommonActionTy Action(nullptr, llvm::None, 5972 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 5973 EndArgs); 5974 AtomicRCG.setAction(Action); 5975 AtomicRCG(CGF); 5976 } else { 5977 AtomicRCG(CGF); 5978 } 5979 5980 CGF.EmitBranch(DefaultBB); 5981 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5982 } 5983 5984 /// Generates unique name for artificial threadprivate variables. 5985 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5986 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5987 const Expr *Ref) { 5988 SmallString<256> Buffer; 5989 llvm::raw_svector_ostream Out(Buffer); 5990 const clang::DeclRefExpr *DE; 5991 const VarDecl *D = ::getBaseDecl(Ref, DE); 5992 if (!D) 5993 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5994 D = D->getCanonicalDecl(); 5995 std::string Name = CGM.getOpenMPRuntime().getName( 5996 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5997 Out << Prefix << Name << "_" 5998 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5999 return Out.str(); 6000 } 6001 6002 /// Emits reduction initializer function: 6003 /// \code 6004 /// void @.red_init(void* %arg) { 6005 /// %0 = bitcast void* %arg to <type>* 6006 /// store <type> <init>, <type>* %0 6007 /// ret void 6008 /// } 6009 /// \endcode 6010 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6011 SourceLocation Loc, 6012 ReductionCodeGen &RCG, unsigned N) { 6013 ASTContext &C = CGM.getContext(); 6014 FunctionArgList Args; 6015 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6016 ImplicitParamDecl::Other); 6017 Args.emplace_back(&Param); 6018 const auto &FnInfo = 6019 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6020 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6021 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6022 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6023 Name, &CGM.getModule()); 6024 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6025 Fn->setDoesNotRecurse(); 6026 CodeGenFunction CGF(CGM); 6027 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6028 Address PrivateAddr = CGF.EmitLoadOfPointer( 6029 CGF.GetAddrOfLocalVar(&Param), 6030 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6031 llvm::Value *Size = nullptr; 6032 // If the size of the reduction item is non-constant, load it from global 6033 // threadprivate variable. 6034 if (RCG.getSizes(N).second) { 6035 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6036 CGF, CGM.getContext().getSizeType(), 6037 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6038 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6039 CGM.getContext().getSizeType(), Loc); 6040 } 6041 RCG.emitAggregateType(CGF, N, Size); 6042 LValue SharedLVal; 6043 // If initializer uses initializer from declare reduction construct, emit a 6044 // pointer to the address of the original reduction item (reuired by reduction 6045 // initializer) 6046 if (RCG.usesReductionInitializer(N)) { 6047 Address SharedAddr = 6048 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6049 CGF, CGM.getContext().VoidPtrTy, 6050 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6051 SharedAddr = CGF.EmitLoadOfPointer( 6052 SharedAddr, 6053 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6054 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6055 } else { 6056 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6057 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6058 CGM.getContext().VoidPtrTy); 6059 } 6060 // Emit the initializer: 6061 // %0 = bitcast void* %arg to <type>* 6062 // store <type> <init>, <type>* %0 6063 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6064 [](CodeGenFunction &) { return false; }); 6065 CGF.FinishFunction(); 6066 return Fn; 6067 } 6068 6069 /// Emits reduction combiner function: 6070 /// \code 6071 /// void @.red_comb(void* %arg0, void* %arg1) { 6072 /// %lhs = bitcast void* %arg0 to <type>* 6073 /// %rhs = bitcast void* %arg1 to <type>* 6074 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6075 /// store <type> %2, <type>* %lhs 6076 /// ret void 6077 /// } 6078 /// \endcode 6079 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6080 SourceLocation Loc, 6081 ReductionCodeGen &RCG, unsigned N, 6082 const Expr *ReductionOp, 6083 const Expr *LHS, const Expr *RHS, 6084 const Expr *PrivateRef) { 6085 ASTContext &C = CGM.getContext(); 6086 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6087 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6088 FunctionArgList Args; 6089 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6090 C.VoidPtrTy, ImplicitParamDecl::Other); 6091 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6092 ImplicitParamDecl::Other); 6093 Args.emplace_back(&ParamInOut); 6094 Args.emplace_back(&ParamIn); 6095 const auto &FnInfo = 6096 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6097 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6098 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6099 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6100 Name, &CGM.getModule()); 6101 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6102 Fn->setDoesNotRecurse(); 6103 CodeGenFunction CGF(CGM); 6104 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6105 llvm::Value *Size = nullptr; 6106 // If the size of the reduction item is non-constant, load it from global 6107 // threadprivate variable. 6108 if (RCG.getSizes(N).second) { 6109 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6110 CGF, CGM.getContext().getSizeType(), 6111 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6112 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6113 CGM.getContext().getSizeType(), Loc); 6114 } 6115 RCG.emitAggregateType(CGF, N, Size); 6116 // Remap lhs and rhs variables to the addresses of the function arguments. 6117 // %lhs = bitcast void* %arg0 to <type>* 6118 // %rhs = bitcast void* %arg1 to <type>* 6119 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6120 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6121 // Pull out the pointer to the variable. 6122 Address PtrAddr = CGF.EmitLoadOfPointer( 6123 CGF.GetAddrOfLocalVar(&ParamInOut), 6124 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6125 return CGF.Builder.CreateElementBitCast( 6126 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6127 }); 6128 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6129 // Pull out the pointer to the variable. 6130 Address PtrAddr = CGF.EmitLoadOfPointer( 6131 CGF.GetAddrOfLocalVar(&ParamIn), 6132 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6133 return CGF.Builder.CreateElementBitCast( 6134 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6135 }); 6136 PrivateScope.Privatize(); 6137 // Emit the combiner body: 6138 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6139 // store <type> %2, <type>* %lhs 6140 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6141 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6142 cast<DeclRefExpr>(RHS)); 6143 CGF.FinishFunction(); 6144 return Fn; 6145 } 6146 6147 /// Emits reduction finalizer function: 6148 /// \code 6149 /// void @.red_fini(void* %arg) { 6150 /// %0 = bitcast void* %arg to <type>* 6151 /// <destroy>(<type>* %0) 6152 /// ret void 6153 /// } 6154 /// \endcode 6155 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6156 SourceLocation Loc, 6157 ReductionCodeGen &RCG, unsigned N) { 6158 if (!RCG.needCleanups(N)) 6159 return nullptr; 6160 ASTContext &C = CGM.getContext(); 6161 FunctionArgList Args; 6162 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6163 ImplicitParamDecl::Other); 6164 Args.emplace_back(&Param); 6165 const auto &FnInfo = 6166 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6167 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6168 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6169 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6170 Name, &CGM.getModule()); 6171 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6172 Fn->setDoesNotRecurse(); 6173 CodeGenFunction CGF(CGM); 6174 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6175 Address PrivateAddr = CGF.EmitLoadOfPointer( 6176 CGF.GetAddrOfLocalVar(&Param), 6177 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6178 llvm::Value *Size = nullptr; 6179 // If the size of the reduction item is non-constant, load it from global 6180 // threadprivate variable. 6181 if (RCG.getSizes(N).second) { 6182 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6183 CGF, CGM.getContext().getSizeType(), 6184 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6185 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6186 CGM.getContext().getSizeType(), Loc); 6187 } 6188 RCG.emitAggregateType(CGF, N, Size); 6189 // Emit the finalizer body: 6190 // <destroy>(<type>* %0) 6191 RCG.emitCleanups(CGF, N, PrivateAddr); 6192 CGF.FinishFunction(); 6193 return Fn; 6194 } 6195 6196 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6197 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6198 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6199 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6200 return nullptr; 6201 6202 // Build typedef struct: 6203 // kmp_task_red_input { 6204 // void *reduce_shar; // shared reduction item 6205 // size_t reduce_size; // size of data item 6206 // void *reduce_init; // data initialization routine 6207 // void *reduce_fini; // data finalization routine 6208 // void *reduce_comb; // data combiner routine 6209 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6210 // } kmp_task_red_input_t; 6211 ASTContext &C = CGM.getContext(); 6212 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6213 RD->startDefinition(); 6214 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6215 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6216 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6217 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6218 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6219 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6220 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6221 RD->completeDefinition(); 6222 QualType RDType = C.getRecordType(RD); 6223 unsigned Size = Data.ReductionVars.size(); 6224 llvm::APInt ArraySize(/*numBits=*/64, Size); 6225 QualType ArrayRDType = C.getConstantArrayType( 6226 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6227 // kmp_task_red_input_t .rd_input.[Size]; 6228 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6229 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6230 Data.ReductionOps); 6231 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6232 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6233 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6234 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6235 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6236 TaskRedInput.getPointer(), Idxs, 6237 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6238 ".rd_input.gep."); 6239 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6240 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6241 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6242 RCG.emitSharedLValue(CGF, Cnt); 6243 llvm::Value *CastedShared = 6244 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6245 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6246 RCG.emitAggregateType(CGF, Cnt); 6247 llvm::Value *SizeValInChars; 6248 llvm::Value *SizeVal; 6249 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6250 // We use delayed creation/initialization for VLAs, array sections and 6251 // custom reduction initializations. It is required because runtime does not 6252 // provide the way to pass the sizes of VLAs/array sections to 6253 // initializer/combiner/finalizer functions and does not pass the pointer to 6254 // original reduction item to the initializer. Instead threadprivate global 6255 // variables are used to store these values and use them in the functions. 6256 bool DelayedCreation = !!SizeVal; 6257 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6258 /*isSigned=*/false); 6259 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6260 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6261 // ElemLVal.reduce_init = init; 6262 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6263 llvm::Value *InitAddr = 6264 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6265 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6266 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6267 // ElemLVal.reduce_fini = fini; 6268 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6269 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6270 llvm::Value *FiniAddr = Fini 6271 ? CGF.EmitCastToVoidPtr(Fini) 6272 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6273 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6274 // ElemLVal.reduce_comb = comb; 6275 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6276 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6277 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6278 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6279 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6280 // ElemLVal.flags = 0; 6281 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6282 if (DelayedCreation) { 6283 CGF.EmitStoreOfScalar( 6284 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6285 FlagsLVal); 6286 } else 6287 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6288 FlagsLVal.getType()); 6289 } 6290 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6291 // *data); 6292 llvm::Value *Args[] = { 6293 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6294 /*isSigned=*/true), 6295 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6296 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6297 CGM.VoidPtrTy)}; 6298 return CGF.EmitRuntimeCall( 6299 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6300 } 6301 6302 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6303 SourceLocation Loc, 6304 ReductionCodeGen &RCG, 6305 unsigned N) { 6306 auto Sizes = RCG.getSizes(N); 6307 // Emit threadprivate global variable if the type is non-constant 6308 // (Sizes.second = nullptr). 6309 if (Sizes.second) { 6310 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6311 /*isSigned=*/false); 6312 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6313 CGF, CGM.getContext().getSizeType(), 6314 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6315 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6316 } 6317 // Store address of the original reduction item if custom initializer is used. 6318 if (RCG.usesReductionInitializer(N)) { 6319 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6320 CGF, CGM.getContext().VoidPtrTy, 6321 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6322 CGF.Builder.CreateStore( 6323 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6324 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy), 6325 SharedAddr, /*IsVolatile=*/false); 6326 } 6327 } 6328 6329 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6330 SourceLocation Loc, 6331 llvm::Value *ReductionsPtr, 6332 LValue SharedLVal) { 6333 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6334 // *d); 6335 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6336 CGM.IntTy, 6337 /*isSigned=*/true), 6338 ReductionsPtr, 6339 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6340 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6341 return Address( 6342 CGF.EmitRuntimeCall( 6343 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6344 SharedLVal.getAlignment()); 6345 } 6346 6347 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6348 SourceLocation Loc) { 6349 if (!CGF.HaveInsertPoint()) 6350 return; 6351 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6352 // global_tid); 6353 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6354 // Ignore return result until untied tasks are supported. 6355 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6356 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6357 Region->emitUntiedSwitch(CGF); 6358 } 6359 6360 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6361 OpenMPDirectiveKind InnerKind, 6362 const RegionCodeGenTy &CodeGen, 6363 bool HasCancel) { 6364 if (!CGF.HaveInsertPoint()) 6365 return; 6366 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6367 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6368 } 6369 6370 namespace { 6371 enum RTCancelKind { 6372 CancelNoreq = 0, 6373 CancelParallel = 1, 6374 CancelLoop = 2, 6375 CancelSections = 3, 6376 CancelTaskgroup = 4 6377 }; 6378 } // anonymous namespace 6379 6380 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6381 RTCancelKind CancelKind = CancelNoreq; 6382 if (CancelRegion == OMPD_parallel) 6383 CancelKind = CancelParallel; 6384 else if (CancelRegion == OMPD_for) 6385 CancelKind = CancelLoop; 6386 else if (CancelRegion == OMPD_sections) 6387 CancelKind = CancelSections; 6388 else { 6389 assert(CancelRegion == OMPD_taskgroup); 6390 CancelKind = CancelTaskgroup; 6391 } 6392 return CancelKind; 6393 } 6394 6395 void CGOpenMPRuntime::emitCancellationPointCall( 6396 CodeGenFunction &CGF, SourceLocation Loc, 6397 OpenMPDirectiveKind CancelRegion) { 6398 if (!CGF.HaveInsertPoint()) 6399 return; 6400 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6401 // global_tid, kmp_int32 cncl_kind); 6402 if (auto *OMPRegionInfo = 6403 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6404 // For 'cancellation point taskgroup', the task region info may not have a 6405 // cancel. This may instead happen in another adjacent task. 6406 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6407 llvm::Value *Args[] = { 6408 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6409 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6410 // Ignore return result until untied tasks are supported. 6411 llvm::Value *Result = CGF.EmitRuntimeCall( 6412 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6413 // if (__kmpc_cancellationpoint()) { 6414 // exit from construct; 6415 // } 6416 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6417 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6418 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6419 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6420 CGF.EmitBlock(ExitBB); 6421 // exit from construct; 6422 CodeGenFunction::JumpDest CancelDest = 6423 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6424 CGF.EmitBranchThroughCleanup(CancelDest); 6425 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6426 } 6427 } 6428 } 6429 6430 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6431 const Expr *IfCond, 6432 OpenMPDirectiveKind CancelRegion) { 6433 if (!CGF.HaveInsertPoint()) 6434 return; 6435 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6436 // kmp_int32 cncl_kind); 6437 if (auto *OMPRegionInfo = 6438 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6439 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6440 PrePostActionTy &) { 6441 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6442 llvm::Value *Args[] = { 6443 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6444 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6445 // Ignore return result until untied tasks are supported. 6446 llvm::Value *Result = CGF.EmitRuntimeCall( 6447 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6448 // if (__kmpc_cancel()) { 6449 // exit from construct; 6450 // } 6451 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6452 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6453 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6454 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6455 CGF.EmitBlock(ExitBB); 6456 // exit from construct; 6457 CodeGenFunction::JumpDest CancelDest = 6458 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6459 CGF.EmitBranchThroughCleanup(CancelDest); 6460 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6461 }; 6462 if (IfCond) { 6463 emitIfClause(CGF, IfCond, ThenGen, 6464 [](CodeGenFunction &, PrePostActionTy &) {}); 6465 } else { 6466 RegionCodeGenTy ThenRCG(ThenGen); 6467 ThenRCG(CGF); 6468 } 6469 } 6470 } 6471 6472 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6473 const OMPExecutableDirective &D, StringRef ParentName, 6474 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6475 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6476 assert(!ParentName.empty() && "Invalid target region parent name!"); 6477 HasEmittedTargetRegion = true; 6478 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6479 IsOffloadEntry, CodeGen); 6480 } 6481 6482 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6483 const OMPExecutableDirective &D, StringRef ParentName, 6484 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6485 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6486 // Create a unique name for the entry function using the source location 6487 // information of the current target region. The name will be something like: 6488 // 6489 // __omp_offloading_DD_FFFF_PP_lBB 6490 // 6491 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6492 // mangled name of the function that encloses the target region and BB is the 6493 // line number of the target region. 6494 6495 unsigned DeviceID; 6496 unsigned FileID; 6497 unsigned Line; 6498 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6499 Line); 6500 SmallString<64> EntryFnName; 6501 { 6502 llvm::raw_svector_ostream OS(EntryFnName); 6503 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6504 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6505 } 6506 6507 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6508 6509 CodeGenFunction CGF(CGM, true); 6510 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6511 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6512 6513 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 6514 6515 // If this target outline function is not an offload entry, we don't need to 6516 // register it. 6517 if (!IsOffloadEntry) 6518 return; 6519 6520 // The target region ID is used by the runtime library to identify the current 6521 // target region, so it only has to be unique and not necessarily point to 6522 // anything. It could be the pointer to the outlined function that implements 6523 // the target region, but we aren't using that so that the compiler doesn't 6524 // need to keep that, and could therefore inline the host function if proven 6525 // worthwhile during optimization. In the other hand, if emitting code for the 6526 // device, the ID has to be the function address so that it can retrieved from 6527 // the offloading entry and launched by the runtime library. We also mark the 6528 // outlined function to have external linkage in case we are emitting code for 6529 // the device, because these functions will be entry points to the device. 6530 6531 if (CGM.getLangOpts().OpenMPIsDevice) { 6532 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6533 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6534 OutlinedFn->setDSOLocal(false); 6535 } else { 6536 std::string Name = getName({EntryFnName, "region_id"}); 6537 OutlinedFnID = new llvm::GlobalVariable( 6538 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6539 llvm::GlobalValue::WeakAnyLinkage, 6540 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6541 } 6542 6543 // Register the information for the entry associated with this target region. 6544 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6545 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6546 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6547 } 6548 6549 /// Checks if the expression is constant or does not have non-trivial function 6550 /// calls. 6551 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6552 // We can skip constant expressions. 6553 // We can skip expressions with trivial calls or simple expressions. 6554 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6555 !E->hasNonTrivialCall(Ctx)) && 6556 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6557 } 6558 6559 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6560 const Stmt *Body) { 6561 const Stmt *Child = Body->IgnoreContainers(); 6562 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6563 Child = nullptr; 6564 for (const Stmt *S : C->body()) { 6565 if (const auto *E = dyn_cast<Expr>(S)) { 6566 if (isTrivial(Ctx, E)) 6567 continue; 6568 } 6569 // Some of the statements can be ignored. 6570 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6571 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6572 continue; 6573 // Analyze declarations. 6574 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6575 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6576 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6577 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6578 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6579 isa<UsingDirectiveDecl>(D) || 6580 isa<OMPDeclareReductionDecl>(D) || 6581 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6582 return true; 6583 const auto *VD = dyn_cast<VarDecl>(D); 6584 if (!VD) 6585 return false; 6586 return VD->isConstexpr() || 6587 ((VD->getType().isTrivialType(Ctx) || 6588 VD->getType()->isReferenceType()) && 6589 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6590 })) 6591 continue; 6592 } 6593 // Found multiple children - cannot get the one child only. 6594 if (Child) 6595 return nullptr; 6596 Child = S; 6597 } 6598 if (Child) 6599 Child = Child->IgnoreContainers(); 6600 } 6601 return Child; 6602 } 6603 6604 /// Emit the number of teams for a target directive. Inspect the num_teams 6605 /// clause associated with a teams construct combined or closely nested 6606 /// with the target directive. 6607 /// 6608 /// Emit a team of size one for directives such as 'target parallel' that 6609 /// have no associated teams construct. 6610 /// 6611 /// Otherwise, return nullptr. 6612 static llvm::Value * 6613 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6614 const OMPExecutableDirective &D) { 6615 assert(!CGF.getLangOpts().OpenMPIsDevice && 6616 "Clauses associated with the teams directive expected to be emitted " 6617 "only for the host!"); 6618 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6619 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6620 "Expected target-based executable directive."); 6621 CGBuilderTy &Bld = CGF.Builder; 6622 switch (DirectiveKind) { 6623 case OMPD_target: { 6624 const auto *CS = D.getInnermostCapturedStmt(); 6625 const auto *Body = 6626 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6627 const Stmt *ChildStmt = 6628 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6629 if (const auto *NestedDir = 6630 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6631 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6632 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6633 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6634 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6635 const Expr *NumTeams = 6636 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6637 llvm::Value *NumTeamsVal = 6638 CGF.EmitScalarExpr(NumTeams, 6639 /*IgnoreResultAssign*/ true); 6640 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6641 /*isSigned=*/true); 6642 } 6643 return Bld.getInt32(0); 6644 } 6645 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6646 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6647 return Bld.getInt32(1); 6648 return Bld.getInt32(0); 6649 } 6650 return nullptr; 6651 } 6652 case OMPD_target_teams: 6653 case OMPD_target_teams_distribute: 6654 case OMPD_target_teams_distribute_simd: 6655 case OMPD_target_teams_distribute_parallel_for: 6656 case OMPD_target_teams_distribute_parallel_for_simd: { 6657 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6658 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6659 const Expr *NumTeams = 6660 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6661 llvm::Value *NumTeamsVal = 6662 CGF.EmitScalarExpr(NumTeams, 6663 /*IgnoreResultAssign*/ true); 6664 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6665 /*isSigned=*/true); 6666 } 6667 return Bld.getInt32(0); 6668 } 6669 case OMPD_target_parallel: 6670 case OMPD_target_parallel_for: 6671 case OMPD_target_parallel_for_simd: 6672 case OMPD_target_simd: 6673 return Bld.getInt32(1); 6674 case OMPD_parallel: 6675 case OMPD_for: 6676 case OMPD_parallel_for: 6677 case OMPD_parallel_sections: 6678 case OMPD_for_simd: 6679 case OMPD_parallel_for_simd: 6680 case OMPD_cancel: 6681 case OMPD_cancellation_point: 6682 case OMPD_ordered: 6683 case OMPD_threadprivate: 6684 case OMPD_allocate: 6685 case OMPD_task: 6686 case OMPD_simd: 6687 case OMPD_sections: 6688 case OMPD_section: 6689 case OMPD_single: 6690 case OMPD_master: 6691 case OMPD_critical: 6692 case OMPD_taskyield: 6693 case OMPD_barrier: 6694 case OMPD_taskwait: 6695 case OMPD_taskgroup: 6696 case OMPD_atomic: 6697 case OMPD_flush: 6698 case OMPD_teams: 6699 case OMPD_target_data: 6700 case OMPD_target_exit_data: 6701 case OMPD_target_enter_data: 6702 case OMPD_distribute: 6703 case OMPD_distribute_simd: 6704 case OMPD_distribute_parallel_for: 6705 case OMPD_distribute_parallel_for_simd: 6706 case OMPD_teams_distribute: 6707 case OMPD_teams_distribute_simd: 6708 case OMPD_teams_distribute_parallel_for: 6709 case OMPD_teams_distribute_parallel_for_simd: 6710 case OMPD_target_update: 6711 case OMPD_declare_simd: 6712 case OMPD_declare_variant: 6713 case OMPD_declare_target: 6714 case OMPD_end_declare_target: 6715 case OMPD_declare_reduction: 6716 case OMPD_declare_mapper: 6717 case OMPD_taskloop: 6718 case OMPD_taskloop_simd: 6719 case OMPD_master_taskloop: 6720 case OMPD_master_taskloop_simd: 6721 case OMPD_parallel_master_taskloop: 6722 case OMPD_parallel_master_taskloop_simd: 6723 case OMPD_requires: 6724 case OMPD_unknown: 6725 break; 6726 } 6727 llvm_unreachable("Unexpected directive kind."); 6728 } 6729 6730 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6731 llvm::Value *DefaultThreadLimitVal) { 6732 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6733 CGF.getContext(), CS->getCapturedStmt()); 6734 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6735 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6736 llvm::Value *NumThreads = nullptr; 6737 llvm::Value *CondVal = nullptr; 6738 // Handle if clause. If if clause present, the number of threads is 6739 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6740 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6741 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6742 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6743 const OMPIfClause *IfClause = nullptr; 6744 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6745 if (C->getNameModifier() == OMPD_unknown || 6746 C->getNameModifier() == OMPD_parallel) { 6747 IfClause = C; 6748 break; 6749 } 6750 } 6751 if (IfClause) { 6752 const Expr *Cond = IfClause->getCondition(); 6753 bool Result; 6754 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6755 if (!Result) 6756 return CGF.Builder.getInt32(1); 6757 } else { 6758 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6759 if (const auto *PreInit = 6760 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6761 for (const auto *I : PreInit->decls()) { 6762 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6763 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6764 } else { 6765 CodeGenFunction::AutoVarEmission Emission = 6766 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6767 CGF.EmitAutoVarCleanups(Emission); 6768 } 6769 } 6770 } 6771 CondVal = CGF.EvaluateExprAsBool(Cond); 6772 } 6773 } 6774 } 6775 // Check the value of num_threads clause iff if clause was not specified 6776 // or is not evaluated to false. 6777 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6778 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6779 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6780 const auto *NumThreadsClause = 6781 Dir->getSingleClause<OMPNumThreadsClause>(); 6782 CodeGenFunction::LexicalScope Scope( 6783 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6784 if (const auto *PreInit = 6785 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6786 for (const auto *I : PreInit->decls()) { 6787 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6788 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6789 } else { 6790 CodeGenFunction::AutoVarEmission Emission = 6791 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6792 CGF.EmitAutoVarCleanups(Emission); 6793 } 6794 } 6795 } 6796 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6797 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6798 /*isSigned=*/false); 6799 if (DefaultThreadLimitVal) 6800 NumThreads = CGF.Builder.CreateSelect( 6801 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6802 DefaultThreadLimitVal, NumThreads); 6803 } else { 6804 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6805 : CGF.Builder.getInt32(0); 6806 } 6807 // Process condition of the if clause. 6808 if (CondVal) { 6809 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6810 CGF.Builder.getInt32(1)); 6811 } 6812 return NumThreads; 6813 } 6814 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6815 return CGF.Builder.getInt32(1); 6816 return DefaultThreadLimitVal; 6817 } 6818 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6819 : CGF.Builder.getInt32(0); 6820 } 6821 6822 /// Emit the number of threads for a target directive. Inspect the 6823 /// thread_limit clause associated with a teams construct combined or closely 6824 /// nested with the target directive. 6825 /// 6826 /// Emit the num_threads clause for directives such as 'target parallel' that 6827 /// have no associated teams construct. 6828 /// 6829 /// Otherwise, return nullptr. 6830 static llvm::Value * 6831 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6832 const OMPExecutableDirective &D) { 6833 assert(!CGF.getLangOpts().OpenMPIsDevice && 6834 "Clauses associated with the teams directive expected to be emitted " 6835 "only for the host!"); 6836 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6837 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6838 "Expected target-based executable directive."); 6839 CGBuilderTy &Bld = CGF.Builder; 6840 llvm::Value *ThreadLimitVal = nullptr; 6841 llvm::Value *NumThreadsVal = nullptr; 6842 switch (DirectiveKind) { 6843 case OMPD_target: { 6844 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6845 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6846 return NumThreads; 6847 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6848 CGF.getContext(), CS->getCapturedStmt()); 6849 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6850 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6851 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6852 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6853 const auto *ThreadLimitClause = 6854 Dir->getSingleClause<OMPThreadLimitClause>(); 6855 CodeGenFunction::LexicalScope Scope( 6856 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6857 if (const auto *PreInit = 6858 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6859 for (const auto *I : PreInit->decls()) { 6860 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6861 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6862 } else { 6863 CodeGenFunction::AutoVarEmission Emission = 6864 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6865 CGF.EmitAutoVarCleanups(Emission); 6866 } 6867 } 6868 } 6869 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6870 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6871 ThreadLimitVal = 6872 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6873 } 6874 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6875 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6876 CS = Dir->getInnermostCapturedStmt(); 6877 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6878 CGF.getContext(), CS->getCapturedStmt()); 6879 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6880 } 6881 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6882 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6883 CS = Dir->getInnermostCapturedStmt(); 6884 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6885 return NumThreads; 6886 } 6887 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6888 return Bld.getInt32(1); 6889 } 6890 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6891 } 6892 case OMPD_target_teams: { 6893 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6894 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6895 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6896 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6897 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6898 ThreadLimitVal = 6899 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6900 } 6901 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6902 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6903 return NumThreads; 6904 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6905 CGF.getContext(), CS->getCapturedStmt()); 6906 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6907 if (Dir->getDirectiveKind() == OMPD_distribute) { 6908 CS = Dir->getInnermostCapturedStmt(); 6909 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6910 return NumThreads; 6911 } 6912 } 6913 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6914 } 6915 case OMPD_target_teams_distribute: 6916 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6917 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6918 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6919 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6920 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6921 ThreadLimitVal = 6922 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6923 } 6924 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6925 case OMPD_target_parallel: 6926 case OMPD_target_parallel_for: 6927 case OMPD_target_parallel_for_simd: 6928 case OMPD_target_teams_distribute_parallel_for: 6929 case OMPD_target_teams_distribute_parallel_for_simd: { 6930 llvm::Value *CondVal = nullptr; 6931 // Handle if clause. If if clause present, the number of threads is 6932 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6933 if (D.hasClausesOfKind<OMPIfClause>()) { 6934 const OMPIfClause *IfClause = nullptr; 6935 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6936 if (C->getNameModifier() == OMPD_unknown || 6937 C->getNameModifier() == OMPD_parallel) { 6938 IfClause = C; 6939 break; 6940 } 6941 } 6942 if (IfClause) { 6943 const Expr *Cond = IfClause->getCondition(); 6944 bool Result; 6945 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6946 if (!Result) 6947 return Bld.getInt32(1); 6948 } else { 6949 CodeGenFunction::RunCleanupsScope Scope(CGF); 6950 CondVal = CGF.EvaluateExprAsBool(Cond); 6951 } 6952 } 6953 } 6954 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6955 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6956 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6957 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6958 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6959 ThreadLimitVal = 6960 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6961 } 6962 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6963 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6964 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6965 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6966 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6967 NumThreadsVal = 6968 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6969 ThreadLimitVal = ThreadLimitVal 6970 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6971 ThreadLimitVal), 6972 NumThreadsVal, ThreadLimitVal) 6973 : NumThreadsVal; 6974 } 6975 if (!ThreadLimitVal) 6976 ThreadLimitVal = Bld.getInt32(0); 6977 if (CondVal) 6978 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6979 return ThreadLimitVal; 6980 } 6981 case OMPD_target_teams_distribute_simd: 6982 case OMPD_target_simd: 6983 return Bld.getInt32(1); 6984 case OMPD_parallel: 6985 case OMPD_for: 6986 case OMPD_parallel_for: 6987 case OMPD_parallel_sections: 6988 case OMPD_for_simd: 6989 case OMPD_parallel_for_simd: 6990 case OMPD_cancel: 6991 case OMPD_cancellation_point: 6992 case OMPD_ordered: 6993 case OMPD_threadprivate: 6994 case OMPD_allocate: 6995 case OMPD_task: 6996 case OMPD_simd: 6997 case OMPD_sections: 6998 case OMPD_section: 6999 case OMPD_single: 7000 case OMPD_master: 7001 case OMPD_critical: 7002 case OMPD_taskyield: 7003 case OMPD_barrier: 7004 case OMPD_taskwait: 7005 case OMPD_taskgroup: 7006 case OMPD_atomic: 7007 case OMPD_flush: 7008 case OMPD_teams: 7009 case OMPD_target_data: 7010 case OMPD_target_exit_data: 7011 case OMPD_target_enter_data: 7012 case OMPD_distribute: 7013 case OMPD_distribute_simd: 7014 case OMPD_distribute_parallel_for: 7015 case OMPD_distribute_parallel_for_simd: 7016 case OMPD_teams_distribute: 7017 case OMPD_teams_distribute_simd: 7018 case OMPD_teams_distribute_parallel_for: 7019 case OMPD_teams_distribute_parallel_for_simd: 7020 case OMPD_target_update: 7021 case OMPD_declare_simd: 7022 case OMPD_declare_variant: 7023 case OMPD_declare_target: 7024 case OMPD_end_declare_target: 7025 case OMPD_declare_reduction: 7026 case OMPD_declare_mapper: 7027 case OMPD_taskloop: 7028 case OMPD_taskloop_simd: 7029 case OMPD_master_taskloop: 7030 case OMPD_master_taskloop_simd: 7031 case OMPD_parallel_master_taskloop: 7032 case OMPD_parallel_master_taskloop_simd: 7033 case OMPD_requires: 7034 case OMPD_unknown: 7035 break; 7036 } 7037 llvm_unreachable("Unsupported directive kind."); 7038 } 7039 7040 namespace { 7041 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7042 7043 // Utility to handle information from clauses associated with a given 7044 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7045 // It provides a convenient interface to obtain the information and generate 7046 // code for that information. 7047 class MappableExprsHandler { 7048 public: 7049 /// Values for bit flags used to specify the mapping type for 7050 /// offloading. 7051 enum OpenMPOffloadMappingFlags : uint64_t { 7052 /// No flags 7053 OMP_MAP_NONE = 0x0, 7054 /// Allocate memory on the device and move data from host to device. 7055 OMP_MAP_TO = 0x01, 7056 /// Allocate memory on the device and move data from device to host. 7057 OMP_MAP_FROM = 0x02, 7058 /// Always perform the requested mapping action on the element, even 7059 /// if it was already mapped before. 7060 OMP_MAP_ALWAYS = 0x04, 7061 /// Delete the element from the device environment, ignoring the 7062 /// current reference count associated with the element. 7063 OMP_MAP_DELETE = 0x08, 7064 /// The element being mapped is a pointer-pointee pair; both the 7065 /// pointer and the pointee should be mapped. 7066 OMP_MAP_PTR_AND_OBJ = 0x10, 7067 /// This flags signals that the base address of an entry should be 7068 /// passed to the target kernel as an argument. 7069 OMP_MAP_TARGET_PARAM = 0x20, 7070 /// Signal that the runtime library has to return the device pointer 7071 /// in the current position for the data being mapped. Used when we have the 7072 /// use_device_ptr clause. 7073 OMP_MAP_RETURN_PARAM = 0x40, 7074 /// This flag signals that the reference being passed is a pointer to 7075 /// private data. 7076 OMP_MAP_PRIVATE = 0x80, 7077 /// Pass the element to the device by value. 7078 OMP_MAP_LITERAL = 0x100, 7079 /// Implicit map 7080 OMP_MAP_IMPLICIT = 0x200, 7081 /// Close is a hint to the runtime to allocate memory close to 7082 /// the target device. 7083 OMP_MAP_CLOSE = 0x400, 7084 /// The 16 MSBs of the flags indicate whether the entry is member of some 7085 /// struct/class. 7086 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7087 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7088 }; 7089 7090 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7091 static unsigned getFlagMemberOffset() { 7092 unsigned Offset = 0; 7093 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7094 Remain = Remain >> 1) 7095 Offset++; 7096 return Offset; 7097 } 7098 7099 /// Class that associates information with a base pointer to be passed to the 7100 /// runtime library. 7101 class BasePointerInfo { 7102 /// The base pointer. 7103 llvm::Value *Ptr = nullptr; 7104 /// The base declaration that refers to this device pointer, or null if 7105 /// there is none. 7106 const ValueDecl *DevPtrDecl = nullptr; 7107 7108 public: 7109 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7110 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7111 llvm::Value *operator*() const { return Ptr; } 7112 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7113 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7114 }; 7115 7116 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7117 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7118 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7119 7120 /// Map between a struct and the its lowest & highest elements which have been 7121 /// mapped. 7122 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7123 /// HE(FieldIndex, Pointer)} 7124 struct StructRangeInfoTy { 7125 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7126 0, Address::invalid()}; 7127 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7128 0, Address::invalid()}; 7129 Address Base = Address::invalid(); 7130 }; 7131 7132 private: 7133 /// Kind that defines how a device pointer has to be returned. 7134 struct MapInfo { 7135 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7136 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7137 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7138 bool ReturnDevicePointer = false; 7139 bool IsImplicit = false; 7140 7141 MapInfo() = default; 7142 MapInfo( 7143 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7144 OpenMPMapClauseKind MapType, 7145 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7146 bool ReturnDevicePointer, bool IsImplicit) 7147 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7148 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7149 }; 7150 7151 /// If use_device_ptr is used on a pointer which is a struct member and there 7152 /// is no map information about it, then emission of that entry is deferred 7153 /// until the whole struct has been processed. 7154 struct DeferredDevicePtrEntryTy { 7155 const Expr *IE = nullptr; 7156 const ValueDecl *VD = nullptr; 7157 7158 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7159 : IE(IE), VD(VD) {} 7160 }; 7161 7162 /// The target directive from where the mappable clauses were extracted. It 7163 /// is either a executable directive or a user-defined mapper directive. 7164 llvm::PointerUnion<const OMPExecutableDirective *, 7165 const OMPDeclareMapperDecl *> 7166 CurDir; 7167 7168 /// Function the directive is being generated for. 7169 CodeGenFunction &CGF; 7170 7171 /// Set of all first private variables in the current directive. 7172 /// bool data is set to true if the variable is implicitly marked as 7173 /// firstprivate, false otherwise. 7174 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7175 7176 /// Map between device pointer declarations and their expression components. 7177 /// The key value for declarations in 'this' is null. 7178 llvm::DenseMap< 7179 const ValueDecl *, 7180 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7181 DevPointersMap; 7182 7183 llvm::Value *getExprTypeSize(const Expr *E) const { 7184 QualType ExprTy = E->getType().getCanonicalType(); 7185 7186 // Reference types are ignored for mapping purposes. 7187 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7188 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7189 7190 // Given that an array section is considered a built-in type, we need to 7191 // do the calculation based on the length of the section instead of relying 7192 // on CGF.getTypeSize(E->getType()). 7193 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7194 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7195 OAE->getBase()->IgnoreParenImpCasts()) 7196 .getCanonicalType(); 7197 7198 // If there is no length associated with the expression and lower bound is 7199 // not specified too, that means we are using the whole length of the 7200 // base. 7201 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7202 !OAE->getLowerBound()) 7203 return CGF.getTypeSize(BaseTy); 7204 7205 llvm::Value *ElemSize; 7206 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7207 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7208 } else { 7209 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7210 assert(ATy && "Expecting array type if not a pointer type."); 7211 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7212 } 7213 7214 // If we don't have a length at this point, that is because we have an 7215 // array section with a single element. 7216 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7217 return ElemSize; 7218 7219 if (const Expr *LenExpr = OAE->getLength()) { 7220 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7221 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7222 CGF.getContext().getSizeType(), 7223 LenExpr->getExprLoc()); 7224 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7225 } 7226 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7227 OAE->getLowerBound() && "expected array_section[lb:]."); 7228 // Size = sizetype - lb * elemtype; 7229 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7230 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7231 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7232 CGF.getContext().getSizeType(), 7233 OAE->getLowerBound()->getExprLoc()); 7234 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7235 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7236 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7237 LengthVal = CGF.Builder.CreateSelect( 7238 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7239 return LengthVal; 7240 } 7241 return CGF.getTypeSize(ExprTy); 7242 } 7243 7244 /// Return the corresponding bits for a given map clause modifier. Add 7245 /// a flag marking the map as a pointer if requested. Add a flag marking the 7246 /// map as the first one of a series of maps that relate to the same map 7247 /// expression. 7248 OpenMPOffloadMappingFlags getMapTypeBits( 7249 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7250 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7251 OpenMPOffloadMappingFlags Bits = 7252 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7253 switch (MapType) { 7254 case OMPC_MAP_alloc: 7255 case OMPC_MAP_release: 7256 // alloc and release is the default behavior in the runtime library, i.e. 7257 // if we don't pass any bits alloc/release that is what the runtime is 7258 // going to do. Therefore, we don't need to signal anything for these two 7259 // type modifiers. 7260 break; 7261 case OMPC_MAP_to: 7262 Bits |= OMP_MAP_TO; 7263 break; 7264 case OMPC_MAP_from: 7265 Bits |= OMP_MAP_FROM; 7266 break; 7267 case OMPC_MAP_tofrom: 7268 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7269 break; 7270 case OMPC_MAP_delete: 7271 Bits |= OMP_MAP_DELETE; 7272 break; 7273 case OMPC_MAP_unknown: 7274 llvm_unreachable("Unexpected map type!"); 7275 } 7276 if (AddPtrFlag) 7277 Bits |= OMP_MAP_PTR_AND_OBJ; 7278 if (AddIsTargetParamFlag) 7279 Bits |= OMP_MAP_TARGET_PARAM; 7280 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7281 != MapModifiers.end()) 7282 Bits |= OMP_MAP_ALWAYS; 7283 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7284 != MapModifiers.end()) 7285 Bits |= OMP_MAP_CLOSE; 7286 return Bits; 7287 } 7288 7289 /// Return true if the provided expression is a final array section. A 7290 /// final array section, is one whose length can't be proved to be one. 7291 bool isFinalArraySectionExpression(const Expr *E) const { 7292 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7293 7294 // It is not an array section and therefore not a unity-size one. 7295 if (!OASE) 7296 return false; 7297 7298 // An array section with no colon always refer to a single element. 7299 if (OASE->getColonLoc().isInvalid()) 7300 return false; 7301 7302 const Expr *Length = OASE->getLength(); 7303 7304 // If we don't have a length we have to check if the array has size 1 7305 // for this dimension. Also, we should always expect a length if the 7306 // base type is pointer. 7307 if (!Length) { 7308 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7309 OASE->getBase()->IgnoreParenImpCasts()) 7310 .getCanonicalType(); 7311 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7312 return ATy->getSize().getSExtValue() != 1; 7313 // If we don't have a constant dimension length, we have to consider 7314 // the current section as having any size, so it is not necessarily 7315 // unitary. If it happen to be unity size, that's user fault. 7316 return true; 7317 } 7318 7319 // Check if the length evaluates to 1. 7320 Expr::EvalResult Result; 7321 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7322 return true; // Can have more that size 1. 7323 7324 llvm::APSInt ConstLength = Result.Val.getInt(); 7325 return ConstLength.getSExtValue() != 1; 7326 } 7327 7328 /// Generate the base pointers, section pointers, sizes and map type 7329 /// bits for the provided map type, map modifier, and expression components. 7330 /// \a IsFirstComponent should be set to true if the provided set of 7331 /// components is the first associated with a capture. 7332 void generateInfoForComponentList( 7333 OpenMPMapClauseKind MapType, 7334 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7335 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7336 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7337 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7338 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7339 bool IsImplicit, 7340 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7341 OverlappedElements = llvm::None) const { 7342 // The following summarizes what has to be generated for each map and the 7343 // types below. The generated information is expressed in this order: 7344 // base pointer, section pointer, size, flags 7345 // (to add to the ones that come from the map type and modifier). 7346 // 7347 // double d; 7348 // int i[100]; 7349 // float *p; 7350 // 7351 // struct S1 { 7352 // int i; 7353 // float f[50]; 7354 // } 7355 // struct S2 { 7356 // int i; 7357 // float f[50]; 7358 // S1 s; 7359 // double *p; 7360 // struct S2 *ps; 7361 // } 7362 // S2 s; 7363 // S2 *ps; 7364 // 7365 // map(d) 7366 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7367 // 7368 // map(i) 7369 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7370 // 7371 // map(i[1:23]) 7372 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7373 // 7374 // map(p) 7375 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7376 // 7377 // map(p[1:24]) 7378 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7379 // 7380 // map(s) 7381 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7382 // 7383 // map(s.i) 7384 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7385 // 7386 // map(s.s.f) 7387 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7388 // 7389 // map(s.p) 7390 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7391 // 7392 // map(to: s.p[:22]) 7393 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7394 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7395 // &(s.p), &(s.p[0]), 22*sizeof(double), 7396 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7397 // (*) alloc space for struct members, only this is a target parameter 7398 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7399 // optimizes this entry out, same in the examples below) 7400 // (***) map the pointee (map: to) 7401 // 7402 // map(s.ps) 7403 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7404 // 7405 // map(from: s.ps->s.i) 7406 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7407 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7408 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7409 // 7410 // map(to: s.ps->ps) 7411 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7412 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7413 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7414 // 7415 // map(s.ps->ps->ps) 7416 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7417 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7418 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7419 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7420 // 7421 // map(to: s.ps->ps->s.f[:22]) 7422 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7423 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7424 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7425 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7426 // 7427 // map(ps) 7428 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7429 // 7430 // map(ps->i) 7431 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7432 // 7433 // map(ps->s.f) 7434 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7435 // 7436 // map(from: ps->p) 7437 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7438 // 7439 // map(to: ps->p[:22]) 7440 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7441 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7442 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7443 // 7444 // map(ps->ps) 7445 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7446 // 7447 // map(from: ps->ps->s.i) 7448 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7449 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7450 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7451 // 7452 // map(from: ps->ps->ps) 7453 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7454 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7455 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7456 // 7457 // map(ps->ps->ps->ps) 7458 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7459 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7460 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7461 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7462 // 7463 // map(to: ps->ps->ps->s.f[:22]) 7464 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7465 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7466 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7467 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7468 // 7469 // map(to: s.f[:22]) map(from: s.p[:33]) 7470 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7471 // sizeof(double*) (**), TARGET_PARAM 7472 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7473 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7474 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7475 // (*) allocate contiguous space needed to fit all mapped members even if 7476 // we allocate space for members not mapped (in this example, 7477 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7478 // them as well because they fall between &s.f[0] and &s.p) 7479 // 7480 // map(from: s.f[:22]) map(to: ps->p[:33]) 7481 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7482 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7483 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7484 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7485 // (*) the struct this entry pertains to is the 2nd element in the list of 7486 // arguments, hence MEMBER_OF(2) 7487 // 7488 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7489 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7490 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7491 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7492 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7493 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7494 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7495 // (*) the struct this entry pertains to is the 4th element in the list 7496 // of arguments, hence MEMBER_OF(4) 7497 7498 // Track if the map information being generated is the first for a capture. 7499 bool IsCaptureFirstInfo = IsFirstComponentList; 7500 // When the variable is on a declare target link or in a to clause with 7501 // unified memory, a reference is needed to hold the host/device address 7502 // of the variable. 7503 bool RequiresReference = false; 7504 7505 // Scan the components from the base to the complete expression. 7506 auto CI = Components.rbegin(); 7507 auto CE = Components.rend(); 7508 auto I = CI; 7509 7510 // Track if the map information being generated is the first for a list of 7511 // components. 7512 bool IsExpressionFirstInfo = true; 7513 Address BP = Address::invalid(); 7514 const Expr *AssocExpr = I->getAssociatedExpression(); 7515 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7516 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7517 7518 if (isa<MemberExpr>(AssocExpr)) { 7519 // The base is the 'this' pointer. The content of the pointer is going 7520 // to be the base of the field being mapped. 7521 BP = CGF.LoadCXXThisAddress(); 7522 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7523 (OASE && 7524 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7525 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7526 } else { 7527 // The base is the reference to the variable. 7528 // BP = &Var. 7529 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7530 if (const auto *VD = 7531 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7532 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7533 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7534 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7535 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7536 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7537 RequiresReference = true; 7538 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7539 } 7540 } 7541 } 7542 7543 // If the variable is a pointer and is being dereferenced (i.e. is not 7544 // the last component), the base has to be the pointer itself, not its 7545 // reference. References are ignored for mapping purposes. 7546 QualType Ty = 7547 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7548 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7549 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7550 7551 // We do not need to generate individual map information for the 7552 // pointer, it can be associated with the combined storage. 7553 ++I; 7554 } 7555 } 7556 7557 // Track whether a component of the list should be marked as MEMBER_OF some 7558 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7559 // in a component list should be marked as MEMBER_OF, all subsequent entries 7560 // do not belong to the base struct. E.g. 7561 // struct S2 s; 7562 // s.ps->ps->ps->f[:] 7563 // (1) (2) (3) (4) 7564 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7565 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7566 // is the pointee of ps(2) which is not member of struct s, so it should not 7567 // be marked as such (it is still PTR_AND_OBJ). 7568 // The variable is initialized to false so that PTR_AND_OBJ entries which 7569 // are not struct members are not considered (e.g. array of pointers to 7570 // data). 7571 bool ShouldBeMemberOf = false; 7572 7573 // Variable keeping track of whether or not we have encountered a component 7574 // in the component list which is a member expression. Useful when we have a 7575 // pointer or a final array section, in which case it is the previous 7576 // component in the list which tells us whether we have a member expression. 7577 // E.g. X.f[:] 7578 // While processing the final array section "[:]" it is "f" which tells us 7579 // whether we are dealing with a member of a declared struct. 7580 const MemberExpr *EncounteredME = nullptr; 7581 7582 for (; I != CE; ++I) { 7583 // If the current component is member of a struct (parent struct) mark it. 7584 if (!EncounteredME) { 7585 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7586 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7587 // as MEMBER_OF the parent struct. 7588 if (EncounteredME) 7589 ShouldBeMemberOf = true; 7590 } 7591 7592 auto Next = std::next(I); 7593 7594 // We need to generate the addresses and sizes if this is the last 7595 // component, if the component is a pointer or if it is an array section 7596 // whose length can't be proved to be one. If this is a pointer, it 7597 // becomes the base address for the following components. 7598 7599 // A final array section, is one whose length can't be proved to be one. 7600 bool IsFinalArraySection = 7601 isFinalArraySectionExpression(I->getAssociatedExpression()); 7602 7603 // Get information on whether the element is a pointer. Have to do a 7604 // special treatment for array sections given that they are built-in 7605 // types. 7606 const auto *OASE = 7607 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7608 bool IsPointer = 7609 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7610 .getCanonicalType() 7611 ->isAnyPointerType()) || 7612 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7613 7614 if (Next == CE || IsPointer || IsFinalArraySection) { 7615 // If this is not the last component, we expect the pointer to be 7616 // associated with an array expression or member expression. 7617 assert((Next == CE || 7618 isa<MemberExpr>(Next->getAssociatedExpression()) || 7619 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7620 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 7621 "Unexpected expression"); 7622 7623 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7624 .getAddress(CGF); 7625 7626 // If this component is a pointer inside the base struct then we don't 7627 // need to create any entry for it - it will be combined with the object 7628 // it is pointing to into a single PTR_AND_OBJ entry. 7629 bool IsMemberPointer = 7630 IsPointer && EncounteredME && 7631 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7632 EncounteredME); 7633 if (!OverlappedElements.empty()) { 7634 // Handle base element with the info for overlapped elements. 7635 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7636 assert(Next == CE && 7637 "Expected last element for the overlapped elements."); 7638 assert(!IsPointer && 7639 "Unexpected base element with the pointer type."); 7640 // Mark the whole struct as the struct that requires allocation on the 7641 // device. 7642 PartialStruct.LowestElem = {0, LB}; 7643 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7644 I->getAssociatedExpression()->getType()); 7645 Address HB = CGF.Builder.CreateConstGEP( 7646 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7647 CGF.VoidPtrTy), 7648 TypeSize.getQuantity() - 1); 7649 PartialStruct.HighestElem = { 7650 std::numeric_limits<decltype( 7651 PartialStruct.HighestElem.first)>::max(), 7652 HB}; 7653 PartialStruct.Base = BP; 7654 // Emit data for non-overlapped data. 7655 OpenMPOffloadMappingFlags Flags = 7656 OMP_MAP_MEMBER_OF | 7657 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7658 /*AddPtrFlag=*/false, 7659 /*AddIsTargetParamFlag=*/false); 7660 LB = BP; 7661 llvm::Value *Size = nullptr; 7662 // Do bitcopy of all non-overlapped structure elements. 7663 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7664 Component : OverlappedElements) { 7665 Address ComponentLB = Address::invalid(); 7666 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7667 Component) { 7668 if (MC.getAssociatedDeclaration()) { 7669 ComponentLB = 7670 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7671 .getAddress(CGF); 7672 Size = CGF.Builder.CreatePtrDiff( 7673 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7674 CGF.EmitCastToVoidPtr(LB.getPointer())); 7675 break; 7676 } 7677 } 7678 BasePointers.push_back(BP.getPointer()); 7679 Pointers.push_back(LB.getPointer()); 7680 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7681 /*isSigned=*/true)); 7682 Types.push_back(Flags); 7683 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7684 } 7685 BasePointers.push_back(BP.getPointer()); 7686 Pointers.push_back(LB.getPointer()); 7687 Size = CGF.Builder.CreatePtrDiff( 7688 CGF.EmitCastToVoidPtr( 7689 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7690 CGF.EmitCastToVoidPtr(LB.getPointer())); 7691 Sizes.push_back( 7692 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7693 Types.push_back(Flags); 7694 break; 7695 } 7696 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7697 if (!IsMemberPointer) { 7698 BasePointers.push_back(BP.getPointer()); 7699 Pointers.push_back(LB.getPointer()); 7700 Sizes.push_back( 7701 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7702 7703 // We need to add a pointer flag for each map that comes from the 7704 // same expression except for the first one. We also need to signal 7705 // this map is the first one that relates with the current capture 7706 // (there is a set of entries for each capture). 7707 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7708 MapType, MapModifiers, IsImplicit, 7709 !IsExpressionFirstInfo || RequiresReference, 7710 IsCaptureFirstInfo && !RequiresReference); 7711 7712 if (!IsExpressionFirstInfo) { 7713 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7714 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7715 if (IsPointer) 7716 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7717 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7718 7719 if (ShouldBeMemberOf) { 7720 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7721 // should be later updated with the correct value of MEMBER_OF. 7722 Flags |= OMP_MAP_MEMBER_OF; 7723 // From now on, all subsequent PTR_AND_OBJ entries should not be 7724 // marked as MEMBER_OF. 7725 ShouldBeMemberOf = false; 7726 } 7727 } 7728 7729 Types.push_back(Flags); 7730 } 7731 7732 // If we have encountered a member expression so far, keep track of the 7733 // mapped member. If the parent is "*this", then the value declaration 7734 // is nullptr. 7735 if (EncounteredME) { 7736 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); 7737 unsigned FieldIndex = FD->getFieldIndex(); 7738 7739 // Update info about the lowest and highest elements for this struct 7740 if (!PartialStruct.Base.isValid()) { 7741 PartialStruct.LowestElem = {FieldIndex, LB}; 7742 PartialStruct.HighestElem = {FieldIndex, LB}; 7743 PartialStruct.Base = BP; 7744 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7745 PartialStruct.LowestElem = {FieldIndex, LB}; 7746 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7747 PartialStruct.HighestElem = {FieldIndex, LB}; 7748 } 7749 } 7750 7751 // If we have a final array section, we are done with this expression. 7752 if (IsFinalArraySection) 7753 break; 7754 7755 // The pointer becomes the base for the next element. 7756 if (Next != CE) 7757 BP = LB; 7758 7759 IsExpressionFirstInfo = false; 7760 IsCaptureFirstInfo = false; 7761 } 7762 } 7763 } 7764 7765 /// Return the adjusted map modifiers if the declaration a capture refers to 7766 /// appears in a first-private clause. This is expected to be used only with 7767 /// directives that start with 'target'. 7768 MappableExprsHandler::OpenMPOffloadMappingFlags 7769 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7770 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7771 7772 // A first private variable captured by reference will use only the 7773 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7774 // declaration is known as first-private in this handler. 7775 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7776 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7777 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7778 return MappableExprsHandler::OMP_MAP_ALWAYS | 7779 MappableExprsHandler::OMP_MAP_TO; 7780 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7781 return MappableExprsHandler::OMP_MAP_TO | 7782 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7783 return MappableExprsHandler::OMP_MAP_PRIVATE | 7784 MappableExprsHandler::OMP_MAP_TO; 7785 } 7786 return MappableExprsHandler::OMP_MAP_TO | 7787 MappableExprsHandler::OMP_MAP_FROM; 7788 } 7789 7790 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7791 // Rotate by getFlagMemberOffset() bits. 7792 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7793 << getFlagMemberOffset()); 7794 } 7795 7796 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7797 OpenMPOffloadMappingFlags MemberOfFlag) { 7798 // If the entry is PTR_AND_OBJ but has not been marked with the special 7799 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7800 // marked as MEMBER_OF. 7801 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7802 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7803 return; 7804 7805 // Reset the placeholder value to prepare the flag for the assignment of the 7806 // proper MEMBER_OF value. 7807 Flags &= ~OMP_MAP_MEMBER_OF; 7808 Flags |= MemberOfFlag; 7809 } 7810 7811 void getPlainLayout(const CXXRecordDecl *RD, 7812 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7813 bool AsBase) const { 7814 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7815 7816 llvm::StructType *St = 7817 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7818 7819 unsigned NumElements = St->getNumElements(); 7820 llvm::SmallVector< 7821 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7822 RecordLayout(NumElements); 7823 7824 // Fill bases. 7825 for (const auto &I : RD->bases()) { 7826 if (I.isVirtual()) 7827 continue; 7828 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7829 // Ignore empty bases. 7830 if (Base->isEmpty() || CGF.getContext() 7831 .getASTRecordLayout(Base) 7832 .getNonVirtualSize() 7833 .isZero()) 7834 continue; 7835 7836 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7837 RecordLayout[FieldIndex] = Base; 7838 } 7839 // Fill in virtual bases. 7840 for (const auto &I : RD->vbases()) { 7841 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7842 // Ignore empty bases. 7843 if (Base->isEmpty()) 7844 continue; 7845 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7846 if (RecordLayout[FieldIndex]) 7847 continue; 7848 RecordLayout[FieldIndex] = Base; 7849 } 7850 // Fill in all the fields. 7851 assert(!RD->isUnion() && "Unexpected union."); 7852 for (const auto *Field : RD->fields()) { 7853 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7854 // will fill in later.) 7855 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7856 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7857 RecordLayout[FieldIndex] = Field; 7858 } 7859 } 7860 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7861 &Data : RecordLayout) { 7862 if (Data.isNull()) 7863 continue; 7864 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7865 getPlainLayout(Base, Layout, /*AsBase=*/true); 7866 else 7867 Layout.push_back(Data.get<const FieldDecl *>()); 7868 } 7869 } 7870 7871 public: 7872 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7873 : CurDir(&Dir), CGF(CGF) { 7874 // Extract firstprivate clause information. 7875 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7876 for (const auto *D : C->varlists()) 7877 FirstPrivateDecls.try_emplace( 7878 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 7879 // Extract device pointer clause information. 7880 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7881 for (auto L : C->component_lists()) 7882 DevPointersMap[L.first].push_back(L.second); 7883 } 7884 7885 /// Constructor for the declare mapper directive. 7886 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 7887 : CurDir(&Dir), CGF(CGF) {} 7888 7889 /// Generate code for the combined entry if we have a partially mapped struct 7890 /// and take care of the mapping flags of the arguments corresponding to 7891 /// individual struct members. 7892 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 7893 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7894 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 7895 const StructRangeInfoTy &PartialStruct) const { 7896 // Base is the base of the struct 7897 BasePointers.push_back(PartialStruct.Base.getPointer()); 7898 // Pointer is the address of the lowest element 7899 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7900 Pointers.push_back(LB); 7901 // Size is (addr of {highest+1} element) - (addr of lowest element) 7902 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7903 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7904 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7905 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7906 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7907 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 7908 /*isSigned=*/false); 7909 Sizes.push_back(Size); 7910 // Map type is always TARGET_PARAM 7911 Types.push_back(OMP_MAP_TARGET_PARAM); 7912 // Remove TARGET_PARAM flag from the first element 7913 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7914 7915 // All other current entries will be MEMBER_OF the combined entry 7916 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7917 // 0xFFFF in the MEMBER_OF field). 7918 OpenMPOffloadMappingFlags MemberOfFlag = 7919 getMemberOfFlag(BasePointers.size() - 1); 7920 for (auto &M : CurTypes) 7921 setCorrectMemberOfFlag(M, MemberOfFlag); 7922 } 7923 7924 /// Generate all the base pointers, section pointers, sizes and map 7925 /// types for the extracted mappable expressions. Also, for each item that 7926 /// relates with a device pointer, a pair of the relevant declaration and 7927 /// index where it occurs is appended to the device pointers info array. 7928 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 7929 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7930 MapFlagsArrayTy &Types) const { 7931 // We have to process the component lists that relate with the same 7932 // declaration in a single chunk so that we can generate the map flags 7933 // correctly. Therefore, we organize all lists in a map. 7934 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7935 7936 // Helper function to fill the information map for the different supported 7937 // clauses. 7938 auto &&InfoGen = [&Info]( 7939 const ValueDecl *D, 7940 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7941 OpenMPMapClauseKind MapType, 7942 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7943 bool ReturnDevicePointer, bool IsImplicit) { 7944 const ValueDecl *VD = 7945 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7946 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7947 IsImplicit); 7948 }; 7949 7950 assert(CurDir.is<const OMPExecutableDirective *>() && 7951 "Expect a executable directive"); 7952 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 7953 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 7954 for (const auto L : C->component_lists()) { 7955 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 7956 /*ReturnDevicePointer=*/false, C->isImplicit()); 7957 } 7958 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 7959 for (const auto L : C->component_lists()) { 7960 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 7961 /*ReturnDevicePointer=*/false, C->isImplicit()); 7962 } 7963 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 7964 for (const auto L : C->component_lists()) { 7965 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 7966 /*ReturnDevicePointer=*/false, C->isImplicit()); 7967 } 7968 7969 // Look at the use_device_ptr clause information and mark the existing map 7970 // entries as such. If there is no map information for an entry in the 7971 // use_device_ptr list, we create one with map type 'alloc' and zero size 7972 // section. It is the user fault if that was not mapped before. If there is 7973 // no map information and the pointer is a struct member, then we defer the 7974 // emission of that entry until the whole struct has been processed. 7975 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 7976 DeferredInfo; 7977 7978 for (const auto *C : 7979 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 7980 for (const auto L : C->component_lists()) { 7981 assert(!L.second.empty() && "Not expecting empty list of components!"); 7982 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 7983 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 7984 const Expr *IE = L.second.back().getAssociatedExpression(); 7985 // If the first component is a member expression, we have to look into 7986 // 'this', which maps to null in the map of map information. Otherwise 7987 // look directly for the information. 7988 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 7989 7990 // We potentially have map information for this declaration already. 7991 // Look for the first set of components that refer to it. 7992 if (It != Info.end()) { 7993 auto CI = std::find_if( 7994 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 7995 return MI.Components.back().getAssociatedDeclaration() == VD; 7996 }); 7997 // If we found a map entry, signal that the pointer has to be returned 7998 // and move on to the next declaration. 7999 if (CI != It->second.end()) { 8000 CI->ReturnDevicePointer = true; 8001 continue; 8002 } 8003 } 8004 8005 // We didn't find any match in our map information - generate a zero 8006 // size array section - if the pointer is a struct member we defer this 8007 // action until the whole struct has been processed. 8008 if (isa<MemberExpr>(IE)) { 8009 // Insert the pointer into Info to be processed by 8010 // generateInfoForComponentList. Because it is a member pointer 8011 // without a pointee, no entry will be generated for it, therefore 8012 // we need to generate one after the whole struct has been processed. 8013 // Nonetheless, generateInfoForComponentList must be called to take 8014 // the pointer into account for the calculation of the range of the 8015 // partial struct. 8016 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 8017 /*ReturnDevicePointer=*/false, C->isImplicit()); 8018 DeferredInfo[nullptr].emplace_back(IE, VD); 8019 } else { 8020 llvm::Value *Ptr = 8021 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8022 BasePointers.emplace_back(Ptr, VD); 8023 Pointers.push_back(Ptr); 8024 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8025 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8026 } 8027 } 8028 } 8029 8030 for (const auto &M : Info) { 8031 // We need to know when we generate information for the first component 8032 // associated with a capture, because the mapping flags depend on it. 8033 bool IsFirstComponentList = true; 8034 8035 // Temporary versions of arrays 8036 MapBaseValuesArrayTy CurBasePointers; 8037 MapValuesArrayTy CurPointers; 8038 MapValuesArrayTy CurSizes; 8039 MapFlagsArrayTy CurTypes; 8040 StructRangeInfoTy PartialStruct; 8041 8042 for (const MapInfo &L : M.second) { 8043 assert(!L.Components.empty() && 8044 "Not expecting declaration with no component lists."); 8045 8046 // Remember the current base pointer index. 8047 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8048 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8049 CurBasePointers, CurPointers, CurSizes, 8050 CurTypes, PartialStruct, 8051 IsFirstComponentList, L.IsImplicit); 8052 8053 // If this entry relates with a device pointer, set the relevant 8054 // declaration and add the 'return pointer' flag. 8055 if (L.ReturnDevicePointer) { 8056 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8057 "Unexpected number of mapped base pointers."); 8058 8059 const ValueDecl *RelevantVD = 8060 L.Components.back().getAssociatedDeclaration(); 8061 assert(RelevantVD && 8062 "No relevant declaration related with device pointer??"); 8063 8064 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8065 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8066 } 8067 IsFirstComponentList = false; 8068 } 8069 8070 // Append any pending zero-length pointers which are struct members and 8071 // used with use_device_ptr. 8072 auto CI = DeferredInfo.find(M.first); 8073 if (CI != DeferredInfo.end()) { 8074 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8075 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8076 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8077 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8078 CurBasePointers.emplace_back(BasePtr, L.VD); 8079 CurPointers.push_back(Ptr); 8080 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8081 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8082 // value MEMBER_OF=FFFF so that the entry is later updated with the 8083 // correct value of MEMBER_OF. 8084 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8085 OMP_MAP_MEMBER_OF); 8086 } 8087 } 8088 8089 // If there is an entry in PartialStruct it means we have a struct with 8090 // individual members mapped. Emit an extra combined entry. 8091 if (PartialStruct.Base.isValid()) 8092 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8093 PartialStruct); 8094 8095 // We need to append the results of this capture to what we already have. 8096 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8097 Pointers.append(CurPointers.begin(), CurPointers.end()); 8098 Sizes.append(CurSizes.begin(), CurSizes.end()); 8099 Types.append(CurTypes.begin(), CurTypes.end()); 8100 } 8101 } 8102 8103 /// Generate all the base pointers, section pointers, sizes and map types for 8104 /// the extracted map clauses of user-defined mapper. 8105 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8106 MapValuesArrayTy &Pointers, 8107 MapValuesArrayTy &Sizes, 8108 MapFlagsArrayTy &Types) const { 8109 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8110 "Expect a declare mapper directive"); 8111 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8112 // We have to process the component lists that relate with the same 8113 // declaration in a single chunk so that we can generate the map flags 8114 // correctly. Therefore, we organize all lists in a map. 8115 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8116 8117 // Helper function to fill the information map for the different supported 8118 // clauses. 8119 auto &&InfoGen = [&Info]( 8120 const ValueDecl *D, 8121 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8122 OpenMPMapClauseKind MapType, 8123 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8124 bool ReturnDevicePointer, bool IsImplicit) { 8125 const ValueDecl *VD = 8126 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8127 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8128 IsImplicit); 8129 }; 8130 8131 for (const auto *C : CurMapperDir->clauselists()) { 8132 const auto *MC = cast<OMPMapClause>(C); 8133 for (const auto L : MC->component_lists()) { 8134 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8135 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8136 } 8137 } 8138 8139 for (const auto &M : Info) { 8140 // We need to know when we generate information for the first component 8141 // associated with a capture, because the mapping flags depend on it. 8142 bool IsFirstComponentList = true; 8143 8144 // Temporary versions of arrays 8145 MapBaseValuesArrayTy CurBasePointers; 8146 MapValuesArrayTy CurPointers; 8147 MapValuesArrayTy CurSizes; 8148 MapFlagsArrayTy CurTypes; 8149 StructRangeInfoTy PartialStruct; 8150 8151 for (const MapInfo &L : M.second) { 8152 assert(!L.Components.empty() && 8153 "Not expecting declaration with no component lists."); 8154 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8155 CurBasePointers, CurPointers, CurSizes, 8156 CurTypes, PartialStruct, 8157 IsFirstComponentList, L.IsImplicit); 8158 IsFirstComponentList = false; 8159 } 8160 8161 // If there is an entry in PartialStruct it means we have a struct with 8162 // individual members mapped. Emit an extra combined entry. 8163 if (PartialStruct.Base.isValid()) 8164 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8165 PartialStruct); 8166 8167 // We need to append the results of this capture to what we already have. 8168 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8169 Pointers.append(CurPointers.begin(), CurPointers.end()); 8170 Sizes.append(CurSizes.begin(), CurSizes.end()); 8171 Types.append(CurTypes.begin(), CurTypes.end()); 8172 } 8173 } 8174 8175 /// Emit capture info for lambdas for variables captured by reference. 8176 void generateInfoForLambdaCaptures( 8177 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8178 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8179 MapFlagsArrayTy &Types, 8180 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8181 const auto *RD = VD->getType() 8182 .getCanonicalType() 8183 .getNonReferenceType() 8184 ->getAsCXXRecordDecl(); 8185 if (!RD || !RD->isLambda()) 8186 return; 8187 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8188 LValue VDLVal = CGF.MakeAddrLValue( 8189 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8190 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8191 FieldDecl *ThisCapture = nullptr; 8192 RD->getCaptureFields(Captures, ThisCapture); 8193 if (ThisCapture) { 8194 LValue ThisLVal = 8195 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8196 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8197 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8198 VDLVal.getPointer(CGF)); 8199 BasePointers.push_back(ThisLVal.getPointer(CGF)); 8200 Pointers.push_back(ThisLValVal.getPointer(CGF)); 8201 Sizes.push_back( 8202 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8203 CGF.Int64Ty, /*isSigned=*/true)); 8204 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8205 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8206 } 8207 for (const LambdaCapture &LC : RD->captures()) { 8208 if (!LC.capturesVariable()) 8209 continue; 8210 const VarDecl *VD = LC.getCapturedVar(); 8211 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8212 continue; 8213 auto It = Captures.find(VD); 8214 assert(It != Captures.end() && "Found lambda capture without field."); 8215 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8216 if (LC.getCaptureKind() == LCK_ByRef) { 8217 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8218 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8219 VDLVal.getPointer(CGF)); 8220 BasePointers.push_back(VarLVal.getPointer(CGF)); 8221 Pointers.push_back(VarLValVal.getPointer(CGF)); 8222 Sizes.push_back(CGF.Builder.CreateIntCast( 8223 CGF.getTypeSize( 8224 VD->getType().getCanonicalType().getNonReferenceType()), 8225 CGF.Int64Ty, /*isSigned=*/true)); 8226 } else { 8227 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8228 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8229 VDLVal.getPointer(CGF)); 8230 BasePointers.push_back(VarLVal.getPointer(CGF)); 8231 Pointers.push_back(VarRVal.getScalarVal()); 8232 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8233 } 8234 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8235 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8236 } 8237 } 8238 8239 /// Set correct indices for lambdas captures. 8240 void adjustMemberOfForLambdaCaptures( 8241 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8242 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8243 MapFlagsArrayTy &Types) const { 8244 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8245 // Set correct member_of idx for all implicit lambda captures. 8246 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8247 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8248 continue; 8249 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8250 assert(BasePtr && "Unable to find base lambda address."); 8251 int TgtIdx = -1; 8252 for (unsigned J = I; J > 0; --J) { 8253 unsigned Idx = J - 1; 8254 if (Pointers[Idx] != BasePtr) 8255 continue; 8256 TgtIdx = Idx; 8257 break; 8258 } 8259 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8260 // All other current entries will be MEMBER_OF the combined entry 8261 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8262 // 0xFFFF in the MEMBER_OF field). 8263 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8264 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8265 } 8266 } 8267 8268 /// Generate the base pointers, section pointers, sizes and map types 8269 /// associated to a given capture. 8270 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8271 llvm::Value *Arg, 8272 MapBaseValuesArrayTy &BasePointers, 8273 MapValuesArrayTy &Pointers, 8274 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8275 StructRangeInfoTy &PartialStruct) const { 8276 assert(!Cap->capturesVariableArrayType() && 8277 "Not expecting to generate map info for a variable array type!"); 8278 8279 // We need to know when we generating information for the first component 8280 const ValueDecl *VD = Cap->capturesThis() 8281 ? nullptr 8282 : Cap->getCapturedVar()->getCanonicalDecl(); 8283 8284 // If this declaration appears in a is_device_ptr clause we just have to 8285 // pass the pointer by value. If it is a reference to a declaration, we just 8286 // pass its value. 8287 if (DevPointersMap.count(VD)) { 8288 BasePointers.emplace_back(Arg, VD); 8289 Pointers.push_back(Arg); 8290 Sizes.push_back( 8291 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8292 CGF.Int64Ty, /*isSigned=*/true)); 8293 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8294 return; 8295 } 8296 8297 using MapData = 8298 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8299 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8300 SmallVector<MapData, 4> DeclComponentLists; 8301 assert(CurDir.is<const OMPExecutableDirective *>() && 8302 "Expect a executable directive"); 8303 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8304 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8305 for (const auto L : C->decl_component_lists(VD)) { 8306 assert(L.first == VD && 8307 "We got information for the wrong declaration??"); 8308 assert(!L.second.empty() && 8309 "Not expecting declaration with no component lists."); 8310 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8311 C->getMapTypeModifiers(), 8312 C->isImplicit()); 8313 } 8314 } 8315 8316 // Find overlapping elements (including the offset from the base element). 8317 llvm::SmallDenseMap< 8318 const MapData *, 8319 llvm::SmallVector< 8320 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8321 4> 8322 OverlappedData; 8323 size_t Count = 0; 8324 for (const MapData &L : DeclComponentLists) { 8325 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8326 OpenMPMapClauseKind MapType; 8327 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8328 bool IsImplicit; 8329 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8330 ++Count; 8331 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8332 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8333 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8334 auto CI = Components.rbegin(); 8335 auto CE = Components.rend(); 8336 auto SI = Components1.rbegin(); 8337 auto SE = Components1.rend(); 8338 for (; CI != CE && SI != SE; ++CI, ++SI) { 8339 if (CI->getAssociatedExpression()->getStmtClass() != 8340 SI->getAssociatedExpression()->getStmtClass()) 8341 break; 8342 // Are we dealing with different variables/fields? 8343 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8344 break; 8345 } 8346 // Found overlapping if, at least for one component, reached the head of 8347 // the components list. 8348 if (CI == CE || SI == SE) { 8349 assert((CI != CE || SI != SE) && 8350 "Unexpected full match of the mapping components."); 8351 const MapData &BaseData = CI == CE ? L : L1; 8352 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8353 SI == SE ? Components : Components1; 8354 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8355 OverlappedElements.getSecond().push_back(SubData); 8356 } 8357 } 8358 } 8359 // Sort the overlapped elements for each item. 8360 llvm::SmallVector<const FieldDecl *, 4> Layout; 8361 if (!OverlappedData.empty()) { 8362 if (const auto *CRD = 8363 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8364 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8365 else { 8366 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8367 Layout.append(RD->field_begin(), RD->field_end()); 8368 } 8369 } 8370 for (auto &Pair : OverlappedData) { 8371 llvm::sort( 8372 Pair.getSecond(), 8373 [&Layout]( 8374 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8375 OMPClauseMappableExprCommon::MappableExprComponentListRef 8376 Second) { 8377 auto CI = First.rbegin(); 8378 auto CE = First.rend(); 8379 auto SI = Second.rbegin(); 8380 auto SE = Second.rend(); 8381 for (; CI != CE && SI != SE; ++CI, ++SI) { 8382 if (CI->getAssociatedExpression()->getStmtClass() != 8383 SI->getAssociatedExpression()->getStmtClass()) 8384 break; 8385 // Are we dealing with different variables/fields? 8386 if (CI->getAssociatedDeclaration() != 8387 SI->getAssociatedDeclaration()) 8388 break; 8389 } 8390 8391 // Lists contain the same elements. 8392 if (CI == CE && SI == SE) 8393 return false; 8394 8395 // List with less elements is less than list with more elements. 8396 if (CI == CE || SI == SE) 8397 return CI == CE; 8398 8399 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8400 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8401 if (FD1->getParent() == FD2->getParent()) 8402 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8403 const auto It = 8404 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8405 return FD == FD1 || FD == FD2; 8406 }); 8407 return *It == FD1; 8408 }); 8409 } 8410 8411 // Associated with a capture, because the mapping flags depend on it. 8412 // Go through all of the elements with the overlapped elements. 8413 for (const auto &Pair : OverlappedData) { 8414 const MapData &L = *Pair.getFirst(); 8415 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8416 OpenMPMapClauseKind MapType; 8417 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8418 bool IsImplicit; 8419 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8420 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8421 OverlappedComponents = Pair.getSecond(); 8422 bool IsFirstComponentList = true; 8423 generateInfoForComponentList(MapType, MapModifiers, Components, 8424 BasePointers, Pointers, Sizes, Types, 8425 PartialStruct, IsFirstComponentList, 8426 IsImplicit, OverlappedComponents); 8427 } 8428 // Go through other elements without overlapped elements. 8429 bool IsFirstComponentList = OverlappedData.empty(); 8430 for (const MapData &L : DeclComponentLists) { 8431 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8432 OpenMPMapClauseKind MapType; 8433 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8434 bool IsImplicit; 8435 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8436 auto It = OverlappedData.find(&L); 8437 if (It == OverlappedData.end()) 8438 generateInfoForComponentList(MapType, MapModifiers, Components, 8439 BasePointers, Pointers, Sizes, Types, 8440 PartialStruct, IsFirstComponentList, 8441 IsImplicit); 8442 IsFirstComponentList = false; 8443 } 8444 } 8445 8446 /// Generate the base pointers, section pointers, sizes and map types 8447 /// associated with the declare target link variables. 8448 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8449 MapValuesArrayTy &Pointers, 8450 MapValuesArrayTy &Sizes, 8451 MapFlagsArrayTy &Types) const { 8452 assert(CurDir.is<const OMPExecutableDirective *>() && 8453 "Expect a executable directive"); 8454 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8455 // Map other list items in the map clause which are not captured variables 8456 // but "declare target link" global variables. 8457 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8458 for (const auto L : C->component_lists()) { 8459 if (!L.first) 8460 continue; 8461 const auto *VD = dyn_cast<VarDecl>(L.first); 8462 if (!VD) 8463 continue; 8464 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8465 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8466 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8467 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8468 continue; 8469 StructRangeInfoTy PartialStruct; 8470 generateInfoForComponentList( 8471 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8472 Pointers, Sizes, Types, PartialStruct, 8473 /*IsFirstComponentList=*/true, C->isImplicit()); 8474 assert(!PartialStruct.Base.isValid() && 8475 "No partial structs for declare target link expected."); 8476 } 8477 } 8478 } 8479 8480 /// Generate the default map information for a given capture \a CI, 8481 /// record field declaration \a RI and captured value \a CV. 8482 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8483 const FieldDecl &RI, llvm::Value *CV, 8484 MapBaseValuesArrayTy &CurBasePointers, 8485 MapValuesArrayTy &CurPointers, 8486 MapValuesArrayTy &CurSizes, 8487 MapFlagsArrayTy &CurMapTypes) const { 8488 bool IsImplicit = true; 8489 // Do the default mapping. 8490 if (CI.capturesThis()) { 8491 CurBasePointers.push_back(CV); 8492 CurPointers.push_back(CV); 8493 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8494 CurSizes.push_back( 8495 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8496 CGF.Int64Ty, /*isSigned=*/true)); 8497 // Default map type. 8498 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8499 } else if (CI.capturesVariableByCopy()) { 8500 CurBasePointers.push_back(CV); 8501 CurPointers.push_back(CV); 8502 if (!RI.getType()->isAnyPointerType()) { 8503 // We have to signal to the runtime captures passed by value that are 8504 // not pointers. 8505 CurMapTypes.push_back(OMP_MAP_LITERAL); 8506 CurSizes.push_back(CGF.Builder.CreateIntCast( 8507 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8508 } else { 8509 // Pointers are implicitly mapped with a zero size and no flags 8510 // (other than first map that is added for all implicit maps). 8511 CurMapTypes.push_back(OMP_MAP_NONE); 8512 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8513 } 8514 const VarDecl *VD = CI.getCapturedVar(); 8515 auto I = FirstPrivateDecls.find(VD); 8516 if (I != FirstPrivateDecls.end()) 8517 IsImplicit = I->getSecond(); 8518 } else { 8519 assert(CI.capturesVariable() && "Expected captured reference."); 8520 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8521 QualType ElementType = PtrTy->getPointeeType(); 8522 CurSizes.push_back(CGF.Builder.CreateIntCast( 8523 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8524 // The default map type for a scalar/complex type is 'to' because by 8525 // default the value doesn't have to be retrieved. For an aggregate 8526 // type, the default is 'tofrom'. 8527 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8528 const VarDecl *VD = CI.getCapturedVar(); 8529 auto I = FirstPrivateDecls.find(VD); 8530 if (I != FirstPrivateDecls.end() && 8531 VD->getType().isConstant(CGF.getContext())) { 8532 llvm::Constant *Addr = 8533 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8534 // Copy the value of the original variable to the new global copy. 8535 CGF.Builder.CreateMemCpy( 8536 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 8537 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8538 CurSizes.back(), /*IsVolatile=*/false); 8539 // Use new global variable as the base pointers. 8540 CurBasePointers.push_back(Addr); 8541 CurPointers.push_back(Addr); 8542 } else { 8543 CurBasePointers.push_back(CV); 8544 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8545 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8546 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8547 AlignmentSource::Decl)); 8548 CurPointers.push_back(PtrAddr.getPointer()); 8549 } else { 8550 CurPointers.push_back(CV); 8551 } 8552 } 8553 if (I != FirstPrivateDecls.end()) 8554 IsImplicit = I->getSecond(); 8555 } 8556 // Every default map produces a single argument which is a target parameter. 8557 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8558 8559 // Add flag stating this is an implicit map. 8560 if (IsImplicit) 8561 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8562 } 8563 }; 8564 } // anonymous namespace 8565 8566 /// Emit the arrays used to pass the captures and map information to the 8567 /// offloading runtime library. If there is no map or capture information, 8568 /// return nullptr by reference. 8569 static void 8570 emitOffloadingArrays(CodeGenFunction &CGF, 8571 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8572 MappableExprsHandler::MapValuesArrayTy &Pointers, 8573 MappableExprsHandler::MapValuesArrayTy &Sizes, 8574 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8575 CGOpenMPRuntime::TargetDataInfo &Info) { 8576 CodeGenModule &CGM = CGF.CGM; 8577 ASTContext &Ctx = CGF.getContext(); 8578 8579 // Reset the array information. 8580 Info.clearArrayInfo(); 8581 Info.NumberOfPtrs = BasePointers.size(); 8582 8583 if (Info.NumberOfPtrs) { 8584 // Detect if we have any capture size requiring runtime evaluation of the 8585 // size so that a constant array could be eventually used. 8586 bool hasRuntimeEvaluationCaptureSize = false; 8587 for (llvm::Value *S : Sizes) 8588 if (!isa<llvm::Constant>(S)) { 8589 hasRuntimeEvaluationCaptureSize = true; 8590 break; 8591 } 8592 8593 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8594 QualType PointerArrayType = Ctx.getConstantArrayType( 8595 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8596 /*IndexTypeQuals=*/0); 8597 8598 Info.BasePointersArray = 8599 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8600 Info.PointersArray = 8601 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8602 8603 // If we don't have any VLA types or other types that require runtime 8604 // evaluation, we can use a constant array for the map sizes, otherwise we 8605 // need to fill up the arrays as we do for the pointers. 8606 QualType Int64Ty = 8607 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8608 if (hasRuntimeEvaluationCaptureSize) { 8609 QualType SizeArrayType = Ctx.getConstantArrayType( 8610 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8611 /*IndexTypeQuals=*/0); 8612 Info.SizesArray = 8613 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8614 } else { 8615 // We expect all the sizes to be constant, so we collect them to create 8616 // a constant array. 8617 SmallVector<llvm::Constant *, 16> ConstSizes; 8618 for (llvm::Value *S : Sizes) 8619 ConstSizes.push_back(cast<llvm::Constant>(S)); 8620 8621 auto *SizesArrayInit = llvm::ConstantArray::get( 8622 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8623 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8624 auto *SizesArrayGbl = new llvm::GlobalVariable( 8625 CGM.getModule(), SizesArrayInit->getType(), 8626 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8627 SizesArrayInit, Name); 8628 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8629 Info.SizesArray = SizesArrayGbl; 8630 } 8631 8632 // The map types are always constant so we don't need to generate code to 8633 // fill arrays. Instead, we create an array constant. 8634 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8635 llvm::copy(MapTypes, Mapping.begin()); 8636 llvm::Constant *MapTypesArrayInit = 8637 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8638 std::string MaptypesName = 8639 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8640 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8641 CGM.getModule(), MapTypesArrayInit->getType(), 8642 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8643 MapTypesArrayInit, MaptypesName); 8644 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8645 Info.MapTypesArray = MapTypesArrayGbl; 8646 8647 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8648 llvm::Value *BPVal = *BasePointers[I]; 8649 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8650 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8651 Info.BasePointersArray, 0, I); 8652 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8653 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8654 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8655 CGF.Builder.CreateStore(BPVal, BPAddr); 8656 8657 if (Info.requiresDevicePointerInfo()) 8658 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8659 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8660 8661 llvm::Value *PVal = Pointers[I]; 8662 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8663 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8664 Info.PointersArray, 0, I); 8665 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8666 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8667 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8668 CGF.Builder.CreateStore(PVal, PAddr); 8669 8670 if (hasRuntimeEvaluationCaptureSize) { 8671 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8672 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8673 Info.SizesArray, 8674 /*Idx0=*/0, 8675 /*Idx1=*/I); 8676 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8677 CGF.Builder.CreateStore( 8678 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8679 SAddr); 8680 } 8681 } 8682 } 8683 } 8684 8685 /// Emit the arguments to be passed to the runtime library based on the 8686 /// arrays of pointers, sizes and map types. 8687 static void emitOffloadingArraysArgument( 8688 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8689 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8690 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8691 CodeGenModule &CGM = CGF.CGM; 8692 if (Info.NumberOfPtrs) { 8693 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8694 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8695 Info.BasePointersArray, 8696 /*Idx0=*/0, /*Idx1=*/0); 8697 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8698 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8699 Info.PointersArray, 8700 /*Idx0=*/0, 8701 /*Idx1=*/0); 8702 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8703 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8704 /*Idx0=*/0, /*Idx1=*/0); 8705 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8706 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8707 Info.MapTypesArray, 8708 /*Idx0=*/0, 8709 /*Idx1=*/0); 8710 } else { 8711 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8712 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8713 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8714 MapTypesArrayArg = 8715 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8716 } 8717 } 8718 8719 /// Check for inner distribute directive. 8720 static const OMPExecutableDirective * 8721 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8722 const auto *CS = D.getInnermostCapturedStmt(); 8723 const auto *Body = 8724 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8725 const Stmt *ChildStmt = 8726 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8727 8728 if (const auto *NestedDir = 8729 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8730 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8731 switch (D.getDirectiveKind()) { 8732 case OMPD_target: 8733 if (isOpenMPDistributeDirective(DKind)) 8734 return NestedDir; 8735 if (DKind == OMPD_teams) { 8736 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8737 /*IgnoreCaptured=*/true); 8738 if (!Body) 8739 return nullptr; 8740 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8741 if (const auto *NND = 8742 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8743 DKind = NND->getDirectiveKind(); 8744 if (isOpenMPDistributeDirective(DKind)) 8745 return NND; 8746 } 8747 } 8748 return nullptr; 8749 case OMPD_target_teams: 8750 if (isOpenMPDistributeDirective(DKind)) 8751 return NestedDir; 8752 return nullptr; 8753 case OMPD_target_parallel: 8754 case OMPD_target_simd: 8755 case OMPD_target_parallel_for: 8756 case OMPD_target_parallel_for_simd: 8757 return nullptr; 8758 case OMPD_target_teams_distribute: 8759 case OMPD_target_teams_distribute_simd: 8760 case OMPD_target_teams_distribute_parallel_for: 8761 case OMPD_target_teams_distribute_parallel_for_simd: 8762 case OMPD_parallel: 8763 case OMPD_for: 8764 case OMPD_parallel_for: 8765 case OMPD_parallel_sections: 8766 case OMPD_for_simd: 8767 case OMPD_parallel_for_simd: 8768 case OMPD_cancel: 8769 case OMPD_cancellation_point: 8770 case OMPD_ordered: 8771 case OMPD_threadprivate: 8772 case OMPD_allocate: 8773 case OMPD_task: 8774 case OMPD_simd: 8775 case OMPD_sections: 8776 case OMPD_section: 8777 case OMPD_single: 8778 case OMPD_master: 8779 case OMPD_critical: 8780 case OMPD_taskyield: 8781 case OMPD_barrier: 8782 case OMPD_taskwait: 8783 case OMPD_taskgroup: 8784 case OMPD_atomic: 8785 case OMPD_flush: 8786 case OMPD_teams: 8787 case OMPD_target_data: 8788 case OMPD_target_exit_data: 8789 case OMPD_target_enter_data: 8790 case OMPD_distribute: 8791 case OMPD_distribute_simd: 8792 case OMPD_distribute_parallel_for: 8793 case OMPD_distribute_parallel_for_simd: 8794 case OMPD_teams_distribute: 8795 case OMPD_teams_distribute_simd: 8796 case OMPD_teams_distribute_parallel_for: 8797 case OMPD_teams_distribute_parallel_for_simd: 8798 case OMPD_target_update: 8799 case OMPD_declare_simd: 8800 case OMPD_declare_variant: 8801 case OMPD_declare_target: 8802 case OMPD_end_declare_target: 8803 case OMPD_declare_reduction: 8804 case OMPD_declare_mapper: 8805 case OMPD_taskloop: 8806 case OMPD_taskloop_simd: 8807 case OMPD_master_taskloop: 8808 case OMPD_master_taskloop_simd: 8809 case OMPD_parallel_master_taskloop: 8810 case OMPD_parallel_master_taskloop_simd: 8811 case OMPD_requires: 8812 case OMPD_unknown: 8813 llvm_unreachable("Unexpected directive."); 8814 } 8815 } 8816 8817 return nullptr; 8818 } 8819 8820 /// Emit the user-defined mapper function. The code generation follows the 8821 /// pattern in the example below. 8822 /// \code 8823 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8824 /// void *base, void *begin, 8825 /// int64_t size, int64_t type) { 8826 /// // Allocate space for an array section first. 8827 /// if (size > 1 && !maptype.IsDelete) 8828 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8829 /// size*sizeof(Ty), clearToFrom(type)); 8830 /// // Map members. 8831 /// for (unsigned i = 0; i < size; i++) { 8832 /// // For each component specified by this mapper: 8833 /// for (auto c : all_components) { 8834 /// if (c.hasMapper()) 8835 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8836 /// c.arg_type); 8837 /// else 8838 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8839 /// c.arg_begin, c.arg_size, c.arg_type); 8840 /// } 8841 /// } 8842 /// // Delete the array section. 8843 /// if (size > 1 && maptype.IsDelete) 8844 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8845 /// size*sizeof(Ty), clearToFrom(type)); 8846 /// } 8847 /// \endcode 8848 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8849 CodeGenFunction *CGF) { 8850 if (UDMMap.count(D) > 0) 8851 return; 8852 ASTContext &C = CGM.getContext(); 8853 QualType Ty = D->getType(); 8854 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8855 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8856 auto *MapperVarDecl = 8857 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8858 SourceLocation Loc = D->getLocation(); 8859 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8860 8861 // Prepare mapper function arguments and attributes. 8862 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8863 C.VoidPtrTy, ImplicitParamDecl::Other); 8864 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8865 ImplicitParamDecl::Other); 8866 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8867 C.VoidPtrTy, ImplicitParamDecl::Other); 8868 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8869 ImplicitParamDecl::Other); 8870 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8871 ImplicitParamDecl::Other); 8872 FunctionArgList Args; 8873 Args.push_back(&HandleArg); 8874 Args.push_back(&BaseArg); 8875 Args.push_back(&BeginArg); 8876 Args.push_back(&SizeArg); 8877 Args.push_back(&TypeArg); 8878 const CGFunctionInfo &FnInfo = 8879 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8880 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8881 SmallString<64> TyStr; 8882 llvm::raw_svector_ostream Out(TyStr); 8883 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 8884 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 8885 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 8886 Name, &CGM.getModule()); 8887 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 8888 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 8889 // Start the mapper function code generation. 8890 CodeGenFunction MapperCGF(CGM); 8891 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 8892 // Compute the starting and end addreses of array elements. 8893 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 8894 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 8895 C.getPointerType(Int64Ty), Loc); 8896 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 8897 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 8898 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 8899 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 8900 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 8901 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 8902 C.getPointerType(Int64Ty), Loc); 8903 // Prepare common arguments for array initiation and deletion. 8904 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 8905 MapperCGF.GetAddrOfLocalVar(&HandleArg), 8906 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8907 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 8908 MapperCGF.GetAddrOfLocalVar(&BaseArg), 8909 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8910 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 8911 MapperCGF.GetAddrOfLocalVar(&BeginArg), 8912 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8913 8914 // Emit array initiation if this is an array section and \p MapType indicates 8915 // that memory allocation is required. 8916 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 8917 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8918 ElementSize, HeadBB, /*IsInit=*/true); 8919 8920 // Emit a for loop to iterate through SizeArg of elements and map all of them. 8921 8922 // Emit the loop header block. 8923 MapperCGF.EmitBlock(HeadBB); 8924 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 8925 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 8926 // Evaluate whether the initial condition is satisfied. 8927 llvm::Value *IsEmpty = 8928 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 8929 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 8930 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 8931 8932 // Emit the loop body block. 8933 MapperCGF.EmitBlock(BodyBB); 8934 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 8935 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 8936 PtrPHI->addIncoming(PtrBegin, EntryBB); 8937 Address PtrCurrent = 8938 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 8939 .getAlignment() 8940 .alignmentOfArrayElement(ElementSize)); 8941 // Privatize the declared variable of mapper to be the current array element. 8942 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 8943 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 8944 return MapperCGF 8945 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 8946 .getAddress(MapperCGF); 8947 }); 8948 (void)Scope.Privatize(); 8949 8950 // Get map clause information. Fill up the arrays with all mapped variables. 8951 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 8952 MappableExprsHandler::MapValuesArrayTy Pointers; 8953 MappableExprsHandler::MapValuesArrayTy Sizes; 8954 MappableExprsHandler::MapFlagsArrayTy MapTypes; 8955 MappableExprsHandler MEHandler(*D, MapperCGF); 8956 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 8957 8958 // Call the runtime API __tgt_mapper_num_components to get the number of 8959 // pre-existing components. 8960 llvm::Value *OffloadingArgs[] = {Handle}; 8961 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 8962 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 8963 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 8964 PreviousSize, 8965 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 8966 8967 // Fill up the runtime mapper handle for all components. 8968 for (unsigned I = 0; I < BasePointers.size(); ++I) { 8969 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 8970 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8971 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 8972 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8973 llvm::Value *CurSizeArg = Sizes[I]; 8974 8975 // Extract the MEMBER_OF field from the map type. 8976 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 8977 MapperCGF.EmitBlock(MemberBB); 8978 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 8979 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 8980 OriMapType, 8981 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 8982 llvm::BasicBlock *MemberCombineBB = 8983 MapperCGF.createBasicBlock("omp.member.combine"); 8984 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 8985 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 8986 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 8987 // Add the number of pre-existing components to the MEMBER_OF field if it 8988 // is valid. 8989 MapperCGF.EmitBlock(MemberCombineBB); 8990 llvm::Value *CombinedMember = 8991 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 8992 // Do nothing if it is not a member of previous components. 8993 MapperCGF.EmitBlock(TypeBB); 8994 llvm::PHINode *MemberMapType = 8995 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 8996 MemberMapType->addIncoming(OriMapType, MemberBB); 8997 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 8998 8999 // Combine the map type inherited from user-defined mapper with that 9000 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9001 // bits of the \a MapType, which is the input argument of the mapper 9002 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9003 // bits of MemberMapType. 9004 // [OpenMP 5.0], 1.2.6. map-type decay. 9005 // | alloc | to | from | tofrom | release | delete 9006 // ---------------------------------------------------------- 9007 // alloc | alloc | alloc | alloc | alloc | release | delete 9008 // to | alloc | to | alloc | to | release | delete 9009 // from | alloc | alloc | from | from | release | delete 9010 // tofrom | alloc | to | from | tofrom | release | delete 9011 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9012 MapType, 9013 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9014 MappableExprsHandler::OMP_MAP_FROM)); 9015 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9016 llvm::BasicBlock *AllocElseBB = 9017 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9018 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9019 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9020 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9021 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9022 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9023 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9024 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9025 MapperCGF.EmitBlock(AllocBB); 9026 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9027 MemberMapType, 9028 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9029 MappableExprsHandler::OMP_MAP_FROM))); 9030 MapperCGF.Builder.CreateBr(EndBB); 9031 MapperCGF.EmitBlock(AllocElseBB); 9032 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9033 LeftToFrom, 9034 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9035 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9036 // In case of to, clear OMP_MAP_FROM. 9037 MapperCGF.EmitBlock(ToBB); 9038 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9039 MemberMapType, 9040 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9041 MapperCGF.Builder.CreateBr(EndBB); 9042 MapperCGF.EmitBlock(ToElseBB); 9043 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9044 LeftToFrom, 9045 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9046 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9047 // In case of from, clear OMP_MAP_TO. 9048 MapperCGF.EmitBlock(FromBB); 9049 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9050 MemberMapType, 9051 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9052 // In case of tofrom, do nothing. 9053 MapperCGF.EmitBlock(EndBB); 9054 llvm::PHINode *CurMapType = 9055 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9056 CurMapType->addIncoming(AllocMapType, AllocBB); 9057 CurMapType->addIncoming(ToMapType, ToBB); 9058 CurMapType->addIncoming(FromMapType, FromBB); 9059 CurMapType->addIncoming(MemberMapType, ToElseBB); 9060 9061 // TODO: call the corresponding mapper function if a user-defined mapper is 9062 // associated with this map clause. 9063 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9064 // data structure. 9065 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9066 CurSizeArg, CurMapType}; 9067 MapperCGF.EmitRuntimeCall( 9068 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9069 OffloadingArgs); 9070 } 9071 9072 // Update the pointer to point to the next element that needs to be mapped, 9073 // and check whether we have mapped all elements. 9074 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9075 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9076 PtrPHI->addIncoming(PtrNext, BodyBB); 9077 llvm::Value *IsDone = 9078 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9079 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9080 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9081 9082 MapperCGF.EmitBlock(ExitBB); 9083 // Emit array deletion if this is an array section and \p MapType indicates 9084 // that deletion is required. 9085 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9086 ElementSize, DoneBB, /*IsInit=*/false); 9087 9088 // Emit the function exit block. 9089 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9090 MapperCGF.FinishFunction(); 9091 UDMMap.try_emplace(D, Fn); 9092 if (CGF) { 9093 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9094 Decls.second.push_back(D); 9095 } 9096 } 9097 9098 /// Emit the array initialization or deletion portion for user-defined mapper 9099 /// code generation. First, it evaluates whether an array section is mapped and 9100 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9101 /// true, and \a MapType indicates to not delete this array, array 9102 /// initialization code is generated. If \a IsInit is false, and \a MapType 9103 /// indicates to not this array, array deletion code is generated. 9104 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9105 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9106 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9107 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9108 StringRef Prefix = IsInit ? ".init" : ".del"; 9109 9110 // Evaluate if this is an array section. 9111 llvm::BasicBlock *IsDeleteBB = 9112 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete"); 9113 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix); 9114 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9115 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9116 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9117 9118 // Evaluate if we are going to delete this section. 9119 MapperCGF.EmitBlock(IsDeleteBB); 9120 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9121 MapType, 9122 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9123 llvm::Value *DeleteCond; 9124 if (IsInit) { 9125 DeleteCond = MapperCGF.Builder.CreateIsNull( 9126 DeleteBit, "omp.array" + Prefix + ".delete"); 9127 } else { 9128 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9129 DeleteBit, "omp.array" + Prefix + ".delete"); 9130 } 9131 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9132 9133 MapperCGF.EmitBlock(BodyBB); 9134 // Get the array size by multiplying element size and element number (i.e., \p 9135 // Size). 9136 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9137 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9138 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9139 // memory allocation/deletion purpose only. 9140 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9141 MapType, 9142 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9143 MappableExprsHandler::OMP_MAP_FROM))); 9144 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9145 // data structure. 9146 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9147 MapperCGF.EmitRuntimeCall( 9148 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9149 } 9150 9151 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9152 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9153 llvm::Value *DeviceID, 9154 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9155 const OMPLoopDirective &D)> 9156 SizeEmitter) { 9157 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9158 const OMPExecutableDirective *TD = &D; 9159 // Get nested teams distribute kind directive, if any. 9160 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9161 TD = getNestedDistributeDirective(CGM.getContext(), D); 9162 if (!TD) 9163 return; 9164 const auto *LD = cast<OMPLoopDirective>(TD); 9165 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9166 PrePostActionTy &) { 9167 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9168 llvm::Value *Args[] = {DeviceID, NumIterations}; 9169 CGF.EmitRuntimeCall( 9170 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9171 } 9172 }; 9173 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9174 } 9175 9176 void CGOpenMPRuntime::emitTargetCall( 9177 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9178 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9179 const Expr *Device, 9180 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9181 const OMPLoopDirective &D)> 9182 SizeEmitter) { 9183 if (!CGF.HaveInsertPoint()) 9184 return; 9185 9186 assert(OutlinedFn && "Invalid outlined function!"); 9187 9188 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9189 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9190 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9191 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9192 PrePostActionTy &) { 9193 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9194 }; 9195 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9196 9197 CodeGenFunction::OMPTargetDataInfo InputInfo; 9198 llvm::Value *MapTypesArray = nullptr; 9199 // Fill up the pointer arrays and transfer execution to the device. 9200 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9201 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9202 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9203 // On top of the arrays that were filled up, the target offloading call 9204 // takes as arguments the device id as well as the host pointer. The host 9205 // pointer is used by the runtime library to identify the current target 9206 // region, so it only has to be unique and not necessarily point to 9207 // anything. It could be the pointer to the outlined function that 9208 // implements the target region, but we aren't using that so that the 9209 // compiler doesn't need to keep that, and could therefore inline the host 9210 // function if proven worthwhile during optimization. 9211 9212 // From this point on, we need to have an ID of the target region defined. 9213 assert(OutlinedFnID && "Invalid outlined function ID!"); 9214 9215 // Emit device ID if any. 9216 llvm::Value *DeviceID; 9217 if (Device) { 9218 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9219 CGF.Int64Ty, /*isSigned=*/true); 9220 } else { 9221 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9222 } 9223 9224 // Emit the number of elements in the offloading arrays. 9225 llvm::Value *PointerNum = 9226 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9227 9228 // Return value of the runtime offloading call. 9229 llvm::Value *Return; 9230 9231 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9232 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9233 9234 // Emit tripcount for the target loop-based directive. 9235 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9236 9237 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9238 // The target region is an outlined function launched by the runtime 9239 // via calls __tgt_target() or __tgt_target_teams(). 9240 // 9241 // __tgt_target() launches a target region with one team and one thread, 9242 // executing a serial region. This master thread may in turn launch 9243 // more threads within its team upon encountering a parallel region, 9244 // however, no additional teams can be launched on the device. 9245 // 9246 // __tgt_target_teams() launches a target region with one or more teams, 9247 // each with one or more threads. This call is required for target 9248 // constructs such as: 9249 // 'target teams' 9250 // 'target' / 'teams' 9251 // 'target teams distribute parallel for' 9252 // 'target parallel' 9253 // and so on. 9254 // 9255 // Note that on the host and CPU targets, the runtime implementation of 9256 // these calls simply call the outlined function without forking threads. 9257 // The outlined functions themselves have runtime calls to 9258 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9259 // the compiler in emitTeamsCall() and emitParallelCall(). 9260 // 9261 // In contrast, on the NVPTX target, the implementation of 9262 // __tgt_target_teams() launches a GPU kernel with the requested number 9263 // of teams and threads so no additional calls to the runtime are required. 9264 if (NumTeams) { 9265 // If we have NumTeams defined this means that we have an enclosed teams 9266 // region. Therefore we also expect to have NumThreads defined. These two 9267 // values should be defined in the presence of a teams directive, 9268 // regardless of having any clauses associated. If the user is using teams 9269 // but no clauses, these two values will be the default that should be 9270 // passed to the runtime library - a 32-bit integer with the value zero. 9271 assert(NumThreads && "Thread limit expression should be available along " 9272 "with number of teams."); 9273 llvm::Value *OffloadingArgs[] = {DeviceID, 9274 OutlinedFnID, 9275 PointerNum, 9276 InputInfo.BasePointersArray.getPointer(), 9277 InputInfo.PointersArray.getPointer(), 9278 InputInfo.SizesArray.getPointer(), 9279 MapTypesArray, 9280 NumTeams, 9281 NumThreads}; 9282 Return = CGF.EmitRuntimeCall( 9283 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9284 : OMPRTL__tgt_target_teams), 9285 OffloadingArgs); 9286 } else { 9287 llvm::Value *OffloadingArgs[] = {DeviceID, 9288 OutlinedFnID, 9289 PointerNum, 9290 InputInfo.BasePointersArray.getPointer(), 9291 InputInfo.PointersArray.getPointer(), 9292 InputInfo.SizesArray.getPointer(), 9293 MapTypesArray}; 9294 Return = CGF.EmitRuntimeCall( 9295 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9296 : OMPRTL__tgt_target), 9297 OffloadingArgs); 9298 } 9299 9300 // Check the error code and execute the host version if required. 9301 llvm::BasicBlock *OffloadFailedBlock = 9302 CGF.createBasicBlock("omp_offload.failed"); 9303 llvm::BasicBlock *OffloadContBlock = 9304 CGF.createBasicBlock("omp_offload.cont"); 9305 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9306 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9307 9308 CGF.EmitBlock(OffloadFailedBlock); 9309 if (RequiresOuterTask) { 9310 CapturedVars.clear(); 9311 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9312 } 9313 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9314 CGF.EmitBranch(OffloadContBlock); 9315 9316 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9317 }; 9318 9319 // Notify that the host version must be executed. 9320 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9321 RequiresOuterTask](CodeGenFunction &CGF, 9322 PrePostActionTy &) { 9323 if (RequiresOuterTask) { 9324 CapturedVars.clear(); 9325 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9326 } 9327 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9328 }; 9329 9330 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9331 &CapturedVars, RequiresOuterTask, 9332 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9333 // Fill up the arrays with all the captured variables. 9334 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9335 MappableExprsHandler::MapValuesArrayTy Pointers; 9336 MappableExprsHandler::MapValuesArrayTy Sizes; 9337 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9338 9339 // Get mappable expression information. 9340 MappableExprsHandler MEHandler(D, CGF); 9341 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9342 9343 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9344 auto CV = CapturedVars.begin(); 9345 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9346 CE = CS.capture_end(); 9347 CI != CE; ++CI, ++RI, ++CV) { 9348 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9349 MappableExprsHandler::MapValuesArrayTy CurPointers; 9350 MappableExprsHandler::MapValuesArrayTy CurSizes; 9351 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9352 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9353 9354 // VLA sizes are passed to the outlined region by copy and do not have map 9355 // information associated. 9356 if (CI->capturesVariableArrayType()) { 9357 CurBasePointers.push_back(*CV); 9358 CurPointers.push_back(*CV); 9359 CurSizes.push_back(CGF.Builder.CreateIntCast( 9360 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9361 // Copy to the device as an argument. No need to retrieve it. 9362 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9363 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9364 MappableExprsHandler::OMP_MAP_IMPLICIT); 9365 } else { 9366 // If we have any information in the map clause, we use it, otherwise we 9367 // just do a default mapping. 9368 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9369 CurSizes, CurMapTypes, PartialStruct); 9370 if (CurBasePointers.empty()) 9371 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9372 CurPointers, CurSizes, CurMapTypes); 9373 // Generate correct mapping for variables captured by reference in 9374 // lambdas. 9375 if (CI->capturesVariable()) 9376 MEHandler.generateInfoForLambdaCaptures( 9377 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9378 CurMapTypes, LambdaPointers); 9379 } 9380 // We expect to have at least an element of information for this capture. 9381 assert(!CurBasePointers.empty() && 9382 "Non-existing map pointer for capture!"); 9383 assert(CurBasePointers.size() == CurPointers.size() && 9384 CurBasePointers.size() == CurSizes.size() && 9385 CurBasePointers.size() == CurMapTypes.size() && 9386 "Inconsistent map information sizes!"); 9387 9388 // If there is an entry in PartialStruct it means we have a struct with 9389 // individual members mapped. Emit an extra combined entry. 9390 if (PartialStruct.Base.isValid()) 9391 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9392 CurMapTypes, PartialStruct); 9393 9394 // We need to append the results of this capture to what we already have. 9395 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9396 Pointers.append(CurPointers.begin(), CurPointers.end()); 9397 Sizes.append(CurSizes.begin(), CurSizes.end()); 9398 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9399 } 9400 // Adjust MEMBER_OF flags for the lambdas captures. 9401 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9402 Pointers, MapTypes); 9403 // Map other list items in the map clause which are not captured variables 9404 // but "declare target link" global variables. 9405 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9406 MapTypes); 9407 9408 TargetDataInfo Info; 9409 // Fill up the arrays and create the arguments. 9410 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9411 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9412 Info.PointersArray, Info.SizesArray, 9413 Info.MapTypesArray, Info); 9414 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9415 InputInfo.BasePointersArray = 9416 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9417 InputInfo.PointersArray = 9418 Address(Info.PointersArray, CGM.getPointerAlign()); 9419 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9420 MapTypesArray = Info.MapTypesArray; 9421 if (RequiresOuterTask) 9422 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9423 else 9424 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9425 }; 9426 9427 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9428 CodeGenFunction &CGF, PrePostActionTy &) { 9429 if (RequiresOuterTask) { 9430 CodeGenFunction::OMPTargetDataInfo InputInfo; 9431 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9432 } else { 9433 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9434 } 9435 }; 9436 9437 // If we have a target function ID it means that we need to support 9438 // offloading, otherwise, just execute on the host. We need to execute on host 9439 // regardless of the conditional in the if clause if, e.g., the user do not 9440 // specify target triples. 9441 if (OutlinedFnID) { 9442 if (IfCond) { 9443 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9444 } else { 9445 RegionCodeGenTy ThenRCG(TargetThenGen); 9446 ThenRCG(CGF); 9447 } 9448 } else { 9449 RegionCodeGenTy ElseRCG(TargetElseGen); 9450 ElseRCG(CGF); 9451 } 9452 } 9453 9454 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9455 StringRef ParentName) { 9456 if (!S) 9457 return; 9458 9459 // Codegen OMP target directives that offload compute to the device. 9460 bool RequiresDeviceCodegen = 9461 isa<OMPExecutableDirective>(S) && 9462 isOpenMPTargetExecutionDirective( 9463 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9464 9465 if (RequiresDeviceCodegen) { 9466 const auto &E = *cast<OMPExecutableDirective>(S); 9467 unsigned DeviceID; 9468 unsigned FileID; 9469 unsigned Line; 9470 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9471 FileID, Line); 9472 9473 // Is this a target region that should not be emitted as an entry point? If 9474 // so just signal we are done with this target region. 9475 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9476 ParentName, Line)) 9477 return; 9478 9479 switch (E.getDirectiveKind()) { 9480 case OMPD_target: 9481 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9482 cast<OMPTargetDirective>(E)); 9483 break; 9484 case OMPD_target_parallel: 9485 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9486 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9487 break; 9488 case OMPD_target_teams: 9489 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9490 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9491 break; 9492 case OMPD_target_teams_distribute: 9493 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9494 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9495 break; 9496 case OMPD_target_teams_distribute_simd: 9497 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9498 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9499 break; 9500 case OMPD_target_parallel_for: 9501 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9502 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9503 break; 9504 case OMPD_target_parallel_for_simd: 9505 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9506 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9507 break; 9508 case OMPD_target_simd: 9509 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9510 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9511 break; 9512 case OMPD_target_teams_distribute_parallel_for: 9513 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9514 CGM, ParentName, 9515 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9516 break; 9517 case OMPD_target_teams_distribute_parallel_for_simd: 9518 CodeGenFunction:: 9519 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9520 CGM, ParentName, 9521 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9522 break; 9523 case OMPD_parallel: 9524 case OMPD_for: 9525 case OMPD_parallel_for: 9526 case OMPD_parallel_sections: 9527 case OMPD_for_simd: 9528 case OMPD_parallel_for_simd: 9529 case OMPD_cancel: 9530 case OMPD_cancellation_point: 9531 case OMPD_ordered: 9532 case OMPD_threadprivate: 9533 case OMPD_allocate: 9534 case OMPD_task: 9535 case OMPD_simd: 9536 case OMPD_sections: 9537 case OMPD_section: 9538 case OMPD_single: 9539 case OMPD_master: 9540 case OMPD_critical: 9541 case OMPD_taskyield: 9542 case OMPD_barrier: 9543 case OMPD_taskwait: 9544 case OMPD_taskgroup: 9545 case OMPD_atomic: 9546 case OMPD_flush: 9547 case OMPD_teams: 9548 case OMPD_target_data: 9549 case OMPD_target_exit_data: 9550 case OMPD_target_enter_data: 9551 case OMPD_distribute: 9552 case OMPD_distribute_simd: 9553 case OMPD_distribute_parallel_for: 9554 case OMPD_distribute_parallel_for_simd: 9555 case OMPD_teams_distribute: 9556 case OMPD_teams_distribute_simd: 9557 case OMPD_teams_distribute_parallel_for: 9558 case OMPD_teams_distribute_parallel_for_simd: 9559 case OMPD_target_update: 9560 case OMPD_declare_simd: 9561 case OMPD_declare_variant: 9562 case OMPD_declare_target: 9563 case OMPD_end_declare_target: 9564 case OMPD_declare_reduction: 9565 case OMPD_declare_mapper: 9566 case OMPD_taskloop: 9567 case OMPD_taskloop_simd: 9568 case OMPD_master_taskloop: 9569 case OMPD_master_taskloop_simd: 9570 case OMPD_parallel_master_taskloop: 9571 case OMPD_parallel_master_taskloop_simd: 9572 case OMPD_requires: 9573 case OMPD_unknown: 9574 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9575 } 9576 return; 9577 } 9578 9579 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9580 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9581 return; 9582 9583 scanForTargetRegionsFunctions( 9584 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9585 return; 9586 } 9587 9588 // If this is a lambda function, look into its body. 9589 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9590 S = L->getBody(); 9591 9592 // Keep looking for target regions recursively. 9593 for (const Stmt *II : S->children()) 9594 scanForTargetRegionsFunctions(II, ParentName); 9595 } 9596 9597 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9598 // If emitting code for the host, we do not process FD here. Instead we do 9599 // the normal code generation. 9600 if (!CGM.getLangOpts().OpenMPIsDevice) { 9601 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9602 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9603 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9604 // Do not emit device_type(nohost) functions for the host. 9605 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9606 return true; 9607 } 9608 return false; 9609 } 9610 9611 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9612 StringRef Name = CGM.getMangledName(GD); 9613 // Try to detect target regions in the function. 9614 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9615 scanForTargetRegionsFunctions(FD->getBody(), Name); 9616 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9617 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9618 // Do not emit device_type(nohost) functions for the host. 9619 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9620 return true; 9621 } 9622 9623 // Do not to emit function if it is not marked as declare target. 9624 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9625 AlreadyEmittedTargetFunctions.count(Name) == 0; 9626 } 9627 9628 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9629 if (!CGM.getLangOpts().OpenMPIsDevice) 9630 return false; 9631 9632 // Check if there are Ctors/Dtors in this declaration and look for target 9633 // regions in it. We use the complete variant to produce the kernel name 9634 // mangling. 9635 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9636 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9637 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9638 StringRef ParentName = 9639 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9640 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9641 } 9642 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9643 StringRef ParentName = 9644 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9645 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9646 } 9647 } 9648 9649 // Do not to emit variable if it is not marked as declare target. 9650 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9651 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9652 cast<VarDecl>(GD.getDecl())); 9653 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9654 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9655 HasRequiresUnifiedSharedMemory)) { 9656 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9657 return true; 9658 } 9659 return false; 9660 } 9661 9662 llvm::Constant * 9663 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9664 const VarDecl *VD) { 9665 assert(VD->getType().isConstant(CGM.getContext()) && 9666 "Expected constant variable."); 9667 StringRef VarName; 9668 llvm::Constant *Addr; 9669 llvm::GlobalValue::LinkageTypes Linkage; 9670 QualType Ty = VD->getType(); 9671 SmallString<128> Buffer; 9672 { 9673 unsigned DeviceID; 9674 unsigned FileID; 9675 unsigned Line; 9676 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9677 FileID, Line); 9678 llvm::raw_svector_ostream OS(Buffer); 9679 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9680 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9681 VarName = OS.str(); 9682 } 9683 Linkage = llvm::GlobalValue::InternalLinkage; 9684 Addr = 9685 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9686 getDefaultFirstprivateAddressSpace()); 9687 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9688 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9689 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9690 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9691 VarName, Addr, VarSize, 9692 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9693 return Addr; 9694 } 9695 9696 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9697 llvm::Constant *Addr) { 9698 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9699 !CGM.getLangOpts().OpenMPIsDevice) 9700 return; 9701 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9702 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9703 if (!Res) { 9704 if (CGM.getLangOpts().OpenMPIsDevice) { 9705 // Register non-target variables being emitted in device code (debug info 9706 // may cause this). 9707 StringRef VarName = CGM.getMangledName(VD); 9708 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9709 } 9710 return; 9711 } 9712 // Register declare target variables. 9713 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9714 StringRef VarName; 9715 CharUnits VarSize; 9716 llvm::GlobalValue::LinkageTypes Linkage; 9717 9718 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9719 !HasRequiresUnifiedSharedMemory) { 9720 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9721 VarName = CGM.getMangledName(VD); 9722 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9723 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9724 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9725 } else { 9726 VarSize = CharUnits::Zero(); 9727 } 9728 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9729 // Temp solution to prevent optimizations of the internal variables. 9730 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9731 std::string RefName = getName({VarName, "ref"}); 9732 if (!CGM.GetGlobalValue(RefName)) { 9733 llvm::Constant *AddrRef = 9734 getOrCreateInternalVariable(Addr->getType(), RefName); 9735 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9736 GVAddrRef->setConstant(/*Val=*/true); 9737 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9738 GVAddrRef->setInitializer(Addr); 9739 CGM.addCompilerUsedGlobal(GVAddrRef); 9740 } 9741 } 9742 } else { 9743 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9744 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9745 HasRequiresUnifiedSharedMemory)) && 9746 "Declare target attribute must link or to with unified memory."); 9747 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9748 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9749 else 9750 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9751 9752 if (CGM.getLangOpts().OpenMPIsDevice) { 9753 VarName = Addr->getName(); 9754 Addr = nullptr; 9755 } else { 9756 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9757 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9758 } 9759 VarSize = CGM.getPointerSize(); 9760 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9761 } 9762 9763 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9764 VarName, Addr, VarSize, Flags, Linkage); 9765 } 9766 9767 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9768 if (isa<FunctionDecl>(GD.getDecl()) || 9769 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9770 return emitTargetFunctions(GD); 9771 9772 return emitTargetGlobalVariable(GD); 9773 } 9774 9775 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9776 for (const VarDecl *VD : DeferredGlobalVariables) { 9777 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9778 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9779 if (!Res) 9780 continue; 9781 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9782 !HasRequiresUnifiedSharedMemory) { 9783 CGM.EmitGlobal(VD); 9784 } else { 9785 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9786 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9787 HasRequiresUnifiedSharedMemory)) && 9788 "Expected link clause or to clause with unified memory."); 9789 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9790 } 9791 } 9792 } 9793 9794 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9795 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9796 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9797 " Expected target-based directive."); 9798 } 9799 9800 void CGOpenMPRuntime::checkArchForUnifiedAddressing( 9801 const OMPRequiresDecl *D) { 9802 for (const OMPClause *Clause : D->clauselists()) { 9803 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9804 HasRequiresUnifiedSharedMemory = true; 9805 break; 9806 } 9807 } 9808 } 9809 9810 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9811 LangAS &AS) { 9812 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9813 return false; 9814 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9815 switch(A->getAllocatorType()) { 9816 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9817 // Not supported, fallback to the default mem space. 9818 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9819 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9820 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9821 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9822 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9823 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9824 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9825 AS = LangAS::Default; 9826 return true; 9827 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9828 llvm_unreachable("Expected predefined allocator for the variables with the " 9829 "static storage."); 9830 } 9831 return false; 9832 } 9833 9834 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9835 return HasRequiresUnifiedSharedMemory; 9836 } 9837 9838 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9839 CodeGenModule &CGM) 9840 : CGM(CGM) { 9841 if (CGM.getLangOpts().OpenMPIsDevice) { 9842 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9843 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9844 } 9845 } 9846 9847 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9848 if (CGM.getLangOpts().OpenMPIsDevice) 9849 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9850 } 9851 9852 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9853 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9854 return true; 9855 9856 StringRef Name = CGM.getMangledName(GD); 9857 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9858 // Do not to emit function if it is marked as declare target as it was already 9859 // emitted. 9860 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9861 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) { 9862 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name))) 9863 return !F->isDeclaration(); 9864 return false; 9865 } 9866 return true; 9867 } 9868 9869 return !AlreadyEmittedTargetFunctions.insert(Name).second; 9870 } 9871 9872 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9873 // If we don't have entries or if we are emitting code for the device, we 9874 // don't need to do anything. 9875 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9876 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9877 (OffloadEntriesInfoManager.empty() && 9878 !HasEmittedDeclareTargetRegion && 9879 !HasEmittedTargetRegion)) 9880 return nullptr; 9881 9882 // Create and register the function that handles the requires directives. 9883 ASTContext &C = CGM.getContext(); 9884 9885 llvm::Function *RequiresRegFn; 9886 { 9887 CodeGenFunction CGF(CGM); 9888 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9889 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9890 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9891 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9892 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9893 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9894 // TODO: check for other requires clauses. 9895 // The requires directive takes effect only when a target region is 9896 // present in the compilation unit. Otherwise it is ignored and not 9897 // passed to the runtime. This avoids the runtime from throwing an error 9898 // for mismatching requires clauses across compilation units that don't 9899 // contain at least 1 target region. 9900 assert((HasEmittedTargetRegion || 9901 HasEmittedDeclareTargetRegion || 9902 !OffloadEntriesInfoManager.empty()) && 9903 "Target or declare target region expected."); 9904 if (HasRequiresUnifiedSharedMemory) 9905 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9906 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 9907 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9908 CGF.FinishFunction(); 9909 } 9910 return RequiresRegFn; 9911 } 9912 9913 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9914 const OMPExecutableDirective &D, 9915 SourceLocation Loc, 9916 llvm::Function *OutlinedFn, 9917 ArrayRef<llvm::Value *> CapturedVars) { 9918 if (!CGF.HaveInsertPoint()) 9919 return; 9920 9921 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9922 CodeGenFunction::RunCleanupsScope Scope(CGF); 9923 9924 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9925 llvm::Value *Args[] = { 9926 RTLoc, 9927 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9928 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9929 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9930 RealArgs.append(std::begin(Args), std::end(Args)); 9931 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9932 9933 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 9934 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9935 } 9936 9937 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9938 const Expr *NumTeams, 9939 const Expr *ThreadLimit, 9940 SourceLocation Loc) { 9941 if (!CGF.HaveInsertPoint()) 9942 return; 9943 9944 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9945 9946 llvm::Value *NumTeamsVal = 9947 NumTeams 9948 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9949 CGF.CGM.Int32Ty, /* isSigned = */ true) 9950 : CGF.Builder.getInt32(0); 9951 9952 llvm::Value *ThreadLimitVal = 9953 ThreadLimit 9954 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 9955 CGF.CGM.Int32Ty, /* isSigned = */ true) 9956 : CGF.Builder.getInt32(0); 9957 9958 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 9959 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 9960 ThreadLimitVal}; 9961 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 9962 PushNumTeamsArgs); 9963 } 9964 9965 void CGOpenMPRuntime::emitTargetDataCalls( 9966 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 9967 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 9968 if (!CGF.HaveInsertPoint()) 9969 return; 9970 9971 // Action used to replace the default codegen action and turn privatization 9972 // off. 9973 PrePostActionTy NoPrivAction; 9974 9975 // Generate the code for the opening of the data environment. Capture all the 9976 // arguments of the runtime call by reference because they are used in the 9977 // closing of the region. 9978 auto &&BeginThenGen = [this, &D, Device, &Info, 9979 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 9980 // Fill up the arrays with all the mapped variables. 9981 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9982 MappableExprsHandler::MapValuesArrayTy Pointers; 9983 MappableExprsHandler::MapValuesArrayTy Sizes; 9984 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9985 9986 // Get map clause information. 9987 MappableExprsHandler MCHandler(D, CGF); 9988 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 9989 9990 // Fill up the arrays and create the arguments. 9991 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9992 9993 llvm::Value *BasePointersArrayArg = nullptr; 9994 llvm::Value *PointersArrayArg = nullptr; 9995 llvm::Value *SizesArrayArg = nullptr; 9996 llvm::Value *MapTypesArrayArg = nullptr; 9997 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 9998 SizesArrayArg, MapTypesArrayArg, Info); 9999 10000 // Emit device ID if any. 10001 llvm::Value *DeviceID = nullptr; 10002 if (Device) { 10003 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10004 CGF.Int64Ty, /*isSigned=*/true); 10005 } else { 10006 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10007 } 10008 10009 // Emit the number of elements in the offloading arrays. 10010 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10011 10012 llvm::Value *OffloadingArgs[] = { 10013 DeviceID, PointerNum, BasePointersArrayArg, 10014 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10015 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 10016 OffloadingArgs); 10017 10018 // If device pointer privatization is required, emit the body of the region 10019 // here. It will have to be duplicated: with and without privatization. 10020 if (!Info.CaptureDeviceAddrMap.empty()) 10021 CodeGen(CGF); 10022 }; 10023 10024 // Generate code for the closing of the data region. 10025 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10026 PrePostActionTy &) { 10027 assert(Info.isValid() && "Invalid data environment closing arguments."); 10028 10029 llvm::Value *BasePointersArrayArg = nullptr; 10030 llvm::Value *PointersArrayArg = nullptr; 10031 llvm::Value *SizesArrayArg = nullptr; 10032 llvm::Value *MapTypesArrayArg = nullptr; 10033 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10034 SizesArrayArg, MapTypesArrayArg, Info); 10035 10036 // Emit device ID if any. 10037 llvm::Value *DeviceID = nullptr; 10038 if (Device) { 10039 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10040 CGF.Int64Ty, /*isSigned=*/true); 10041 } else { 10042 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10043 } 10044 10045 // Emit the number of elements in the offloading arrays. 10046 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10047 10048 llvm::Value *OffloadingArgs[] = { 10049 DeviceID, PointerNum, BasePointersArrayArg, 10050 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10051 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10052 OffloadingArgs); 10053 }; 10054 10055 // If we need device pointer privatization, we need to emit the body of the 10056 // region with no privatization in the 'else' branch of the conditional. 10057 // Otherwise, we don't have to do anything. 10058 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10059 PrePostActionTy &) { 10060 if (!Info.CaptureDeviceAddrMap.empty()) { 10061 CodeGen.setAction(NoPrivAction); 10062 CodeGen(CGF); 10063 } 10064 }; 10065 10066 // We don't have to do anything to close the region if the if clause evaluates 10067 // to false. 10068 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10069 10070 if (IfCond) { 10071 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10072 } else { 10073 RegionCodeGenTy RCG(BeginThenGen); 10074 RCG(CGF); 10075 } 10076 10077 // If we don't require privatization of device pointers, we emit the body in 10078 // between the runtime calls. This avoids duplicating the body code. 10079 if (Info.CaptureDeviceAddrMap.empty()) { 10080 CodeGen.setAction(NoPrivAction); 10081 CodeGen(CGF); 10082 } 10083 10084 if (IfCond) { 10085 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10086 } else { 10087 RegionCodeGenTy RCG(EndThenGen); 10088 RCG(CGF); 10089 } 10090 } 10091 10092 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10093 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10094 const Expr *Device) { 10095 if (!CGF.HaveInsertPoint()) 10096 return; 10097 10098 assert((isa<OMPTargetEnterDataDirective>(D) || 10099 isa<OMPTargetExitDataDirective>(D) || 10100 isa<OMPTargetUpdateDirective>(D)) && 10101 "Expecting either target enter, exit data, or update directives."); 10102 10103 CodeGenFunction::OMPTargetDataInfo InputInfo; 10104 llvm::Value *MapTypesArray = nullptr; 10105 // Generate the code for the opening of the data environment. 10106 auto &&ThenGen = [this, &D, Device, &InputInfo, 10107 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10108 // Emit device ID if any. 10109 llvm::Value *DeviceID = nullptr; 10110 if (Device) { 10111 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10112 CGF.Int64Ty, /*isSigned=*/true); 10113 } else { 10114 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10115 } 10116 10117 // Emit the number of elements in the offloading arrays. 10118 llvm::Constant *PointerNum = 10119 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10120 10121 llvm::Value *OffloadingArgs[] = {DeviceID, 10122 PointerNum, 10123 InputInfo.BasePointersArray.getPointer(), 10124 InputInfo.PointersArray.getPointer(), 10125 InputInfo.SizesArray.getPointer(), 10126 MapTypesArray}; 10127 10128 // Select the right runtime function call for each expected standalone 10129 // directive. 10130 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10131 OpenMPRTLFunction RTLFn; 10132 switch (D.getDirectiveKind()) { 10133 case OMPD_target_enter_data: 10134 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10135 : OMPRTL__tgt_target_data_begin; 10136 break; 10137 case OMPD_target_exit_data: 10138 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10139 : OMPRTL__tgt_target_data_end; 10140 break; 10141 case OMPD_target_update: 10142 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10143 : OMPRTL__tgt_target_data_update; 10144 break; 10145 case OMPD_parallel: 10146 case OMPD_for: 10147 case OMPD_parallel_for: 10148 case OMPD_parallel_sections: 10149 case OMPD_for_simd: 10150 case OMPD_parallel_for_simd: 10151 case OMPD_cancel: 10152 case OMPD_cancellation_point: 10153 case OMPD_ordered: 10154 case OMPD_threadprivate: 10155 case OMPD_allocate: 10156 case OMPD_task: 10157 case OMPD_simd: 10158 case OMPD_sections: 10159 case OMPD_section: 10160 case OMPD_single: 10161 case OMPD_master: 10162 case OMPD_critical: 10163 case OMPD_taskyield: 10164 case OMPD_barrier: 10165 case OMPD_taskwait: 10166 case OMPD_taskgroup: 10167 case OMPD_atomic: 10168 case OMPD_flush: 10169 case OMPD_teams: 10170 case OMPD_target_data: 10171 case OMPD_distribute: 10172 case OMPD_distribute_simd: 10173 case OMPD_distribute_parallel_for: 10174 case OMPD_distribute_parallel_for_simd: 10175 case OMPD_teams_distribute: 10176 case OMPD_teams_distribute_simd: 10177 case OMPD_teams_distribute_parallel_for: 10178 case OMPD_teams_distribute_parallel_for_simd: 10179 case OMPD_declare_simd: 10180 case OMPD_declare_variant: 10181 case OMPD_declare_target: 10182 case OMPD_end_declare_target: 10183 case OMPD_declare_reduction: 10184 case OMPD_declare_mapper: 10185 case OMPD_taskloop: 10186 case OMPD_taskloop_simd: 10187 case OMPD_master_taskloop: 10188 case OMPD_master_taskloop_simd: 10189 case OMPD_parallel_master_taskloop: 10190 case OMPD_parallel_master_taskloop_simd: 10191 case OMPD_target: 10192 case OMPD_target_simd: 10193 case OMPD_target_teams_distribute: 10194 case OMPD_target_teams_distribute_simd: 10195 case OMPD_target_teams_distribute_parallel_for: 10196 case OMPD_target_teams_distribute_parallel_for_simd: 10197 case OMPD_target_teams: 10198 case OMPD_target_parallel: 10199 case OMPD_target_parallel_for: 10200 case OMPD_target_parallel_for_simd: 10201 case OMPD_requires: 10202 case OMPD_unknown: 10203 llvm_unreachable("Unexpected standalone target data directive."); 10204 break; 10205 } 10206 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10207 }; 10208 10209 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10210 CodeGenFunction &CGF, PrePostActionTy &) { 10211 // Fill up the arrays with all the mapped variables. 10212 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10213 MappableExprsHandler::MapValuesArrayTy Pointers; 10214 MappableExprsHandler::MapValuesArrayTy Sizes; 10215 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10216 10217 // Get map clause information. 10218 MappableExprsHandler MEHandler(D, CGF); 10219 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10220 10221 TargetDataInfo Info; 10222 // Fill up the arrays and create the arguments. 10223 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10224 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10225 Info.PointersArray, Info.SizesArray, 10226 Info.MapTypesArray, Info); 10227 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10228 InputInfo.BasePointersArray = 10229 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10230 InputInfo.PointersArray = 10231 Address(Info.PointersArray, CGM.getPointerAlign()); 10232 InputInfo.SizesArray = 10233 Address(Info.SizesArray, CGM.getPointerAlign()); 10234 MapTypesArray = Info.MapTypesArray; 10235 if (D.hasClausesOfKind<OMPDependClause>()) 10236 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10237 else 10238 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10239 }; 10240 10241 if (IfCond) { 10242 emitIfClause(CGF, IfCond, TargetThenGen, 10243 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10244 } else { 10245 RegionCodeGenTy ThenRCG(TargetThenGen); 10246 ThenRCG(CGF); 10247 } 10248 } 10249 10250 namespace { 10251 /// Kind of parameter in a function with 'declare simd' directive. 10252 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10253 /// Attribute set of the parameter. 10254 struct ParamAttrTy { 10255 ParamKindTy Kind = Vector; 10256 llvm::APSInt StrideOrArg; 10257 llvm::APSInt Alignment; 10258 }; 10259 } // namespace 10260 10261 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10262 ArrayRef<ParamAttrTy> ParamAttrs) { 10263 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10264 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10265 // of that clause. The VLEN value must be power of 2. 10266 // In other case the notion of the function`s "characteristic data type" (CDT) 10267 // is used to compute the vector length. 10268 // CDT is defined in the following order: 10269 // a) For non-void function, the CDT is the return type. 10270 // b) If the function has any non-uniform, non-linear parameters, then the 10271 // CDT is the type of the first such parameter. 10272 // c) If the CDT determined by a) or b) above is struct, union, or class 10273 // type which is pass-by-value (except for the type that maps to the 10274 // built-in complex data type), the characteristic data type is int. 10275 // d) If none of the above three cases is applicable, the CDT is int. 10276 // The VLEN is then determined based on the CDT and the size of vector 10277 // register of that ISA for which current vector version is generated. The 10278 // VLEN is computed using the formula below: 10279 // VLEN = sizeof(vector_register) / sizeof(CDT), 10280 // where vector register size specified in section 3.2.1 Registers and the 10281 // Stack Frame of original AMD64 ABI document. 10282 QualType RetType = FD->getReturnType(); 10283 if (RetType.isNull()) 10284 return 0; 10285 ASTContext &C = FD->getASTContext(); 10286 QualType CDT; 10287 if (!RetType.isNull() && !RetType->isVoidType()) { 10288 CDT = RetType; 10289 } else { 10290 unsigned Offset = 0; 10291 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10292 if (ParamAttrs[Offset].Kind == Vector) 10293 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10294 ++Offset; 10295 } 10296 if (CDT.isNull()) { 10297 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10298 if (ParamAttrs[I + Offset].Kind == Vector) { 10299 CDT = FD->getParamDecl(I)->getType(); 10300 break; 10301 } 10302 } 10303 } 10304 } 10305 if (CDT.isNull()) 10306 CDT = C.IntTy; 10307 CDT = CDT->getCanonicalTypeUnqualified(); 10308 if (CDT->isRecordType() || CDT->isUnionType()) 10309 CDT = C.IntTy; 10310 return C.getTypeSize(CDT); 10311 } 10312 10313 static void 10314 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10315 const llvm::APSInt &VLENVal, 10316 ArrayRef<ParamAttrTy> ParamAttrs, 10317 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10318 struct ISADataTy { 10319 char ISA; 10320 unsigned VecRegSize; 10321 }; 10322 ISADataTy ISAData[] = { 10323 { 10324 'b', 128 10325 }, // SSE 10326 { 10327 'c', 256 10328 }, // AVX 10329 { 10330 'd', 256 10331 }, // AVX2 10332 { 10333 'e', 512 10334 }, // AVX512 10335 }; 10336 llvm::SmallVector<char, 2> Masked; 10337 switch (State) { 10338 case OMPDeclareSimdDeclAttr::BS_Undefined: 10339 Masked.push_back('N'); 10340 Masked.push_back('M'); 10341 break; 10342 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10343 Masked.push_back('N'); 10344 break; 10345 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10346 Masked.push_back('M'); 10347 break; 10348 } 10349 for (char Mask : Masked) { 10350 for (const ISADataTy &Data : ISAData) { 10351 SmallString<256> Buffer; 10352 llvm::raw_svector_ostream Out(Buffer); 10353 Out << "_ZGV" << Data.ISA << Mask; 10354 if (!VLENVal) { 10355 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10356 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10357 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10358 } else { 10359 Out << VLENVal; 10360 } 10361 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10362 switch (ParamAttr.Kind){ 10363 case LinearWithVarStride: 10364 Out << 's' << ParamAttr.StrideOrArg; 10365 break; 10366 case Linear: 10367 Out << 'l'; 10368 if (!!ParamAttr.StrideOrArg) 10369 Out << ParamAttr.StrideOrArg; 10370 break; 10371 case Uniform: 10372 Out << 'u'; 10373 break; 10374 case Vector: 10375 Out << 'v'; 10376 break; 10377 } 10378 if (!!ParamAttr.Alignment) 10379 Out << 'a' << ParamAttr.Alignment; 10380 } 10381 Out << '_' << Fn->getName(); 10382 Fn->addFnAttr(Out.str()); 10383 } 10384 } 10385 } 10386 10387 // This are the Functions that are needed to mangle the name of the 10388 // vector functions generated by the compiler, according to the rules 10389 // defined in the "Vector Function ABI specifications for AArch64", 10390 // available at 10391 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10392 10393 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10394 /// 10395 /// TODO: Need to implement the behavior for reference marked with a 10396 /// var or no linear modifiers (1.b in the section). For this, we 10397 /// need to extend ParamKindTy to support the linear modifiers. 10398 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10399 QT = QT.getCanonicalType(); 10400 10401 if (QT->isVoidType()) 10402 return false; 10403 10404 if (Kind == ParamKindTy::Uniform) 10405 return false; 10406 10407 if (Kind == ParamKindTy::Linear) 10408 return false; 10409 10410 // TODO: Handle linear references with modifiers 10411 10412 if (Kind == ParamKindTy::LinearWithVarStride) 10413 return false; 10414 10415 return true; 10416 } 10417 10418 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10419 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10420 QT = QT.getCanonicalType(); 10421 unsigned Size = C.getTypeSize(QT); 10422 10423 // Only scalars and complex within 16 bytes wide set PVB to true. 10424 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10425 return false; 10426 10427 if (QT->isFloatingType()) 10428 return true; 10429 10430 if (QT->isIntegerType()) 10431 return true; 10432 10433 if (QT->isPointerType()) 10434 return true; 10435 10436 // TODO: Add support for complex types (section 3.1.2, item 2). 10437 10438 return false; 10439 } 10440 10441 /// Computes the lane size (LS) of a return type or of an input parameter, 10442 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10443 /// TODO: Add support for references, section 3.2.1, item 1. 10444 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10445 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10446 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10447 if (getAArch64PBV(PTy, C)) 10448 return C.getTypeSize(PTy); 10449 } 10450 if (getAArch64PBV(QT, C)) 10451 return C.getTypeSize(QT); 10452 10453 return C.getTypeSize(C.getUIntPtrType()); 10454 } 10455 10456 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10457 // signature of the scalar function, as defined in 3.2.2 of the 10458 // AAVFABI. 10459 static std::tuple<unsigned, unsigned, bool> 10460 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10461 QualType RetType = FD->getReturnType().getCanonicalType(); 10462 10463 ASTContext &C = FD->getASTContext(); 10464 10465 bool OutputBecomesInput = false; 10466 10467 llvm::SmallVector<unsigned, 8> Sizes; 10468 if (!RetType->isVoidType()) { 10469 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10470 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10471 OutputBecomesInput = true; 10472 } 10473 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10474 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10475 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10476 } 10477 10478 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10479 // The LS of a function parameter / return value can only be a power 10480 // of 2, starting from 8 bits, up to 128. 10481 assert(std::all_of(Sizes.begin(), Sizes.end(), 10482 [](unsigned Size) { 10483 return Size == 8 || Size == 16 || Size == 32 || 10484 Size == 64 || Size == 128; 10485 }) && 10486 "Invalid size"); 10487 10488 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10489 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10490 OutputBecomesInput); 10491 } 10492 10493 /// Mangle the parameter part of the vector function name according to 10494 /// their OpenMP classification. The mangling function is defined in 10495 /// section 3.5 of the AAVFABI. 10496 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10497 SmallString<256> Buffer; 10498 llvm::raw_svector_ostream Out(Buffer); 10499 for (const auto &ParamAttr : ParamAttrs) { 10500 switch (ParamAttr.Kind) { 10501 case LinearWithVarStride: 10502 Out << "ls" << ParamAttr.StrideOrArg; 10503 break; 10504 case Linear: 10505 Out << 'l'; 10506 // Don't print the step value if it is not present or if it is 10507 // equal to 1. 10508 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10509 Out << ParamAttr.StrideOrArg; 10510 break; 10511 case Uniform: 10512 Out << 'u'; 10513 break; 10514 case Vector: 10515 Out << 'v'; 10516 break; 10517 } 10518 10519 if (!!ParamAttr.Alignment) 10520 Out << 'a' << ParamAttr.Alignment; 10521 } 10522 10523 return Out.str(); 10524 } 10525 10526 // Function used to add the attribute. The parameter `VLEN` is 10527 // templated to allow the use of "x" when targeting scalable functions 10528 // for SVE. 10529 template <typename T> 10530 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10531 char ISA, StringRef ParSeq, 10532 StringRef MangledName, bool OutputBecomesInput, 10533 llvm::Function *Fn) { 10534 SmallString<256> Buffer; 10535 llvm::raw_svector_ostream Out(Buffer); 10536 Out << Prefix << ISA << LMask << VLEN; 10537 if (OutputBecomesInput) 10538 Out << "v"; 10539 Out << ParSeq << "_" << MangledName; 10540 Fn->addFnAttr(Out.str()); 10541 } 10542 10543 // Helper function to generate the Advanced SIMD names depending on 10544 // the value of the NDS when simdlen is not present. 10545 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10546 StringRef Prefix, char ISA, 10547 StringRef ParSeq, StringRef MangledName, 10548 bool OutputBecomesInput, 10549 llvm::Function *Fn) { 10550 switch (NDS) { 10551 case 8: 10552 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10553 OutputBecomesInput, Fn); 10554 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10555 OutputBecomesInput, Fn); 10556 break; 10557 case 16: 10558 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10559 OutputBecomesInput, Fn); 10560 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10561 OutputBecomesInput, Fn); 10562 break; 10563 case 32: 10564 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10565 OutputBecomesInput, Fn); 10566 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10567 OutputBecomesInput, Fn); 10568 break; 10569 case 64: 10570 case 128: 10571 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10572 OutputBecomesInput, Fn); 10573 break; 10574 default: 10575 llvm_unreachable("Scalar type is too wide."); 10576 } 10577 } 10578 10579 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10580 static void emitAArch64DeclareSimdFunction( 10581 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10582 ArrayRef<ParamAttrTy> ParamAttrs, 10583 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10584 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10585 10586 // Get basic data for building the vector signature. 10587 const auto Data = getNDSWDS(FD, ParamAttrs); 10588 const unsigned NDS = std::get<0>(Data); 10589 const unsigned WDS = std::get<1>(Data); 10590 const bool OutputBecomesInput = std::get<2>(Data); 10591 10592 // Check the values provided via `simdlen` by the user. 10593 // 1. A `simdlen(1)` doesn't produce vector signatures, 10594 if (UserVLEN == 1) { 10595 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10596 DiagnosticsEngine::Warning, 10597 "The clause simdlen(1) has no effect when targeting aarch64."); 10598 CGM.getDiags().Report(SLoc, DiagID); 10599 return; 10600 } 10601 10602 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10603 // Advanced SIMD output. 10604 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10605 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10606 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10607 "power of 2 when targeting Advanced SIMD."); 10608 CGM.getDiags().Report(SLoc, DiagID); 10609 return; 10610 } 10611 10612 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10613 // limits. 10614 if (ISA == 's' && UserVLEN != 0) { 10615 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10616 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10617 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10618 "lanes in the architectural constraints " 10619 "for SVE (min is 128-bit, max is " 10620 "2048-bit, by steps of 128-bit)"); 10621 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10622 return; 10623 } 10624 } 10625 10626 // Sort out parameter sequence. 10627 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10628 StringRef Prefix = "_ZGV"; 10629 // Generate simdlen from user input (if any). 10630 if (UserVLEN) { 10631 if (ISA == 's') { 10632 // SVE generates only a masked function. 10633 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10634 OutputBecomesInput, Fn); 10635 } else { 10636 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10637 // Advanced SIMD generates one or two functions, depending on 10638 // the `[not]inbranch` clause. 10639 switch (State) { 10640 case OMPDeclareSimdDeclAttr::BS_Undefined: 10641 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10642 OutputBecomesInput, Fn); 10643 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10644 OutputBecomesInput, Fn); 10645 break; 10646 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10647 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10648 OutputBecomesInput, Fn); 10649 break; 10650 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10651 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10652 OutputBecomesInput, Fn); 10653 break; 10654 } 10655 } 10656 } else { 10657 // If no user simdlen is provided, follow the AAVFABI rules for 10658 // generating the vector length. 10659 if (ISA == 's') { 10660 // SVE, section 3.4.1, item 1. 10661 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10662 OutputBecomesInput, Fn); 10663 } else { 10664 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10665 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10666 // two vector names depending on the use of the clause 10667 // `[not]inbranch`. 10668 switch (State) { 10669 case OMPDeclareSimdDeclAttr::BS_Undefined: 10670 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10671 OutputBecomesInput, Fn); 10672 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10673 OutputBecomesInput, Fn); 10674 break; 10675 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10676 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10677 OutputBecomesInput, Fn); 10678 break; 10679 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10680 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10681 OutputBecomesInput, Fn); 10682 break; 10683 } 10684 } 10685 } 10686 } 10687 10688 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10689 llvm::Function *Fn) { 10690 ASTContext &C = CGM.getContext(); 10691 FD = FD->getMostRecentDecl(); 10692 // Map params to their positions in function decl. 10693 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10694 if (isa<CXXMethodDecl>(FD)) 10695 ParamPositions.try_emplace(FD, 0); 10696 unsigned ParamPos = ParamPositions.size(); 10697 for (const ParmVarDecl *P : FD->parameters()) { 10698 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10699 ++ParamPos; 10700 } 10701 while (FD) { 10702 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10703 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10704 // Mark uniform parameters. 10705 for (const Expr *E : Attr->uniforms()) { 10706 E = E->IgnoreParenImpCasts(); 10707 unsigned Pos; 10708 if (isa<CXXThisExpr>(E)) { 10709 Pos = ParamPositions[FD]; 10710 } else { 10711 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10712 ->getCanonicalDecl(); 10713 Pos = ParamPositions[PVD]; 10714 } 10715 ParamAttrs[Pos].Kind = Uniform; 10716 } 10717 // Get alignment info. 10718 auto NI = Attr->alignments_begin(); 10719 for (const Expr *E : Attr->aligneds()) { 10720 E = E->IgnoreParenImpCasts(); 10721 unsigned Pos; 10722 QualType ParmTy; 10723 if (isa<CXXThisExpr>(E)) { 10724 Pos = ParamPositions[FD]; 10725 ParmTy = E->getType(); 10726 } else { 10727 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10728 ->getCanonicalDecl(); 10729 Pos = ParamPositions[PVD]; 10730 ParmTy = PVD->getType(); 10731 } 10732 ParamAttrs[Pos].Alignment = 10733 (*NI) 10734 ? (*NI)->EvaluateKnownConstInt(C) 10735 : llvm::APSInt::getUnsigned( 10736 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10737 .getQuantity()); 10738 ++NI; 10739 } 10740 // Mark linear parameters. 10741 auto SI = Attr->steps_begin(); 10742 auto MI = Attr->modifiers_begin(); 10743 for (const Expr *E : Attr->linears()) { 10744 E = E->IgnoreParenImpCasts(); 10745 unsigned Pos; 10746 if (isa<CXXThisExpr>(E)) { 10747 Pos = ParamPositions[FD]; 10748 } else { 10749 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10750 ->getCanonicalDecl(); 10751 Pos = ParamPositions[PVD]; 10752 } 10753 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10754 ParamAttr.Kind = Linear; 10755 if (*SI) { 10756 Expr::EvalResult Result; 10757 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10758 if (const auto *DRE = 10759 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10760 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10761 ParamAttr.Kind = LinearWithVarStride; 10762 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10763 ParamPositions[StridePVD->getCanonicalDecl()]); 10764 } 10765 } 10766 } else { 10767 ParamAttr.StrideOrArg = Result.Val.getInt(); 10768 } 10769 } 10770 ++SI; 10771 ++MI; 10772 } 10773 llvm::APSInt VLENVal; 10774 SourceLocation ExprLoc; 10775 const Expr *VLENExpr = Attr->getSimdlen(); 10776 if (VLENExpr) { 10777 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10778 ExprLoc = VLENExpr->getExprLoc(); 10779 } 10780 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10781 if (CGM.getTriple().getArch() == llvm::Triple::x86 || 10782 CGM.getTriple().getArch() == llvm::Triple::x86_64) { 10783 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10784 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10785 unsigned VLEN = VLENVal.getExtValue(); 10786 StringRef MangledName = Fn->getName(); 10787 if (CGM.getTarget().hasFeature("sve")) 10788 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10789 MangledName, 's', 128, Fn, ExprLoc); 10790 if (CGM.getTarget().hasFeature("neon")) 10791 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10792 MangledName, 'n', 128, Fn, ExprLoc); 10793 } 10794 } 10795 FD = FD->getPreviousDecl(); 10796 } 10797 } 10798 10799 namespace { 10800 /// Cleanup action for doacross support. 10801 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10802 public: 10803 static const int DoacrossFinArgs = 2; 10804 10805 private: 10806 llvm::FunctionCallee RTLFn; 10807 llvm::Value *Args[DoacrossFinArgs]; 10808 10809 public: 10810 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10811 ArrayRef<llvm::Value *> CallArgs) 10812 : RTLFn(RTLFn) { 10813 assert(CallArgs.size() == DoacrossFinArgs); 10814 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10815 } 10816 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10817 if (!CGF.HaveInsertPoint()) 10818 return; 10819 CGF.EmitRuntimeCall(RTLFn, Args); 10820 } 10821 }; 10822 } // namespace 10823 10824 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10825 const OMPLoopDirective &D, 10826 ArrayRef<Expr *> NumIterations) { 10827 if (!CGF.HaveInsertPoint()) 10828 return; 10829 10830 ASTContext &C = CGM.getContext(); 10831 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10832 RecordDecl *RD; 10833 if (KmpDimTy.isNull()) { 10834 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10835 // kmp_int64 lo; // lower 10836 // kmp_int64 up; // upper 10837 // kmp_int64 st; // stride 10838 // }; 10839 RD = C.buildImplicitRecord("kmp_dim"); 10840 RD->startDefinition(); 10841 addFieldToRecordDecl(C, RD, Int64Ty); 10842 addFieldToRecordDecl(C, RD, Int64Ty); 10843 addFieldToRecordDecl(C, RD, Int64Ty); 10844 RD->completeDefinition(); 10845 KmpDimTy = C.getRecordType(RD); 10846 } else { 10847 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10848 } 10849 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10850 QualType ArrayTy = 10851 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 10852 10853 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10854 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10855 enum { LowerFD = 0, UpperFD, StrideFD }; 10856 // Fill dims with data. 10857 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10858 LValue DimsLVal = CGF.MakeAddrLValue( 10859 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10860 // dims.upper = num_iterations; 10861 LValue UpperLVal = CGF.EmitLValueForField( 10862 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10863 llvm::Value *NumIterVal = 10864 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10865 D.getNumIterations()->getType(), Int64Ty, 10866 D.getNumIterations()->getExprLoc()); 10867 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10868 // dims.stride = 1; 10869 LValue StrideLVal = CGF.EmitLValueForField( 10870 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10871 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10872 StrideLVal); 10873 } 10874 10875 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10876 // kmp_int32 num_dims, struct kmp_dim * dims); 10877 llvm::Value *Args[] = { 10878 emitUpdateLocation(CGF, D.getBeginLoc()), 10879 getThreadID(CGF, D.getBeginLoc()), 10880 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10881 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10882 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10883 CGM.VoidPtrTy)}; 10884 10885 llvm::FunctionCallee RTLFn = 10886 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 10887 CGF.EmitRuntimeCall(RTLFn, Args); 10888 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10889 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10890 llvm::FunctionCallee FiniRTLFn = 10891 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 10892 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10893 llvm::makeArrayRef(FiniArgs)); 10894 } 10895 10896 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10897 const OMPDependClause *C) { 10898 QualType Int64Ty = 10899 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10900 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10901 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10902 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 10903 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10904 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10905 const Expr *CounterVal = C->getLoopData(I); 10906 assert(CounterVal); 10907 llvm::Value *CntVal = CGF.EmitScalarConversion( 10908 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10909 CounterVal->getExprLoc()); 10910 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10911 /*Volatile=*/false, Int64Ty); 10912 } 10913 llvm::Value *Args[] = { 10914 emitUpdateLocation(CGF, C->getBeginLoc()), 10915 getThreadID(CGF, C->getBeginLoc()), 10916 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10917 llvm::FunctionCallee RTLFn; 10918 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10919 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 10920 } else { 10921 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10922 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 10923 } 10924 CGF.EmitRuntimeCall(RTLFn, Args); 10925 } 10926 10927 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10928 llvm::FunctionCallee Callee, 10929 ArrayRef<llvm::Value *> Args) const { 10930 assert(Loc.isValid() && "Outlined function call location must be valid."); 10931 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10932 10933 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10934 if (Fn->doesNotThrow()) { 10935 CGF.EmitNounwindRuntimeCall(Fn, Args); 10936 return; 10937 } 10938 } 10939 CGF.EmitRuntimeCall(Callee, Args); 10940 } 10941 10942 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10943 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10944 ArrayRef<llvm::Value *> Args) const { 10945 emitCall(CGF, Loc, OutlinedFn, Args); 10946 } 10947 10948 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10949 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 10950 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 10951 HasEmittedDeclareTargetRegion = true; 10952 } 10953 10954 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 10955 const VarDecl *NativeParam, 10956 const VarDecl *TargetParam) const { 10957 return CGF.GetAddrOfLocalVar(NativeParam); 10958 } 10959 10960 namespace { 10961 /// Cleanup action for allocate support. 10962 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 10963 public: 10964 static const int CleanupArgs = 3; 10965 10966 private: 10967 llvm::FunctionCallee RTLFn; 10968 llvm::Value *Args[CleanupArgs]; 10969 10970 public: 10971 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 10972 ArrayRef<llvm::Value *> CallArgs) 10973 : RTLFn(RTLFn) { 10974 assert(CallArgs.size() == CleanupArgs && 10975 "Size of arguments does not match."); 10976 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10977 } 10978 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10979 if (!CGF.HaveInsertPoint()) 10980 return; 10981 CGF.EmitRuntimeCall(RTLFn, Args); 10982 } 10983 }; 10984 } // namespace 10985 10986 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 10987 const VarDecl *VD) { 10988 if (!VD) 10989 return Address::invalid(); 10990 const VarDecl *CVD = VD->getCanonicalDecl(); 10991 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 10992 return Address::invalid(); 10993 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 10994 // Use the default allocation. 10995 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 10996 !AA->getAllocator()) 10997 return Address::invalid(); 10998 llvm::Value *Size; 10999 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11000 if (CVD->getType()->isVariablyModifiedType()) { 11001 Size = CGF.getTypeSize(CVD->getType()); 11002 // Align the size: ((size + align - 1) / align) * align 11003 Size = CGF.Builder.CreateNUWAdd( 11004 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11005 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11006 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11007 } else { 11008 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11009 Size = CGM.getSize(Sz.alignTo(Align)); 11010 } 11011 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11012 assert(AA->getAllocator() && 11013 "Expected allocator expression for non-default allocator."); 11014 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11015 // According to the standard, the original allocator type is a enum (integer). 11016 // Convert to pointer type, if required. 11017 if (Allocator->getType()->isIntegerTy()) 11018 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11019 else if (Allocator->getType()->isPointerTy()) 11020 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11021 CGM.VoidPtrTy); 11022 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11023 11024 llvm::Value *Addr = 11025 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11026 CVD->getName() + ".void.addr"); 11027 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11028 Allocator}; 11029 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11030 11031 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11032 llvm::makeArrayRef(FiniArgs)); 11033 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11034 Addr, 11035 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11036 CVD->getName() + ".addr"); 11037 return Address(Addr, Align); 11038 } 11039 11040 namespace { 11041 using OMPContextSelectorData = 11042 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>; 11043 using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>; 11044 } // anonymous namespace 11045 11046 /// Checks current context and returns true if it matches the context selector. 11047 template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx, 11048 typename... Arguments> 11049 static bool checkContext(const OMPContextSelectorData &Data, 11050 Arguments... Params) { 11051 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown && 11052 "Unknown context selector or context selector set."); 11053 return false; 11054 } 11055 11056 /// Checks for implementation={vendor(<vendor>)} context selector. 11057 /// \returns true iff <vendor>="llvm", false otherwise. 11058 template <> 11059 bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>( 11060 const OMPContextSelectorData &Data) { 11061 return llvm::all_of(Data.Names, 11062 [](StringRef S) { return !S.compare_lower("llvm"); }); 11063 } 11064 11065 /// Checks for device={kind(<kind>)} context selector. 11066 /// \returns true if <kind>="host" and compilation is for host. 11067 /// true if <kind>="nohost" and compilation is for device. 11068 /// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU. 11069 /// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN. 11070 /// false otherwise. 11071 template <> 11072 bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>( 11073 const OMPContextSelectorData &Data, CodeGenModule &CGM) { 11074 for (StringRef Name : Data.Names) { 11075 if (!Name.compare_lower("host")) { 11076 if (CGM.getLangOpts().OpenMPIsDevice) 11077 return false; 11078 continue; 11079 } 11080 if (!Name.compare_lower("nohost")) { 11081 if (!CGM.getLangOpts().OpenMPIsDevice) 11082 return false; 11083 continue; 11084 } 11085 switch (CGM.getTriple().getArch()) { 11086 case llvm::Triple::arm: 11087 case llvm::Triple::armeb: 11088 case llvm::Triple::aarch64: 11089 case llvm::Triple::aarch64_be: 11090 case llvm::Triple::aarch64_32: 11091 case llvm::Triple::ppc: 11092 case llvm::Triple::ppc64: 11093 case llvm::Triple::ppc64le: 11094 case llvm::Triple::x86: 11095 case llvm::Triple::x86_64: 11096 if (Name.compare_lower("cpu")) 11097 return false; 11098 break; 11099 case llvm::Triple::amdgcn: 11100 case llvm::Triple::nvptx: 11101 case llvm::Triple::nvptx64: 11102 if (Name.compare_lower("gpu")) 11103 return false; 11104 break; 11105 case llvm::Triple::UnknownArch: 11106 case llvm::Triple::arc: 11107 case llvm::Triple::avr: 11108 case llvm::Triple::bpfel: 11109 case llvm::Triple::bpfeb: 11110 case llvm::Triple::hexagon: 11111 case llvm::Triple::mips: 11112 case llvm::Triple::mipsel: 11113 case llvm::Triple::mips64: 11114 case llvm::Triple::mips64el: 11115 case llvm::Triple::msp430: 11116 case llvm::Triple::r600: 11117 case llvm::Triple::riscv32: 11118 case llvm::Triple::riscv64: 11119 case llvm::Triple::sparc: 11120 case llvm::Triple::sparcv9: 11121 case llvm::Triple::sparcel: 11122 case llvm::Triple::systemz: 11123 case llvm::Triple::tce: 11124 case llvm::Triple::tcele: 11125 case llvm::Triple::thumb: 11126 case llvm::Triple::thumbeb: 11127 case llvm::Triple::xcore: 11128 case llvm::Triple::le32: 11129 case llvm::Triple::le64: 11130 case llvm::Triple::amdil: 11131 case llvm::Triple::amdil64: 11132 case llvm::Triple::hsail: 11133 case llvm::Triple::hsail64: 11134 case llvm::Triple::spir: 11135 case llvm::Triple::spir64: 11136 case llvm::Triple::kalimba: 11137 case llvm::Triple::shave: 11138 case llvm::Triple::lanai: 11139 case llvm::Triple::wasm32: 11140 case llvm::Triple::wasm64: 11141 case llvm::Triple::renderscript32: 11142 case llvm::Triple::renderscript64: 11143 return false; 11144 } 11145 } 11146 return true; 11147 } 11148 11149 bool matchesContext(CodeGenModule &CGM, 11150 const CompleteOMPContextSelectorData &ContextData) { 11151 for (const OMPContextSelectorData &Data : ContextData) { 11152 switch (Data.Ctx) { 11153 case OMP_CTX_vendor: 11154 assert(Data.CtxSet == OMP_CTX_SET_implementation && 11155 "Expected implementation context selector set."); 11156 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data)) 11157 return false; 11158 break; 11159 case OMP_CTX_kind: 11160 assert(Data.CtxSet == OMP_CTX_SET_device && 11161 "Expected device context selector set."); 11162 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data, 11163 CGM)) 11164 return false; 11165 break; 11166 case OMP_CTX_unknown: 11167 llvm_unreachable("Unknown context selector kind."); 11168 } 11169 } 11170 return true; 11171 } 11172 11173 static CompleteOMPContextSelectorData 11174 translateAttrToContextSelectorData(ASTContext &C, 11175 const OMPDeclareVariantAttr *A) { 11176 CompleteOMPContextSelectorData Data; 11177 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) { 11178 Data.emplace_back(); 11179 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( 11180 *std::next(A->ctxSelectorSets_begin(), I)); 11181 auto Ctx = static_cast<OpenMPContextSelectorKind>( 11182 *std::next(A->ctxSelectors_begin(), I)); 11183 Data.back().CtxSet = CtxSet; 11184 Data.back().Ctx = Ctx; 11185 const Expr *Score = *std::next(A->scores_begin(), I); 11186 Data.back().Score = Score->EvaluateKnownConstInt(C); 11187 switch (Ctx) { 11188 case OMP_CTX_vendor: 11189 assert(CtxSet == OMP_CTX_SET_implementation && 11190 "Expected implementation context selector set."); 11191 Data.back().Names = 11192 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end()); 11193 break; 11194 case OMP_CTX_kind: 11195 assert(CtxSet == OMP_CTX_SET_device && 11196 "Expected device context selector set."); 11197 Data.back().Names = 11198 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end()); 11199 break; 11200 case OMP_CTX_unknown: 11201 llvm_unreachable("Unknown context selector kind."); 11202 } 11203 } 11204 return Data; 11205 } 11206 11207 static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS, 11208 const CompleteOMPContextSelectorData &RHS) { 11209 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData; 11210 for (const OMPContextSelectorData &D : RHS) { 11211 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx)); 11212 Pair.getSecond().insert(D.Names.begin(), D.Names.end()); 11213 } 11214 bool AllSetsAreEqual = true; 11215 for (const OMPContextSelectorData &D : LHS) { 11216 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx)); 11217 if (It == RHSData.end()) 11218 return false; 11219 if (D.Names.size() > It->getSecond().size()) 11220 return false; 11221 if (llvm::set_union(It->getSecond(), D.Names)) 11222 return false; 11223 AllSetsAreEqual = 11224 AllSetsAreEqual && (D.Names.size() == It->getSecond().size()); 11225 } 11226 11227 return LHS.size() != RHS.size() || !AllSetsAreEqual; 11228 } 11229 11230 static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS, 11231 const CompleteOMPContextSelectorData &RHS) { 11232 // Score is calculated as sum of all scores + 1. 11233 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11234 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS); 11235 if (RHSIsSubsetOfLHS) { 11236 LHSScore = llvm::APSInt::get(0); 11237 } else { 11238 for (const OMPContextSelectorData &Data : LHS) { 11239 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) { 11240 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11241 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) { 11242 LHSScore += Data.Score.extend(LHSScore.getBitWidth()); 11243 } else { 11244 LHSScore += Data.Score; 11245 } 11246 } 11247 } 11248 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11249 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) { 11250 RHSScore = llvm::APSInt::get(0); 11251 } else { 11252 for (const OMPContextSelectorData &Data : RHS) { 11253 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) { 11254 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11255 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) { 11256 RHSScore += Data.Score.extend(RHSScore.getBitWidth()); 11257 } else { 11258 RHSScore += Data.Score; 11259 } 11260 } 11261 } 11262 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0; 11263 } 11264 11265 /// Finds the variant function that matches current context with its context 11266 /// selector. 11267 static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, 11268 const FunctionDecl *FD) { 11269 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11270 return FD; 11271 // Iterate through all DeclareVariant attributes and check context selectors. 11272 const OMPDeclareVariantAttr *TopMostAttr = nullptr; 11273 CompleteOMPContextSelectorData TopMostData; 11274 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11275 CompleteOMPContextSelectorData Data = 11276 translateAttrToContextSelectorData(CGM.getContext(), A); 11277 if (!matchesContext(CGM, Data)) 11278 continue; 11279 // If the attribute matches the context, find the attribute with the highest 11280 // score. 11281 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) { 11282 TopMostAttr = A; 11283 TopMostData.swap(Data); 11284 } 11285 } 11286 if (!TopMostAttr) 11287 return FD; 11288 return cast<FunctionDecl>( 11289 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) 11290 ->getDecl()); 11291 } 11292 11293 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11294 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11295 // If the original function is defined already, use its definition. 11296 StringRef MangledName = CGM.getMangledName(GD); 11297 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11298 if (Orig && !Orig->isDeclaration()) 11299 return false; 11300 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D); 11301 // Emit original function if it does not have declare variant attribute or the 11302 // context does not match. 11303 if (NewFD == D) 11304 return false; 11305 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11306 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) { 11307 DeferredVariantFunction.erase(D); 11308 return true; 11309 } 11310 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11311 return true; 11312 } 11313 11314 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11315 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11316 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11317 llvm_unreachable("Not supported in SIMD-only mode"); 11318 } 11319 11320 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11321 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11322 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11323 llvm_unreachable("Not supported in SIMD-only mode"); 11324 } 11325 11326 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11327 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11328 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11329 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11330 bool Tied, unsigned &NumberOfParts) { 11331 llvm_unreachable("Not supported in SIMD-only mode"); 11332 } 11333 11334 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11335 SourceLocation Loc, 11336 llvm::Function *OutlinedFn, 11337 ArrayRef<llvm::Value *> CapturedVars, 11338 const Expr *IfCond) { 11339 llvm_unreachable("Not supported in SIMD-only mode"); 11340 } 11341 11342 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11343 CodeGenFunction &CGF, StringRef CriticalName, 11344 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11345 const Expr *Hint) { 11346 llvm_unreachable("Not supported in SIMD-only mode"); 11347 } 11348 11349 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11350 const RegionCodeGenTy &MasterOpGen, 11351 SourceLocation Loc) { 11352 llvm_unreachable("Not supported in SIMD-only mode"); 11353 } 11354 11355 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11356 SourceLocation Loc) { 11357 llvm_unreachable("Not supported in SIMD-only mode"); 11358 } 11359 11360 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11361 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11362 SourceLocation Loc) { 11363 llvm_unreachable("Not supported in SIMD-only mode"); 11364 } 11365 11366 void CGOpenMPSIMDRuntime::emitSingleRegion( 11367 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11368 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11369 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11370 ArrayRef<const Expr *> AssignmentOps) { 11371 llvm_unreachable("Not supported in SIMD-only mode"); 11372 } 11373 11374 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11375 const RegionCodeGenTy &OrderedOpGen, 11376 SourceLocation Loc, 11377 bool IsThreads) { 11378 llvm_unreachable("Not supported in SIMD-only mode"); 11379 } 11380 11381 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11382 SourceLocation Loc, 11383 OpenMPDirectiveKind Kind, 11384 bool EmitChecks, 11385 bool ForceSimpleCall) { 11386 llvm_unreachable("Not supported in SIMD-only mode"); 11387 } 11388 11389 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11390 CodeGenFunction &CGF, SourceLocation Loc, 11391 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11392 bool Ordered, const DispatchRTInput &DispatchValues) { 11393 llvm_unreachable("Not supported in SIMD-only mode"); 11394 } 11395 11396 void CGOpenMPSIMDRuntime::emitForStaticInit( 11397 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11398 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11399 llvm_unreachable("Not supported in SIMD-only mode"); 11400 } 11401 11402 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11403 CodeGenFunction &CGF, SourceLocation Loc, 11404 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11405 llvm_unreachable("Not supported in SIMD-only mode"); 11406 } 11407 11408 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11409 SourceLocation Loc, 11410 unsigned IVSize, 11411 bool IVSigned) { 11412 llvm_unreachable("Not supported in SIMD-only mode"); 11413 } 11414 11415 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11416 SourceLocation Loc, 11417 OpenMPDirectiveKind DKind) { 11418 llvm_unreachable("Not supported in SIMD-only mode"); 11419 } 11420 11421 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11422 SourceLocation Loc, 11423 unsigned IVSize, bool IVSigned, 11424 Address IL, Address LB, 11425 Address UB, Address ST) { 11426 llvm_unreachable("Not supported in SIMD-only mode"); 11427 } 11428 11429 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11430 llvm::Value *NumThreads, 11431 SourceLocation Loc) { 11432 llvm_unreachable("Not supported in SIMD-only mode"); 11433 } 11434 11435 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11436 OpenMPProcBindClauseKind ProcBind, 11437 SourceLocation Loc) { 11438 llvm_unreachable("Not supported in SIMD-only mode"); 11439 } 11440 11441 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11442 const VarDecl *VD, 11443 Address VDAddr, 11444 SourceLocation Loc) { 11445 llvm_unreachable("Not supported in SIMD-only mode"); 11446 } 11447 11448 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11449 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11450 CodeGenFunction *CGF) { 11451 llvm_unreachable("Not supported in SIMD-only mode"); 11452 } 11453 11454 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11455 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11456 llvm_unreachable("Not supported in SIMD-only mode"); 11457 } 11458 11459 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11460 ArrayRef<const Expr *> Vars, 11461 SourceLocation Loc) { 11462 llvm_unreachable("Not supported in SIMD-only mode"); 11463 } 11464 11465 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11466 const OMPExecutableDirective &D, 11467 llvm::Function *TaskFunction, 11468 QualType SharedsTy, Address Shareds, 11469 const Expr *IfCond, 11470 const OMPTaskDataTy &Data) { 11471 llvm_unreachable("Not supported in SIMD-only mode"); 11472 } 11473 11474 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11475 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11476 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11477 const Expr *IfCond, const OMPTaskDataTy &Data) { 11478 llvm_unreachable("Not supported in SIMD-only mode"); 11479 } 11480 11481 void CGOpenMPSIMDRuntime::emitReduction( 11482 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11483 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11484 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11485 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11486 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 11487 ReductionOps, Options); 11488 } 11489 11490 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 11491 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 11492 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 11493 llvm_unreachable("Not supported in SIMD-only mode"); 11494 } 11495 11496 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 11497 SourceLocation Loc, 11498 ReductionCodeGen &RCG, 11499 unsigned N) { 11500 llvm_unreachable("Not supported in SIMD-only mode"); 11501 } 11502 11503 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 11504 SourceLocation Loc, 11505 llvm::Value *ReductionsPtr, 11506 LValue SharedLVal) { 11507 llvm_unreachable("Not supported in SIMD-only mode"); 11508 } 11509 11510 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 11511 SourceLocation Loc) { 11512 llvm_unreachable("Not supported in SIMD-only mode"); 11513 } 11514 11515 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 11516 CodeGenFunction &CGF, SourceLocation Loc, 11517 OpenMPDirectiveKind CancelRegion) { 11518 llvm_unreachable("Not supported in SIMD-only mode"); 11519 } 11520 11521 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 11522 SourceLocation Loc, const Expr *IfCond, 11523 OpenMPDirectiveKind CancelRegion) { 11524 llvm_unreachable("Not supported in SIMD-only mode"); 11525 } 11526 11527 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 11528 const OMPExecutableDirective &D, StringRef ParentName, 11529 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 11530 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 11531 llvm_unreachable("Not supported in SIMD-only mode"); 11532 } 11533 11534 void CGOpenMPSIMDRuntime::emitTargetCall( 11535 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11536 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 11537 const Expr *Device, 11538 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 11539 const OMPLoopDirective &D)> 11540 SizeEmitter) { 11541 llvm_unreachable("Not supported in SIMD-only mode"); 11542 } 11543 11544 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 11545 llvm_unreachable("Not supported in SIMD-only mode"); 11546 } 11547 11548 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 11549 llvm_unreachable("Not supported in SIMD-only mode"); 11550 } 11551 11552 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 11553 return false; 11554 } 11555 11556 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 11557 const OMPExecutableDirective &D, 11558 SourceLocation Loc, 11559 llvm::Function *OutlinedFn, 11560 ArrayRef<llvm::Value *> CapturedVars) { 11561 llvm_unreachable("Not supported in SIMD-only mode"); 11562 } 11563 11564 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11565 const Expr *NumTeams, 11566 const Expr *ThreadLimit, 11567 SourceLocation Loc) { 11568 llvm_unreachable("Not supported in SIMD-only mode"); 11569 } 11570 11571 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 11572 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11573 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11574 llvm_unreachable("Not supported in SIMD-only mode"); 11575 } 11576 11577 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 11578 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11579 const Expr *Device) { 11580 llvm_unreachable("Not supported in SIMD-only mode"); 11581 } 11582 11583 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11584 const OMPLoopDirective &D, 11585 ArrayRef<Expr *> NumIterations) { 11586 llvm_unreachable("Not supported in SIMD-only mode"); 11587 } 11588 11589 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11590 const OMPDependClause *C) { 11591 llvm_unreachable("Not supported in SIMD-only mode"); 11592 } 11593 11594 const VarDecl * 11595 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 11596 const VarDecl *NativeParam) const { 11597 llvm_unreachable("Not supported in SIMD-only mode"); 11598 } 11599 11600 Address 11601 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 11602 const VarDecl *NativeParam, 11603 const VarDecl *TargetParam) const { 11604 llvm_unreachable("Not supported in SIMD-only mode"); 11605 } 11606