1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides a class for OpenMP runtime code generation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGOpenMPRuntime.h" 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/AST/Attr.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/StmtOpenMP.h" 21 #include "clang/Basic/BitmaskEnum.h" 22 #include "clang/CodeGen/ConstantInitBuilder.h" 23 #include "llvm/ADT/ArrayRef.h" 24 #include "llvm/ADT/SetOperations.h" 25 #include "llvm/Bitcode/BitcodeReader.h" 26 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 27 #include "llvm/IR/DerivedTypes.h" 28 #include "llvm/IR/GlobalValue.h" 29 #include "llvm/IR/Value.h" 30 #include "llvm/Support/Format.h" 31 #include "llvm/Support/raw_ostream.h" 32 #include <cassert> 33 34 using namespace clang; 35 using namespace CodeGen; 36 using namespace llvm::omp; 37 38 namespace { 39 /// Base class for handling code generation inside OpenMP regions. 40 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 41 public: 42 /// Kinds of OpenMP regions used in codegen. 43 enum CGOpenMPRegionKind { 44 /// Region with outlined function for standalone 'parallel' 45 /// directive. 46 ParallelOutlinedRegion, 47 /// Region with outlined function for standalone 'task' directive. 48 TaskOutlinedRegion, 49 /// Region for constructs that do not require function outlining, 50 /// like 'for', 'sections', 'atomic' etc. directives. 51 InlinedRegion, 52 /// Region with outlined function for standalone 'target' directive. 53 TargetRegion, 54 }; 55 56 CGOpenMPRegionInfo(const CapturedStmt &CS, 57 const CGOpenMPRegionKind RegionKind, 58 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 59 bool HasCancel) 60 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 61 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 62 63 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 64 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 65 bool HasCancel) 66 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 67 Kind(Kind), HasCancel(HasCancel) {} 68 69 /// Get a variable or parameter for storing global thread id 70 /// inside OpenMP construct. 71 virtual const VarDecl *getThreadIDVariable() const = 0; 72 73 /// Emit the captured statement body. 74 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 75 76 /// Get an LValue for the current ThreadID variable. 77 /// \return LValue for thread id variable. This LValue always has type int32*. 78 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 79 80 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 81 82 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 83 84 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 85 86 bool hasCancel() const { return HasCancel; } 87 88 static bool classof(const CGCapturedStmtInfo *Info) { 89 return Info->getKind() == CR_OpenMP; 90 } 91 92 ~CGOpenMPRegionInfo() override = default; 93 94 protected: 95 CGOpenMPRegionKind RegionKind; 96 RegionCodeGenTy CodeGen; 97 OpenMPDirectiveKind Kind; 98 bool HasCancel; 99 }; 100 101 /// API for captured statement code generation in OpenMP constructs. 102 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 103 public: 104 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 105 const RegionCodeGenTy &CodeGen, 106 OpenMPDirectiveKind Kind, bool HasCancel, 107 StringRef HelperName) 108 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 109 HasCancel), 110 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 111 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 112 } 113 114 /// Get a variable or parameter for storing global thread id 115 /// inside OpenMP construct. 116 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 117 118 /// Get the name of the capture helper. 119 StringRef getHelperName() const override { return HelperName; } 120 121 static bool classof(const CGCapturedStmtInfo *Info) { 122 return CGOpenMPRegionInfo::classof(Info) && 123 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 124 ParallelOutlinedRegion; 125 } 126 127 private: 128 /// A variable or parameter storing global thread id for OpenMP 129 /// constructs. 130 const VarDecl *ThreadIDVar; 131 StringRef HelperName; 132 }; 133 134 /// API for captured statement code generation in OpenMP constructs. 135 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 136 public: 137 class UntiedTaskActionTy final : public PrePostActionTy { 138 bool Untied; 139 const VarDecl *PartIDVar; 140 const RegionCodeGenTy UntiedCodeGen; 141 llvm::SwitchInst *UntiedSwitch = nullptr; 142 143 public: 144 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 145 const RegionCodeGenTy &UntiedCodeGen) 146 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 147 void Enter(CodeGenFunction &CGF) override { 148 if (Untied) { 149 // Emit task switching point. 150 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 151 CGF.GetAddrOfLocalVar(PartIDVar), 152 PartIDVar->getType()->castAs<PointerType>()); 153 llvm::Value *Res = 154 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 155 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 156 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 157 CGF.EmitBlock(DoneBB); 158 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 159 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 160 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 161 CGF.Builder.GetInsertBlock()); 162 emitUntiedSwitch(CGF); 163 } 164 } 165 void emitUntiedSwitch(CodeGenFunction &CGF) const { 166 if (Untied) { 167 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 168 CGF.GetAddrOfLocalVar(PartIDVar), 169 PartIDVar->getType()->castAs<PointerType>()); 170 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 171 PartIdLVal); 172 UntiedCodeGen(CGF); 173 CodeGenFunction::JumpDest CurPoint = 174 CGF.getJumpDestInCurrentScope(".untied.next."); 175 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 176 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 177 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 178 CGF.Builder.GetInsertBlock()); 179 CGF.EmitBranchThroughCleanup(CurPoint); 180 CGF.EmitBlock(CurPoint.getBlock()); 181 } 182 } 183 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 184 }; 185 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 186 const VarDecl *ThreadIDVar, 187 const RegionCodeGenTy &CodeGen, 188 OpenMPDirectiveKind Kind, bool HasCancel, 189 const UntiedTaskActionTy &Action) 190 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 191 ThreadIDVar(ThreadIDVar), Action(Action) { 192 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 193 } 194 195 /// Get a variable or parameter for storing global thread id 196 /// inside OpenMP construct. 197 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 198 199 /// Get an LValue for the current ThreadID variable. 200 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 201 202 /// Get the name of the capture helper. 203 StringRef getHelperName() const override { return ".omp_outlined."; } 204 205 void emitUntiedSwitch(CodeGenFunction &CGF) override { 206 Action.emitUntiedSwitch(CGF); 207 } 208 209 static bool classof(const CGCapturedStmtInfo *Info) { 210 return CGOpenMPRegionInfo::classof(Info) && 211 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 212 TaskOutlinedRegion; 213 } 214 215 private: 216 /// A variable or parameter storing global thread id for OpenMP 217 /// constructs. 218 const VarDecl *ThreadIDVar; 219 /// Action for emitting code for untied tasks. 220 const UntiedTaskActionTy &Action; 221 }; 222 223 /// API for inlined captured statement code generation in OpenMP 224 /// constructs. 225 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 226 public: 227 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 228 const RegionCodeGenTy &CodeGen, 229 OpenMPDirectiveKind Kind, bool HasCancel) 230 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 231 OldCSI(OldCSI), 232 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 233 234 // Retrieve the value of the context parameter. 235 llvm::Value *getContextValue() const override { 236 if (OuterRegionInfo) 237 return OuterRegionInfo->getContextValue(); 238 llvm_unreachable("No context value for inlined OpenMP region"); 239 } 240 241 void setContextValue(llvm::Value *V) override { 242 if (OuterRegionInfo) { 243 OuterRegionInfo->setContextValue(V); 244 return; 245 } 246 llvm_unreachable("No context value for inlined OpenMP region"); 247 } 248 249 /// Lookup the captured field decl for a variable. 250 const FieldDecl *lookup(const VarDecl *VD) const override { 251 if (OuterRegionInfo) 252 return OuterRegionInfo->lookup(VD); 253 // If there is no outer outlined region,no need to lookup in a list of 254 // captured variables, we can use the original one. 255 return nullptr; 256 } 257 258 FieldDecl *getThisFieldDecl() const override { 259 if (OuterRegionInfo) 260 return OuterRegionInfo->getThisFieldDecl(); 261 return nullptr; 262 } 263 264 /// Get a variable or parameter for storing global thread id 265 /// inside OpenMP construct. 266 const VarDecl *getThreadIDVariable() const override { 267 if (OuterRegionInfo) 268 return OuterRegionInfo->getThreadIDVariable(); 269 return nullptr; 270 } 271 272 /// Get an LValue for the current ThreadID variable. 273 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 274 if (OuterRegionInfo) 275 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 276 llvm_unreachable("No LValue for inlined OpenMP construct"); 277 } 278 279 /// Get the name of the capture helper. 280 StringRef getHelperName() const override { 281 if (auto *OuterRegionInfo = getOldCSI()) 282 return OuterRegionInfo->getHelperName(); 283 llvm_unreachable("No helper name for inlined OpenMP construct"); 284 } 285 286 void emitUntiedSwitch(CodeGenFunction &CGF) override { 287 if (OuterRegionInfo) 288 OuterRegionInfo->emitUntiedSwitch(CGF); 289 } 290 291 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 292 293 static bool classof(const CGCapturedStmtInfo *Info) { 294 return CGOpenMPRegionInfo::classof(Info) && 295 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 296 } 297 298 ~CGOpenMPInlinedRegionInfo() override = default; 299 300 private: 301 /// CodeGen info about outer OpenMP region. 302 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 303 CGOpenMPRegionInfo *OuterRegionInfo; 304 }; 305 306 /// API for captured statement code generation in OpenMP target 307 /// constructs. For this captures, implicit parameters are used instead of the 308 /// captured fields. The name of the target region has to be unique in a given 309 /// application so it is provided by the client, because only the client has 310 /// the information to generate that. 311 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 312 public: 313 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 314 const RegionCodeGenTy &CodeGen, StringRef HelperName) 315 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 316 /*HasCancel=*/false), 317 HelperName(HelperName) {} 318 319 /// This is unused for target regions because each starts executing 320 /// with a single thread. 321 const VarDecl *getThreadIDVariable() const override { return nullptr; } 322 323 /// Get the name of the capture helper. 324 StringRef getHelperName() const override { return HelperName; } 325 326 static bool classof(const CGCapturedStmtInfo *Info) { 327 return CGOpenMPRegionInfo::classof(Info) && 328 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 329 } 330 331 private: 332 StringRef HelperName; 333 }; 334 335 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 336 llvm_unreachable("No codegen for expressions"); 337 } 338 /// API for generation of expressions captured in a innermost OpenMP 339 /// region. 340 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 341 public: 342 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 343 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 344 OMPD_unknown, 345 /*HasCancel=*/false), 346 PrivScope(CGF) { 347 // Make sure the globals captured in the provided statement are local by 348 // using the privatization logic. We assume the same variable is not 349 // captured more than once. 350 for (const auto &C : CS.captures()) { 351 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 352 continue; 353 354 const VarDecl *VD = C.getCapturedVar(); 355 if (VD->isLocalVarDeclOrParm()) 356 continue; 357 358 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 359 /*RefersToEnclosingVariableOrCapture=*/false, 360 VD->getType().getNonReferenceType(), VK_LValue, 361 C.getLocation()); 362 PrivScope.addPrivate( 363 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 364 } 365 (void)PrivScope.Privatize(); 366 } 367 368 /// Lookup the captured field decl for a variable. 369 const FieldDecl *lookup(const VarDecl *VD) const override { 370 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 371 return FD; 372 return nullptr; 373 } 374 375 /// Emit the captured statement body. 376 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 377 llvm_unreachable("No body for expressions"); 378 } 379 380 /// Get a variable or parameter for storing global thread id 381 /// inside OpenMP construct. 382 const VarDecl *getThreadIDVariable() const override { 383 llvm_unreachable("No thread id for expressions"); 384 } 385 386 /// Get the name of the capture helper. 387 StringRef getHelperName() const override { 388 llvm_unreachable("No helper name for expressions"); 389 } 390 391 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 392 393 private: 394 /// Private scope to capture global variables. 395 CodeGenFunction::OMPPrivateScope PrivScope; 396 }; 397 398 /// RAII for emitting code of OpenMP constructs. 399 class InlinedOpenMPRegionRAII { 400 CodeGenFunction &CGF; 401 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 402 FieldDecl *LambdaThisCaptureField = nullptr; 403 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 404 405 public: 406 /// Constructs region for combined constructs. 407 /// \param CodeGen Code generation sequence for combined directives. Includes 408 /// a list of functions used for code generation of implicitly inlined 409 /// regions. 410 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 411 OpenMPDirectiveKind Kind, bool HasCancel) 412 : CGF(CGF) { 413 // Start emission for the construct. 414 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 415 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 416 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 417 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 418 CGF.LambdaThisCaptureField = nullptr; 419 BlockInfo = CGF.BlockInfo; 420 CGF.BlockInfo = nullptr; 421 } 422 423 ~InlinedOpenMPRegionRAII() { 424 // Restore original CapturedStmtInfo only if we're done with code emission. 425 auto *OldCSI = 426 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 427 delete CGF.CapturedStmtInfo; 428 CGF.CapturedStmtInfo = OldCSI; 429 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 430 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 431 CGF.BlockInfo = BlockInfo; 432 } 433 }; 434 435 /// Values for bit flags used in the ident_t to describe the fields. 436 /// All enumeric elements are named and described in accordance with the code 437 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 438 enum OpenMPLocationFlags : unsigned { 439 /// Use trampoline for internal microtask. 440 OMP_IDENT_IMD = 0x01, 441 /// Use c-style ident structure. 442 OMP_IDENT_KMPC = 0x02, 443 /// Atomic reduction option for kmpc_reduce. 444 OMP_ATOMIC_REDUCE = 0x10, 445 /// Explicit 'barrier' directive. 446 OMP_IDENT_BARRIER_EXPL = 0x20, 447 /// Implicit barrier in code. 448 OMP_IDENT_BARRIER_IMPL = 0x40, 449 /// Implicit barrier in 'for' directive. 450 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 451 /// Implicit barrier in 'sections' directive. 452 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 453 /// Implicit barrier in 'single' directive. 454 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 455 /// Call of __kmp_for_static_init for static loop. 456 OMP_IDENT_WORK_LOOP = 0x200, 457 /// Call of __kmp_for_static_init for sections. 458 OMP_IDENT_WORK_SECTIONS = 0x400, 459 /// Call of __kmp_for_static_init for distribute. 460 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 461 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 462 }; 463 464 namespace { 465 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 466 /// Values for bit flags for marking which requires clauses have been used. 467 enum OpenMPOffloadingRequiresDirFlags : int64_t { 468 /// flag undefined. 469 OMP_REQ_UNDEFINED = 0x000, 470 /// no requires clause present. 471 OMP_REQ_NONE = 0x001, 472 /// reverse_offload clause. 473 OMP_REQ_REVERSE_OFFLOAD = 0x002, 474 /// unified_address clause. 475 OMP_REQ_UNIFIED_ADDRESS = 0x004, 476 /// unified_shared_memory clause. 477 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 478 /// dynamic_allocators clause. 479 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 480 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 481 }; 482 483 enum OpenMPOffloadingReservedDeviceIDs { 484 /// Device ID if the device was not defined, runtime should get it 485 /// from environment variables in the spec. 486 OMP_DEVICEID_UNDEF = -1, 487 }; 488 } // anonymous namespace 489 490 /// Describes ident structure that describes a source location. 491 /// All descriptions are taken from 492 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 493 /// Original structure: 494 /// typedef struct ident { 495 /// kmp_int32 reserved_1; /**< might be used in Fortran; 496 /// see above */ 497 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 498 /// KMP_IDENT_KMPC identifies this union 499 /// member */ 500 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 501 /// see above */ 502 ///#if USE_ITT_BUILD 503 /// /* but currently used for storing 504 /// region-specific ITT */ 505 /// /* contextual information. */ 506 ///#endif /* USE_ITT_BUILD */ 507 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 508 /// C++ */ 509 /// char const *psource; /**< String describing the source location. 510 /// The string is composed of semi-colon separated 511 // fields which describe the source file, 512 /// the function and a pair of line numbers that 513 /// delimit the construct. 514 /// */ 515 /// } ident_t; 516 enum IdentFieldIndex { 517 /// might be used in Fortran 518 IdentField_Reserved_1, 519 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 520 IdentField_Flags, 521 /// Not really used in Fortran any more 522 IdentField_Reserved_2, 523 /// Source[4] in Fortran, do not use for C++ 524 IdentField_Reserved_3, 525 /// String describing the source location. The string is composed of 526 /// semi-colon separated fields which describe the source file, the function 527 /// and a pair of line numbers that delimit the construct. 528 IdentField_PSource 529 }; 530 531 /// Schedule types for 'omp for' loops (these enumerators are taken from 532 /// the enum sched_type in kmp.h). 533 enum OpenMPSchedType { 534 /// Lower bound for default (unordered) versions. 535 OMP_sch_lower = 32, 536 OMP_sch_static_chunked = 33, 537 OMP_sch_static = 34, 538 OMP_sch_dynamic_chunked = 35, 539 OMP_sch_guided_chunked = 36, 540 OMP_sch_runtime = 37, 541 OMP_sch_auto = 38, 542 /// static with chunk adjustment (e.g., simd) 543 OMP_sch_static_balanced_chunked = 45, 544 /// Lower bound for 'ordered' versions. 545 OMP_ord_lower = 64, 546 OMP_ord_static_chunked = 65, 547 OMP_ord_static = 66, 548 OMP_ord_dynamic_chunked = 67, 549 OMP_ord_guided_chunked = 68, 550 OMP_ord_runtime = 69, 551 OMP_ord_auto = 70, 552 OMP_sch_default = OMP_sch_static, 553 /// dist_schedule types 554 OMP_dist_sch_static_chunked = 91, 555 OMP_dist_sch_static = 92, 556 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 557 /// Set if the monotonic schedule modifier was present. 558 OMP_sch_modifier_monotonic = (1 << 29), 559 /// Set if the nonmonotonic schedule modifier was present. 560 OMP_sch_modifier_nonmonotonic = (1 << 30), 561 }; 562 563 enum OpenMPRTLFunction { 564 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 565 /// kmpc_micro microtask, ...); 566 OMPRTL__kmpc_fork_call, 567 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 568 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 569 OMPRTL__kmpc_threadprivate_cached, 570 /// Call to void __kmpc_threadprivate_register( ident_t *, 571 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 572 OMPRTL__kmpc_threadprivate_register, 573 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 574 OMPRTL__kmpc_global_thread_num, 575 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 576 // kmp_critical_name *crit); 577 OMPRTL__kmpc_critical, 578 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 579 // global_tid, kmp_critical_name *crit, uintptr_t hint); 580 OMPRTL__kmpc_critical_with_hint, 581 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 582 // kmp_critical_name *crit); 583 OMPRTL__kmpc_end_critical, 584 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 585 // global_tid); 586 OMPRTL__kmpc_cancel_barrier, 587 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 588 OMPRTL__kmpc_barrier, 589 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 590 OMPRTL__kmpc_for_static_fini, 591 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 592 // global_tid); 593 OMPRTL__kmpc_serialized_parallel, 594 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 595 // global_tid); 596 OMPRTL__kmpc_end_serialized_parallel, 597 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 598 // kmp_int32 num_threads); 599 OMPRTL__kmpc_push_num_threads, 600 // Call to void __kmpc_flush(ident_t *loc); 601 OMPRTL__kmpc_flush, 602 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 603 OMPRTL__kmpc_master, 604 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 605 OMPRTL__kmpc_end_master, 606 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 607 // int end_part); 608 OMPRTL__kmpc_omp_taskyield, 609 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 610 OMPRTL__kmpc_single, 611 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 612 OMPRTL__kmpc_end_single, 613 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 614 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 615 // kmp_routine_entry_t *task_entry); 616 OMPRTL__kmpc_omp_task_alloc, 617 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 618 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 619 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 620 // kmp_int64 device_id); 621 OMPRTL__kmpc_omp_target_task_alloc, 622 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 623 // new_task); 624 OMPRTL__kmpc_omp_task, 625 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 626 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 627 // kmp_int32 didit); 628 OMPRTL__kmpc_copyprivate, 629 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 630 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 631 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 632 OMPRTL__kmpc_reduce, 633 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 634 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 635 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 636 // *lck); 637 OMPRTL__kmpc_reduce_nowait, 638 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 639 // kmp_critical_name *lck); 640 OMPRTL__kmpc_end_reduce, 641 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 642 // kmp_critical_name *lck); 643 OMPRTL__kmpc_end_reduce_nowait, 644 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 645 // kmp_task_t * new_task); 646 OMPRTL__kmpc_omp_task_begin_if0, 647 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 648 // kmp_task_t * new_task); 649 OMPRTL__kmpc_omp_task_complete_if0, 650 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 651 OMPRTL__kmpc_ordered, 652 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 653 OMPRTL__kmpc_end_ordered, 654 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 655 // global_tid); 656 OMPRTL__kmpc_omp_taskwait, 657 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 658 OMPRTL__kmpc_taskgroup, 659 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 660 OMPRTL__kmpc_end_taskgroup, 661 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 662 // int proc_bind); 663 OMPRTL__kmpc_push_proc_bind, 664 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 665 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 666 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 667 OMPRTL__kmpc_omp_task_with_deps, 668 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 669 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 670 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 671 OMPRTL__kmpc_omp_wait_deps, 672 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 673 // global_tid, kmp_int32 cncl_kind); 674 OMPRTL__kmpc_cancellationpoint, 675 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 676 // kmp_int32 cncl_kind); 677 OMPRTL__kmpc_cancel, 678 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 679 // kmp_int32 num_teams, kmp_int32 thread_limit); 680 OMPRTL__kmpc_push_num_teams, 681 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 682 // microtask, ...); 683 OMPRTL__kmpc_fork_teams, 684 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 685 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 686 // sched, kmp_uint64 grainsize, void *task_dup); 687 OMPRTL__kmpc_taskloop, 688 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 689 // num_dims, struct kmp_dim *dims); 690 OMPRTL__kmpc_doacross_init, 691 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 692 OMPRTL__kmpc_doacross_fini, 693 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 694 // *vec); 695 OMPRTL__kmpc_doacross_post, 696 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 697 // *vec); 698 OMPRTL__kmpc_doacross_wait, 699 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 700 // *data); 701 OMPRTL__kmpc_task_reduction_init, 702 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 703 // *d); 704 OMPRTL__kmpc_task_reduction_get_th_data, 705 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 706 OMPRTL__kmpc_alloc, 707 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 708 OMPRTL__kmpc_free, 709 710 // 711 // Offloading related calls 712 // 713 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 714 // size); 715 OMPRTL__kmpc_push_target_tripcount, 716 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 717 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 718 // *arg_types); 719 OMPRTL__tgt_target, 720 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 721 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 722 // *arg_types); 723 OMPRTL__tgt_target_nowait, 724 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 725 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 726 // *arg_types, int32_t num_teams, int32_t thread_limit); 727 OMPRTL__tgt_target_teams, 728 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 729 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 730 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 731 OMPRTL__tgt_target_teams_nowait, 732 // Call to void __tgt_register_requires(int64_t flags); 733 OMPRTL__tgt_register_requires, 734 // Call to void __tgt_register_lib(__tgt_bin_desc *desc); 735 OMPRTL__tgt_register_lib, 736 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); 737 OMPRTL__tgt_unregister_lib, 738 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 739 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 740 OMPRTL__tgt_target_data_begin, 741 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 742 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 743 // *arg_types); 744 OMPRTL__tgt_target_data_begin_nowait, 745 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 746 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 747 OMPRTL__tgt_target_data_end, 748 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 749 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 750 // *arg_types); 751 OMPRTL__tgt_target_data_end_nowait, 752 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 753 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 754 OMPRTL__tgt_target_data_update, 755 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 756 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 757 // *arg_types); 758 OMPRTL__tgt_target_data_update_nowait, 759 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 760 OMPRTL__tgt_mapper_num_components, 761 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 762 // *base, void *begin, int64_t size, int64_t type); 763 OMPRTL__tgt_push_mapper_component, 764 }; 765 766 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 767 /// region. 768 class CleanupTy final : public EHScopeStack::Cleanup { 769 PrePostActionTy *Action; 770 771 public: 772 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 773 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 774 if (!CGF.HaveInsertPoint()) 775 return; 776 Action->Exit(CGF); 777 } 778 }; 779 780 } // anonymous namespace 781 782 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 783 CodeGenFunction::RunCleanupsScope Scope(CGF); 784 if (PrePostAction) { 785 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 786 Callback(CodeGen, CGF, *PrePostAction); 787 } else { 788 PrePostActionTy Action; 789 Callback(CodeGen, CGF, Action); 790 } 791 } 792 793 /// Check if the combiner is a call to UDR combiner and if it is so return the 794 /// UDR decl used for reduction. 795 static const OMPDeclareReductionDecl * 796 getReductionInit(const Expr *ReductionOp) { 797 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 798 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 799 if (const auto *DRE = 800 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 801 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 802 return DRD; 803 return nullptr; 804 } 805 806 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 807 const OMPDeclareReductionDecl *DRD, 808 const Expr *InitOp, 809 Address Private, Address Original, 810 QualType Ty) { 811 if (DRD->getInitializer()) { 812 std::pair<llvm::Function *, llvm::Function *> Reduction = 813 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 814 const auto *CE = cast<CallExpr>(InitOp); 815 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 816 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 817 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 818 const auto *LHSDRE = 819 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 820 const auto *RHSDRE = 821 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 822 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 823 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 824 [=]() { return Private; }); 825 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 826 [=]() { return Original; }); 827 (void)PrivateScope.Privatize(); 828 RValue Func = RValue::get(Reduction.second); 829 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 830 CGF.EmitIgnoredExpr(InitOp); 831 } else { 832 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 833 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 834 auto *GV = new llvm::GlobalVariable( 835 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 836 llvm::GlobalValue::PrivateLinkage, Init, Name); 837 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 838 RValue InitRVal; 839 switch (CGF.getEvaluationKind(Ty)) { 840 case TEK_Scalar: 841 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 842 break; 843 case TEK_Complex: 844 InitRVal = 845 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 846 break; 847 case TEK_Aggregate: 848 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 849 break; 850 } 851 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 852 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 853 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 854 /*IsInitializer=*/false); 855 } 856 } 857 858 /// Emit initialization of arrays of complex types. 859 /// \param DestAddr Address of the array. 860 /// \param Type Type of array. 861 /// \param Init Initial expression of array. 862 /// \param SrcAddr Address of the original array. 863 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 864 QualType Type, bool EmitDeclareReductionInit, 865 const Expr *Init, 866 const OMPDeclareReductionDecl *DRD, 867 Address SrcAddr = Address::invalid()) { 868 // Perform element-by-element initialization. 869 QualType ElementTy; 870 871 // Drill down to the base element type on both arrays. 872 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 873 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 874 DestAddr = 875 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 876 if (DRD) 877 SrcAddr = 878 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 879 880 llvm::Value *SrcBegin = nullptr; 881 if (DRD) 882 SrcBegin = SrcAddr.getPointer(); 883 llvm::Value *DestBegin = DestAddr.getPointer(); 884 // Cast from pointer to array type to pointer to single element. 885 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 886 // The basic structure here is a while-do loop. 887 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 888 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 889 llvm::Value *IsEmpty = 890 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 891 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 892 893 // Enter the loop body, making that address the current address. 894 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 895 CGF.EmitBlock(BodyBB); 896 897 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 898 899 llvm::PHINode *SrcElementPHI = nullptr; 900 Address SrcElementCurrent = Address::invalid(); 901 if (DRD) { 902 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 903 "omp.arraycpy.srcElementPast"); 904 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 905 SrcElementCurrent = 906 Address(SrcElementPHI, 907 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 908 } 909 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 910 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 911 DestElementPHI->addIncoming(DestBegin, EntryBB); 912 Address DestElementCurrent = 913 Address(DestElementPHI, 914 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 915 916 // Emit copy. 917 { 918 CodeGenFunction::RunCleanupsScope InitScope(CGF); 919 if (EmitDeclareReductionInit) { 920 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 921 SrcElementCurrent, ElementTy); 922 } else 923 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 924 /*IsInitializer=*/false); 925 } 926 927 if (DRD) { 928 // Shift the address forward by one element. 929 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 930 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 931 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 932 } 933 934 // Shift the address forward by one element. 935 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 936 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 937 // Check whether we've reached the end. 938 llvm::Value *Done = 939 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 940 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 941 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 942 943 // Done. 944 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 945 } 946 947 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 948 return CGF.EmitOMPSharedLValue(E); 949 } 950 951 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 952 const Expr *E) { 953 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 954 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 955 return LValue(); 956 } 957 958 void ReductionCodeGen::emitAggregateInitialization( 959 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 960 const OMPDeclareReductionDecl *DRD) { 961 // Emit VarDecl with copy init for arrays. 962 // Get the address of the original variable captured in current 963 // captured region. 964 const auto *PrivateVD = 965 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 966 bool EmitDeclareReductionInit = 967 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 968 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 969 EmitDeclareReductionInit, 970 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 971 : PrivateVD->getInit(), 972 DRD, SharedLVal.getAddress(CGF)); 973 } 974 975 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 976 ArrayRef<const Expr *> Privates, 977 ArrayRef<const Expr *> ReductionOps) { 978 ClausesData.reserve(Shareds.size()); 979 SharedAddresses.reserve(Shareds.size()); 980 Sizes.reserve(Shareds.size()); 981 BaseDecls.reserve(Shareds.size()); 982 auto IPriv = Privates.begin(); 983 auto IRed = ReductionOps.begin(); 984 for (const Expr *Ref : Shareds) { 985 ClausesData.emplace_back(Ref, *IPriv, *IRed); 986 std::advance(IPriv, 1); 987 std::advance(IRed, 1); 988 } 989 } 990 991 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 992 assert(SharedAddresses.size() == N && 993 "Number of generated lvalues must be exactly N."); 994 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 995 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 996 SharedAddresses.emplace_back(First, Second); 997 } 998 999 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 1000 const auto *PrivateVD = 1001 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1002 QualType PrivateType = PrivateVD->getType(); 1003 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1004 if (!PrivateType->isVariablyModifiedType()) { 1005 Sizes.emplace_back( 1006 CGF.getTypeSize( 1007 SharedAddresses[N].first.getType().getNonReferenceType()), 1008 nullptr); 1009 return; 1010 } 1011 llvm::Value *Size; 1012 llvm::Value *SizeInChars; 1013 auto *ElemType = cast<llvm::PointerType>( 1014 SharedAddresses[N].first.getPointer(CGF)->getType()) 1015 ->getElementType(); 1016 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1017 if (AsArraySection) { 1018 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF), 1019 SharedAddresses[N].first.getPointer(CGF)); 1020 Size = CGF.Builder.CreateNUWAdd( 1021 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1022 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1023 } else { 1024 SizeInChars = CGF.getTypeSize( 1025 SharedAddresses[N].first.getType().getNonReferenceType()); 1026 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1027 } 1028 Sizes.emplace_back(SizeInChars, Size); 1029 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1030 CGF, 1031 cast<OpaqueValueExpr>( 1032 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1033 RValue::get(Size)); 1034 CGF.EmitVariablyModifiedType(PrivateType); 1035 } 1036 1037 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1038 llvm::Value *Size) { 1039 const auto *PrivateVD = 1040 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1041 QualType PrivateType = PrivateVD->getType(); 1042 if (!PrivateType->isVariablyModifiedType()) { 1043 assert(!Size && !Sizes[N].second && 1044 "Size should be nullptr for non-variably modified reduction " 1045 "items."); 1046 return; 1047 } 1048 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1049 CGF, 1050 cast<OpaqueValueExpr>( 1051 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1052 RValue::get(Size)); 1053 CGF.EmitVariablyModifiedType(PrivateType); 1054 } 1055 1056 void ReductionCodeGen::emitInitialization( 1057 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1058 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1059 assert(SharedAddresses.size() > N && "No variable was generated"); 1060 const auto *PrivateVD = 1061 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1062 const OMPDeclareReductionDecl *DRD = 1063 getReductionInit(ClausesData[N].ReductionOp); 1064 QualType PrivateType = PrivateVD->getType(); 1065 PrivateAddr = CGF.Builder.CreateElementBitCast( 1066 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1067 QualType SharedType = SharedAddresses[N].first.getType(); 1068 SharedLVal = CGF.MakeAddrLValue( 1069 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 1070 CGF.ConvertTypeForMem(SharedType)), 1071 SharedType, SharedAddresses[N].first.getBaseInfo(), 1072 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1073 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1074 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1075 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1076 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1077 PrivateAddr, SharedLVal.getAddress(CGF), 1078 SharedLVal.getType()); 1079 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1080 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1081 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1082 PrivateVD->getType().getQualifiers(), 1083 /*IsInitializer=*/false); 1084 } 1085 } 1086 1087 bool ReductionCodeGen::needCleanups(unsigned N) { 1088 const auto *PrivateVD = 1089 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1090 QualType PrivateType = PrivateVD->getType(); 1091 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1092 return DTorKind != QualType::DK_none; 1093 } 1094 1095 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1096 Address PrivateAddr) { 1097 const auto *PrivateVD = 1098 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1099 QualType PrivateType = PrivateVD->getType(); 1100 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1101 if (needCleanups(N)) { 1102 PrivateAddr = CGF.Builder.CreateElementBitCast( 1103 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1104 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1105 } 1106 } 1107 1108 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1109 LValue BaseLV) { 1110 BaseTy = BaseTy.getNonReferenceType(); 1111 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1112 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1113 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1114 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 1115 } else { 1116 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 1117 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1118 } 1119 BaseTy = BaseTy->getPointeeType(); 1120 } 1121 return CGF.MakeAddrLValue( 1122 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 1123 CGF.ConvertTypeForMem(ElTy)), 1124 BaseLV.getType(), BaseLV.getBaseInfo(), 1125 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1126 } 1127 1128 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1129 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1130 llvm::Value *Addr) { 1131 Address Tmp = Address::invalid(); 1132 Address TopTmp = Address::invalid(); 1133 Address MostTopTmp = Address::invalid(); 1134 BaseTy = BaseTy.getNonReferenceType(); 1135 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1136 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1137 Tmp = CGF.CreateMemTemp(BaseTy); 1138 if (TopTmp.isValid()) 1139 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1140 else 1141 MostTopTmp = Tmp; 1142 TopTmp = Tmp; 1143 BaseTy = BaseTy->getPointeeType(); 1144 } 1145 llvm::Type *Ty = BaseLVType; 1146 if (Tmp.isValid()) 1147 Ty = Tmp.getElementType(); 1148 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1149 if (Tmp.isValid()) { 1150 CGF.Builder.CreateStore(Addr, Tmp); 1151 return MostTopTmp; 1152 } 1153 return Address(Addr, BaseLVAlignment); 1154 } 1155 1156 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1157 const VarDecl *OrigVD = nullptr; 1158 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1159 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1160 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1161 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1162 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1163 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1164 DE = cast<DeclRefExpr>(Base); 1165 OrigVD = cast<VarDecl>(DE->getDecl()); 1166 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1167 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1168 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1169 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1170 DE = cast<DeclRefExpr>(Base); 1171 OrigVD = cast<VarDecl>(DE->getDecl()); 1172 } 1173 return OrigVD; 1174 } 1175 1176 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1177 Address PrivateAddr) { 1178 const DeclRefExpr *DE; 1179 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1180 BaseDecls.emplace_back(OrigVD); 1181 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1182 LValue BaseLValue = 1183 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1184 OriginalBaseLValue); 1185 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1186 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1187 llvm::Value *PrivatePointer = 1188 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1189 PrivateAddr.getPointer(), 1190 SharedAddresses[N].first.getAddress(CGF).getType()); 1191 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1192 return castToBase(CGF, OrigVD->getType(), 1193 SharedAddresses[N].first.getType(), 1194 OriginalBaseLValue.getAddress(CGF).getType(), 1195 OriginalBaseLValue.getAlignment(), Ptr); 1196 } 1197 BaseDecls.emplace_back( 1198 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1199 return PrivateAddr; 1200 } 1201 1202 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1203 const OMPDeclareReductionDecl *DRD = 1204 getReductionInit(ClausesData[N].ReductionOp); 1205 return DRD && DRD->getInitializer(); 1206 } 1207 1208 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1209 return CGF.EmitLoadOfPointerLValue( 1210 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1211 getThreadIDVariable()->getType()->castAs<PointerType>()); 1212 } 1213 1214 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1215 if (!CGF.HaveInsertPoint()) 1216 return; 1217 // 1.2.2 OpenMP Language Terminology 1218 // Structured block - An executable statement with a single entry at the 1219 // top and a single exit at the bottom. 1220 // The point of exit cannot be a branch out of the structured block. 1221 // longjmp() and throw() must not violate the entry/exit criteria. 1222 CGF.EHStack.pushTerminate(); 1223 CodeGen(CGF); 1224 CGF.EHStack.popTerminate(); 1225 } 1226 1227 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1228 CodeGenFunction &CGF) { 1229 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1230 getThreadIDVariable()->getType(), 1231 AlignmentSource::Decl); 1232 } 1233 1234 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1235 QualType FieldTy) { 1236 auto *Field = FieldDecl::Create( 1237 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1238 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1239 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1240 Field->setAccess(AS_public); 1241 DC->addDecl(Field); 1242 return Field; 1243 } 1244 1245 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1246 StringRef Separator) 1247 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1248 OffloadEntriesInfoManager(CGM) { 1249 ASTContext &C = CGM.getContext(); 1250 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1251 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1252 RD->startDefinition(); 1253 // reserved_1 1254 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1255 // flags 1256 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1257 // reserved_2 1258 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1259 // reserved_3 1260 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1261 // psource 1262 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1263 RD->completeDefinition(); 1264 IdentQTy = C.getRecordType(RD); 1265 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1266 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1267 1268 loadOffloadInfoMetadata(); 1269 } 1270 1271 bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD, 1272 const GlobalDecl &OldGD, 1273 llvm::GlobalValue *OrigAddr, 1274 bool IsForDefinition) { 1275 // Emit at least a definition for the aliasee if the the address of the 1276 // original function is requested. 1277 if (IsForDefinition || OrigAddr) 1278 (void)CGM.GetAddrOfGlobal(NewGD); 1279 StringRef NewMangledName = CGM.getMangledName(NewGD); 1280 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1281 if (Addr && !Addr->isDeclaration()) { 1282 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1283 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(NewGD); 1284 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1285 1286 // Create a reference to the named value. This ensures that it is emitted 1287 // if a deferred decl. 1288 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1289 1290 // Create the new alias itself, but don't set a name yet. 1291 auto *GA = 1292 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1293 1294 if (OrigAddr) { 1295 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1296 1297 GA->takeName(OrigAddr); 1298 OrigAddr->replaceAllUsesWith( 1299 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1300 OrigAddr->eraseFromParent(); 1301 } else { 1302 GA->setName(CGM.getMangledName(OldGD)); 1303 } 1304 1305 // Set attributes which are particular to an alias; this is a 1306 // specialization of the attributes which may be set on a global function. 1307 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1308 D->isWeakImported()) 1309 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1310 1311 CGM.SetCommonAttributes(OldGD, GA); 1312 return true; 1313 } 1314 return false; 1315 } 1316 1317 void CGOpenMPRuntime::clear() { 1318 InternalVars.clear(); 1319 // Clean non-target variable declarations possibly used only in debug info. 1320 for (const auto &Data : EmittedNonTargetVariables) { 1321 if (!Data.getValue().pointsToAliveValue()) 1322 continue; 1323 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1324 if (!GV) 1325 continue; 1326 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1327 continue; 1328 GV->eraseFromParent(); 1329 } 1330 // Emit aliases for the deferred aliasees. 1331 for (const auto &Pair : DeferredVariantFunction) { 1332 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1333 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1334 // If not able to emit alias, just emit original declaration. 1335 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr, 1336 /*IsForDefinition=*/false); 1337 } 1338 } 1339 1340 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1341 SmallString<128> Buffer; 1342 llvm::raw_svector_ostream OS(Buffer); 1343 StringRef Sep = FirstSeparator; 1344 for (StringRef Part : Parts) { 1345 OS << Sep << Part; 1346 Sep = Separator; 1347 } 1348 return OS.str(); 1349 } 1350 1351 static llvm::Function * 1352 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1353 const Expr *CombinerInitializer, const VarDecl *In, 1354 const VarDecl *Out, bool IsCombiner) { 1355 // void .omp_combiner.(Ty *in, Ty *out); 1356 ASTContext &C = CGM.getContext(); 1357 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1358 FunctionArgList Args; 1359 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1360 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1361 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1362 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1363 Args.push_back(&OmpOutParm); 1364 Args.push_back(&OmpInParm); 1365 const CGFunctionInfo &FnInfo = 1366 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1367 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1368 std::string Name = CGM.getOpenMPRuntime().getName( 1369 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1370 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1371 Name, &CGM.getModule()); 1372 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1373 if (CGM.getLangOpts().Optimize) { 1374 Fn->removeFnAttr(llvm::Attribute::NoInline); 1375 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1376 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1377 } 1378 CodeGenFunction CGF(CGM); 1379 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1380 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1381 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1382 Out->getLocation()); 1383 CodeGenFunction::OMPPrivateScope Scope(CGF); 1384 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1385 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1386 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1387 .getAddress(CGF); 1388 }); 1389 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1390 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1391 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1392 .getAddress(CGF); 1393 }); 1394 (void)Scope.Privatize(); 1395 if (!IsCombiner && Out->hasInit() && 1396 !CGF.isTrivialInitializer(Out->getInit())) { 1397 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1398 Out->getType().getQualifiers(), 1399 /*IsInitializer=*/true); 1400 } 1401 if (CombinerInitializer) 1402 CGF.EmitIgnoredExpr(CombinerInitializer); 1403 Scope.ForceCleanup(); 1404 CGF.FinishFunction(); 1405 return Fn; 1406 } 1407 1408 void CGOpenMPRuntime::emitUserDefinedReduction( 1409 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1410 if (UDRMap.count(D) > 0) 1411 return; 1412 llvm::Function *Combiner = emitCombinerOrInitializer( 1413 CGM, D->getType(), D->getCombiner(), 1414 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1415 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1416 /*IsCombiner=*/true); 1417 llvm::Function *Initializer = nullptr; 1418 if (const Expr *Init = D->getInitializer()) { 1419 Initializer = emitCombinerOrInitializer( 1420 CGM, D->getType(), 1421 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1422 : nullptr, 1423 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1424 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1425 /*IsCombiner=*/false); 1426 } 1427 UDRMap.try_emplace(D, Combiner, Initializer); 1428 if (CGF) { 1429 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1430 Decls.second.push_back(D); 1431 } 1432 } 1433 1434 std::pair<llvm::Function *, llvm::Function *> 1435 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1436 auto I = UDRMap.find(D); 1437 if (I != UDRMap.end()) 1438 return I->second; 1439 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1440 return UDRMap.lookup(D); 1441 } 1442 1443 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1444 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1445 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1446 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1447 assert(ThreadIDVar->getType()->isPointerType() && 1448 "thread id variable must be of type kmp_int32 *"); 1449 CodeGenFunction CGF(CGM, true); 1450 bool HasCancel = false; 1451 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1452 HasCancel = OPD->hasCancel(); 1453 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1454 HasCancel = OPSD->hasCancel(); 1455 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1456 HasCancel = OPFD->hasCancel(); 1457 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1458 HasCancel = OPFD->hasCancel(); 1459 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1460 HasCancel = OPFD->hasCancel(); 1461 else if (const auto *OPFD = 1462 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1463 HasCancel = OPFD->hasCancel(); 1464 else if (const auto *OPFD = 1465 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1466 HasCancel = OPFD->hasCancel(); 1467 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1468 HasCancel, OutlinedHelperName); 1469 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1470 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 1471 } 1472 1473 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1474 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1475 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1476 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1477 return emitParallelOrTeamsOutlinedFunction( 1478 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1479 } 1480 1481 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1482 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1483 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1484 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1485 return emitParallelOrTeamsOutlinedFunction( 1486 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1487 } 1488 1489 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1490 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1491 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1492 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1493 bool Tied, unsigned &NumberOfParts) { 1494 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1495 PrePostActionTy &) { 1496 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1497 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1498 llvm::Value *TaskArgs[] = { 1499 UpLoc, ThreadID, 1500 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1501 TaskTVar->getType()->castAs<PointerType>()) 1502 .getPointer(CGF)}; 1503 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1504 }; 1505 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1506 UntiedCodeGen); 1507 CodeGen.setAction(Action); 1508 assert(!ThreadIDVar->getType()->isPointerType() && 1509 "thread id variable must be of type kmp_int32 for tasks"); 1510 const OpenMPDirectiveKind Region = 1511 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1512 : OMPD_task; 1513 const CapturedStmt *CS = D.getCapturedStmt(Region); 1514 const auto *TD = dyn_cast<OMPTaskDirective>(&D); 1515 CodeGenFunction CGF(CGM, true); 1516 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1517 InnermostKind, 1518 TD ? TD->hasCancel() : false, Action); 1519 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1520 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1521 if (!Tied) 1522 NumberOfParts = Action.getNumberOfParts(); 1523 return Res; 1524 } 1525 1526 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1527 const RecordDecl *RD, const CGRecordLayout &RL, 1528 ArrayRef<llvm::Constant *> Data) { 1529 llvm::StructType *StructTy = RL.getLLVMType(); 1530 unsigned PrevIdx = 0; 1531 ConstantInitBuilder CIBuilder(CGM); 1532 auto DI = Data.begin(); 1533 for (const FieldDecl *FD : RD->fields()) { 1534 unsigned Idx = RL.getLLVMFieldNo(FD); 1535 // Fill the alignment. 1536 for (unsigned I = PrevIdx; I < Idx; ++I) 1537 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1538 PrevIdx = Idx + 1; 1539 Fields.add(*DI); 1540 ++DI; 1541 } 1542 } 1543 1544 template <class... As> 1545 static llvm::GlobalVariable * 1546 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1547 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1548 As &&... Args) { 1549 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1550 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1551 ConstantInitBuilder CIBuilder(CGM); 1552 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1553 buildStructValue(Fields, CGM, RD, RL, Data); 1554 return Fields.finishAndCreateGlobal( 1555 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1556 std::forward<As>(Args)...); 1557 } 1558 1559 template <typename T> 1560 static void 1561 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1562 ArrayRef<llvm::Constant *> Data, 1563 T &Parent) { 1564 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1565 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1566 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1567 buildStructValue(Fields, CGM, RD, RL, Data); 1568 Fields.finishAndAddTo(Parent); 1569 } 1570 1571 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1572 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1573 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1574 FlagsTy FlagsKey(Flags, Reserved2Flags); 1575 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1576 if (!Entry) { 1577 if (!DefaultOpenMPPSource) { 1578 // Initialize default location for psource field of ident_t structure of 1579 // all ident_t objects. Format is ";file;function;line;column;;". 1580 // Taken from 1581 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1582 DefaultOpenMPPSource = 1583 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1584 DefaultOpenMPPSource = 1585 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1586 } 1587 1588 llvm::Constant *Data[] = { 1589 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1590 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1591 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1592 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1593 llvm::GlobalValue *DefaultOpenMPLocation = 1594 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1595 llvm::GlobalValue::PrivateLinkage); 1596 DefaultOpenMPLocation->setUnnamedAddr( 1597 llvm::GlobalValue::UnnamedAddr::Global); 1598 1599 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1600 } 1601 return Address(Entry, Align); 1602 } 1603 1604 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1605 bool AtCurrentPoint) { 1606 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1607 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1608 1609 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1610 if (AtCurrentPoint) { 1611 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1612 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1613 } else { 1614 Elem.second.ServiceInsertPt = 1615 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1616 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1617 } 1618 } 1619 1620 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1621 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1622 if (Elem.second.ServiceInsertPt) { 1623 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1624 Elem.second.ServiceInsertPt = nullptr; 1625 Ptr->eraseFromParent(); 1626 } 1627 } 1628 1629 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1630 SourceLocation Loc, 1631 unsigned Flags) { 1632 Flags |= OMP_IDENT_KMPC; 1633 // If no debug info is generated - return global default location. 1634 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1635 Loc.isInvalid()) 1636 return getOrCreateDefaultLocation(Flags).getPointer(); 1637 1638 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1639 1640 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1641 Address LocValue = Address::invalid(); 1642 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1643 if (I != OpenMPLocThreadIDMap.end()) 1644 LocValue = Address(I->second.DebugLoc, Align); 1645 1646 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1647 // GetOpenMPThreadID was called before this routine. 1648 if (!LocValue.isValid()) { 1649 // Generate "ident_t .kmpc_loc.addr;" 1650 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1651 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1652 Elem.second.DebugLoc = AI.getPointer(); 1653 LocValue = AI; 1654 1655 if (!Elem.second.ServiceInsertPt) 1656 setLocThreadIdInsertPt(CGF); 1657 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1658 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1659 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1660 CGF.getTypeSize(IdentQTy)); 1661 } 1662 1663 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1664 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1665 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1666 LValue PSource = 1667 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1668 1669 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1670 if (OMPDebugLoc == nullptr) { 1671 SmallString<128> Buffer2; 1672 llvm::raw_svector_ostream OS2(Buffer2); 1673 // Build debug location 1674 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1675 OS2 << ";" << PLoc.getFilename() << ";"; 1676 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1677 OS2 << FD->getQualifiedNameAsString(); 1678 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1679 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1680 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1681 } 1682 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1683 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1684 1685 // Our callers always pass this to a runtime function, so for 1686 // convenience, go ahead and return a naked pointer. 1687 return LocValue.getPointer(); 1688 } 1689 1690 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1691 SourceLocation Loc) { 1692 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1693 1694 llvm::Value *ThreadID = nullptr; 1695 // Check whether we've already cached a load of the thread id in this 1696 // function. 1697 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1698 if (I != OpenMPLocThreadIDMap.end()) { 1699 ThreadID = I->second.ThreadID; 1700 if (ThreadID != nullptr) 1701 return ThreadID; 1702 } 1703 // If exceptions are enabled, do not use parameter to avoid possible crash. 1704 if (auto *OMPRegionInfo = 1705 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1706 if (OMPRegionInfo->getThreadIDVariable()) { 1707 // Check if this an outlined function with thread id passed as argument. 1708 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1709 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1710 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1711 !CGF.getLangOpts().CXXExceptions || 1712 CGF.Builder.GetInsertBlock() == TopBlock || 1713 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1714 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1715 TopBlock || 1716 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1717 CGF.Builder.GetInsertBlock()) { 1718 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1719 // If value loaded in entry block, cache it and use it everywhere in 1720 // function. 1721 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1722 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1723 Elem.second.ThreadID = ThreadID; 1724 } 1725 return ThreadID; 1726 } 1727 } 1728 } 1729 1730 // This is not an outlined function region - need to call __kmpc_int32 1731 // kmpc_global_thread_num(ident_t *loc). 1732 // Generate thread id value and cache this value for use across the 1733 // function. 1734 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1735 if (!Elem.second.ServiceInsertPt) 1736 setLocThreadIdInsertPt(CGF); 1737 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1738 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1739 llvm::CallInst *Call = CGF.Builder.CreateCall( 1740 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1741 emitUpdateLocation(CGF, Loc)); 1742 Call->setCallingConv(CGF.getRuntimeCC()); 1743 Elem.second.ThreadID = Call; 1744 return Call; 1745 } 1746 1747 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1748 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1749 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1750 clearLocThreadIdInsertPt(CGF); 1751 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1752 } 1753 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1754 for(auto *D : FunctionUDRMap[CGF.CurFn]) 1755 UDRMap.erase(D); 1756 FunctionUDRMap.erase(CGF.CurFn); 1757 } 1758 auto I = FunctionUDMMap.find(CGF.CurFn); 1759 if (I != FunctionUDMMap.end()) { 1760 for(auto *D : I->second) 1761 UDMMap.erase(D); 1762 FunctionUDMMap.erase(I); 1763 } 1764 } 1765 1766 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1767 return IdentTy->getPointerTo(); 1768 } 1769 1770 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1771 if (!Kmpc_MicroTy) { 1772 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1773 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1774 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1775 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1776 } 1777 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1778 } 1779 1780 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1781 llvm::FunctionCallee RTLFn = nullptr; 1782 switch (static_cast<OpenMPRTLFunction>(Function)) { 1783 case OMPRTL__kmpc_fork_call: { 1784 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1785 // microtask, ...); 1786 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1787 getKmpc_MicroPointerTy()}; 1788 auto *FnTy = 1789 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1790 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1791 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1792 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1793 llvm::LLVMContext &Ctx = F->getContext(); 1794 llvm::MDBuilder MDB(Ctx); 1795 // Annotate the callback behavior of the __kmpc_fork_call: 1796 // - The callback callee is argument number 2 (microtask). 1797 // - The first two arguments of the callback callee are unknown (-1). 1798 // - All variadic arguments to the __kmpc_fork_call are passed to the 1799 // callback callee. 1800 F->addMetadata( 1801 llvm::LLVMContext::MD_callback, 1802 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1803 2, {-1, -1}, 1804 /* VarArgsArePassed */ true)})); 1805 } 1806 } 1807 break; 1808 } 1809 case OMPRTL__kmpc_global_thread_num: { 1810 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1811 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1812 auto *FnTy = 1813 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1814 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1815 break; 1816 } 1817 case OMPRTL__kmpc_threadprivate_cached: { 1818 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1819 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1820 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1821 CGM.VoidPtrTy, CGM.SizeTy, 1822 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1823 auto *FnTy = 1824 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1825 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1826 break; 1827 } 1828 case OMPRTL__kmpc_critical: { 1829 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1830 // kmp_critical_name *crit); 1831 llvm::Type *TypeParams[] = { 1832 getIdentTyPointerTy(), CGM.Int32Ty, 1833 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1834 auto *FnTy = 1835 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1836 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1837 break; 1838 } 1839 case OMPRTL__kmpc_critical_with_hint: { 1840 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1841 // kmp_critical_name *crit, uintptr_t hint); 1842 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1843 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1844 CGM.IntPtrTy}; 1845 auto *FnTy = 1846 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1847 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1848 break; 1849 } 1850 case OMPRTL__kmpc_threadprivate_register: { 1851 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1852 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1853 // typedef void *(*kmpc_ctor)(void *); 1854 auto *KmpcCtorTy = 1855 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1856 /*isVarArg*/ false)->getPointerTo(); 1857 // typedef void *(*kmpc_cctor)(void *, void *); 1858 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1859 auto *KmpcCopyCtorTy = 1860 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1861 /*isVarArg*/ false) 1862 ->getPointerTo(); 1863 // typedef void (*kmpc_dtor)(void *); 1864 auto *KmpcDtorTy = 1865 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1866 ->getPointerTo(); 1867 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1868 KmpcCopyCtorTy, KmpcDtorTy}; 1869 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1870 /*isVarArg*/ false); 1871 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1872 break; 1873 } 1874 case OMPRTL__kmpc_end_critical: { 1875 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1876 // kmp_critical_name *crit); 1877 llvm::Type *TypeParams[] = { 1878 getIdentTyPointerTy(), CGM.Int32Ty, 1879 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1880 auto *FnTy = 1881 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1882 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1883 break; 1884 } 1885 case OMPRTL__kmpc_cancel_barrier: { 1886 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1887 // global_tid); 1888 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1889 auto *FnTy = 1890 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1891 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1892 break; 1893 } 1894 case OMPRTL__kmpc_barrier: { 1895 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1896 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1897 auto *FnTy = 1898 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1899 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1900 break; 1901 } 1902 case OMPRTL__kmpc_for_static_fini: { 1903 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1904 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1905 auto *FnTy = 1906 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1907 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1908 break; 1909 } 1910 case OMPRTL__kmpc_push_num_threads: { 1911 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1912 // kmp_int32 num_threads) 1913 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1914 CGM.Int32Ty}; 1915 auto *FnTy = 1916 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1917 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1918 break; 1919 } 1920 case OMPRTL__kmpc_serialized_parallel: { 1921 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1922 // global_tid); 1923 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1924 auto *FnTy = 1925 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1926 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1927 break; 1928 } 1929 case OMPRTL__kmpc_end_serialized_parallel: { 1930 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1931 // global_tid); 1932 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1933 auto *FnTy = 1934 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1935 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1936 break; 1937 } 1938 case OMPRTL__kmpc_flush: { 1939 // Build void __kmpc_flush(ident_t *loc); 1940 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1941 auto *FnTy = 1942 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1943 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1944 break; 1945 } 1946 case OMPRTL__kmpc_master: { 1947 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1948 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1949 auto *FnTy = 1950 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1951 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 1952 break; 1953 } 1954 case OMPRTL__kmpc_end_master: { 1955 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 1956 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1957 auto *FnTy = 1958 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1959 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 1960 break; 1961 } 1962 case OMPRTL__kmpc_omp_taskyield: { 1963 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 1964 // int end_part); 1965 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1966 auto *FnTy = 1967 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1968 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 1969 break; 1970 } 1971 case OMPRTL__kmpc_single: { 1972 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 1973 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1974 auto *FnTy = 1975 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1976 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 1977 break; 1978 } 1979 case OMPRTL__kmpc_end_single: { 1980 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 1981 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1982 auto *FnTy = 1983 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1984 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 1985 break; 1986 } 1987 case OMPRTL__kmpc_omp_task_alloc: { 1988 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 1989 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1990 // kmp_routine_entry_t *task_entry); 1991 assert(KmpRoutineEntryPtrTy != nullptr && 1992 "Type kmp_routine_entry_t must be created."); 1993 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1994 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 1995 // Return void * and then cast to particular kmp_task_t type. 1996 auto *FnTy = 1997 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1998 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 1999 break; 2000 } 2001 case OMPRTL__kmpc_omp_target_task_alloc: { 2002 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 2003 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2004 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 2005 assert(KmpRoutineEntryPtrTy != nullptr && 2006 "Type kmp_routine_entry_t must be created."); 2007 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2008 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 2009 CGM.Int64Ty}; 2010 // Return void * and then cast to particular kmp_task_t type. 2011 auto *FnTy = 2012 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2013 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2014 break; 2015 } 2016 case OMPRTL__kmpc_omp_task: { 2017 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2018 // *new_task); 2019 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2020 CGM.VoidPtrTy}; 2021 auto *FnTy = 2022 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2023 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2024 break; 2025 } 2026 case OMPRTL__kmpc_copyprivate: { 2027 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2028 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2029 // kmp_int32 didit); 2030 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2031 auto *CpyFnTy = 2032 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2033 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2034 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2035 CGM.Int32Ty}; 2036 auto *FnTy = 2037 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2038 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2039 break; 2040 } 2041 case OMPRTL__kmpc_reduce: { 2042 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2043 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2044 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2045 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2046 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2047 /*isVarArg=*/false); 2048 llvm::Type *TypeParams[] = { 2049 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2050 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2051 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2052 auto *FnTy = 2053 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2054 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2055 break; 2056 } 2057 case OMPRTL__kmpc_reduce_nowait: { 2058 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2059 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2060 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2061 // *lck); 2062 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2063 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2064 /*isVarArg=*/false); 2065 llvm::Type *TypeParams[] = { 2066 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2067 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2068 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2069 auto *FnTy = 2070 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2071 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2072 break; 2073 } 2074 case OMPRTL__kmpc_end_reduce: { 2075 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2076 // kmp_critical_name *lck); 2077 llvm::Type *TypeParams[] = { 2078 getIdentTyPointerTy(), CGM.Int32Ty, 2079 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2080 auto *FnTy = 2081 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2082 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2083 break; 2084 } 2085 case OMPRTL__kmpc_end_reduce_nowait: { 2086 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2087 // kmp_critical_name *lck); 2088 llvm::Type *TypeParams[] = { 2089 getIdentTyPointerTy(), CGM.Int32Ty, 2090 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2091 auto *FnTy = 2092 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2093 RTLFn = 2094 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2095 break; 2096 } 2097 case OMPRTL__kmpc_omp_task_begin_if0: { 2098 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2099 // *new_task); 2100 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2101 CGM.VoidPtrTy}; 2102 auto *FnTy = 2103 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2104 RTLFn = 2105 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2106 break; 2107 } 2108 case OMPRTL__kmpc_omp_task_complete_if0: { 2109 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2110 // *new_task); 2111 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2112 CGM.VoidPtrTy}; 2113 auto *FnTy = 2114 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2115 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2116 /*Name=*/"__kmpc_omp_task_complete_if0"); 2117 break; 2118 } 2119 case OMPRTL__kmpc_ordered: { 2120 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2121 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2122 auto *FnTy = 2123 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2124 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2125 break; 2126 } 2127 case OMPRTL__kmpc_end_ordered: { 2128 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2129 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2130 auto *FnTy = 2131 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2132 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2133 break; 2134 } 2135 case OMPRTL__kmpc_omp_taskwait: { 2136 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2137 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2138 auto *FnTy = 2139 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2140 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2141 break; 2142 } 2143 case OMPRTL__kmpc_taskgroup: { 2144 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2145 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2146 auto *FnTy = 2147 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2148 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2149 break; 2150 } 2151 case OMPRTL__kmpc_end_taskgroup: { 2152 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2153 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2154 auto *FnTy = 2155 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2156 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2157 break; 2158 } 2159 case OMPRTL__kmpc_push_proc_bind: { 2160 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2161 // int proc_bind) 2162 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2163 auto *FnTy = 2164 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2165 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2166 break; 2167 } 2168 case OMPRTL__kmpc_omp_task_with_deps: { 2169 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2170 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2171 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2172 llvm::Type *TypeParams[] = { 2173 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2174 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2175 auto *FnTy = 2176 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2177 RTLFn = 2178 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2179 break; 2180 } 2181 case OMPRTL__kmpc_omp_wait_deps: { 2182 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2183 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2184 // kmp_depend_info_t *noalias_dep_list); 2185 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2186 CGM.Int32Ty, CGM.VoidPtrTy, 2187 CGM.Int32Ty, CGM.VoidPtrTy}; 2188 auto *FnTy = 2189 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2190 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2191 break; 2192 } 2193 case OMPRTL__kmpc_cancellationpoint: { 2194 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2195 // global_tid, kmp_int32 cncl_kind) 2196 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2197 auto *FnTy = 2198 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2199 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2200 break; 2201 } 2202 case OMPRTL__kmpc_cancel: { 2203 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2204 // kmp_int32 cncl_kind) 2205 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2206 auto *FnTy = 2207 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2208 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2209 break; 2210 } 2211 case OMPRTL__kmpc_push_num_teams: { 2212 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2213 // kmp_int32 num_teams, kmp_int32 num_threads) 2214 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2215 CGM.Int32Ty}; 2216 auto *FnTy = 2217 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2218 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2219 break; 2220 } 2221 case OMPRTL__kmpc_fork_teams: { 2222 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2223 // microtask, ...); 2224 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2225 getKmpc_MicroPointerTy()}; 2226 auto *FnTy = 2227 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2228 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2229 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2230 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2231 llvm::LLVMContext &Ctx = F->getContext(); 2232 llvm::MDBuilder MDB(Ctx); 2233 // Annotate the callback behavior of the __kmpc_fork_teams: 2234 // - The callback callee is argument number 2 (microtask). 2235 // - The first two arguments of the callback callee are unknown (-1). 2236 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2237 // callback callee. 2238 F->addMetadata( 2239 llvm::LLVMContext::MD_callback, 2240 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2241 2, {-1, -1}, 2242 /* VarArgsArePassed */ true)})); 2243 } 2244 } 2245 break; 2246 } 2247 case OMPRTL__kmpc_taskloop: { 2248 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2249 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2250 // sched, kmp_uint64 grainsize, void *task_dup); 2251 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2252 CGM.IntTy, 2253 CGM.VoidPtrTy, 2254 CGM.IntTy, 2255 CGM.Int64Ty->getPointerTo(), 2256 CGM.Int64Ty->getPointerTo(), 2257 CGM.Int64Ty, 2258 CGM.IntTy, 2259 CGM.IntTy, 2260 CGM.Int64Ty, 2261 CGM.VoidPtrTy}; 2262 auto *FnTy = 2263 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2264 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2265 break; 2266 } 2267 case OMPRTL__kmpc_doacross_init: { 2268 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2269 // num_dims, struct kmp_dim *dims); 2270 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2271 CGM.Int32Ty, 2272 CGM.Int32Ty, 2273 CGM.VoidPtrTy}; 2274 auto *FnTy = 2275 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2276 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2277 break; 2278 } 2279 case OMPRTL__kmpc_doacross_fini: { 2280 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2281 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2282 auto *FnTy = 2283 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2284 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2285 break; 2286 } 2287 case OMPRTL__kmpc_doacross_post: { 2288 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2289 // *vec); 2290 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2291 CGM.Int64Ty->getPointerTo()}; 2292 auto *FnTy = 2293 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2294 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2295 break; 2296 } 2297 case OMPRTL__kmpc_doacross_wait: { 2298 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2299 // *vec); 2300 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2301 CGM.Int64Ty->getPointerTo()}; 2302 auto *FnTy = 2303 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2304 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2305 break; 2306 } 2307 case OMPRTL__kmpc_task_reduction_init: { 2308 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2309 // *data); 2310 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2311 auto *FnTy = 2312 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2313 RTLFn = 2314 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2315 break; 2316 } 2317 case OMPRTL__kmpc_task_reduction_get_th_data: { 2318 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2319 // *d); 2320 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2321 auto *FnTy = 2322 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2323 RTLFn = CGM.CreateRuntimeFunction( 2324 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2325 break; 2326 } 2327 case OMPRTL__kmpc_alloc: { 2328 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2329 // al); omp_allocator_handle_t type is void *. 2330 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2331 auto *FnTy = 2332 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2333 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2334 break; 2335 } 2336 case OMPRTL__kmpc_free: { 2337 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2338 // al); omp_allocator_handle_t type is void *. 2339 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2340 auto *FnTy = 2341 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2342 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2343 break; 2344 } 2345 case OMPRTL__kmpc_push_target_tripcount: { 2346 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2347 // size); 2348 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2349 llvm::FunctionType *FnTy = 2350 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2351 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2352 break; 2353 } 2354 case OMPRTL__tgt_target: { 2355 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2356 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2357 // *arg_types); 2358 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2359 CGM.VoidPtrTy, 2360 CGM.Int32Ty, 2361 CGM.VoidPtrPtrTy, 2362 CGM.VoidPtrPtrTy, 2363 CGM.Int64Ty->getPointerTo(), 2364 CGM.Int64Ty->getPointerTo()}; 2365 auto *FnTy = 2366 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2367 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2368 break; 2369 } 2370 case OMPRTL__tgt_target_nowait: { 2371 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2372 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2373 // int64_t *arg_types); 2374 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2375 CGM.VoidPtrTy, 2376 CGM.Int32Ty, 2377 CGM.VoidPtrPtrTy, 2378 CGM.VoidPtrPtrTy, 2379 CGM.Int64Ty->getPointerTo(), 2380 CGM.Int64Ty->getPointerTo()}; 2381 auto *FnTy = 2382 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2383 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2384 break; 2385 } 2386 case OMPRTL__tgt_target_teams: { 2387 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2388 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2389 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2390 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2391 CGM.VoidPtrTy, 2392 CGM.Int32Ty, 2393 CGM.VoidPtrPtrTy, 2394 CGM.VoidPtrPtrTy, 2395 CGM.Int64Ty->getPointerTo(), 2396 CGM.Int64Ty->getPointerTo(), 2397 CGM.Int32Ty, 2398 CGM.Int32Ty}; 2399 auto *FnTy = 2400 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2401 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2402 break; 2403 } 2404 case OMPRTL__tgt_target_teams_nowait: { 2405 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2406 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2407 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2408 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2409 CGM.VoidPtrTy, 2410 CGM.Int32Ty, 2411 CGM.VoidPtrPtrTy, 2412 CGM.VoidPtrPtrTy, 2413 CGM.Int64Ty->getPointerTo(), 2414 CGM.Int64Ty->getPointerTo(), 2415 CGM.Int32Ty, 2416 CGM.Int32Ty}; 2417 auto *FnTy = 2418 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2419 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2420 break; 2421 } 2422 case OMPRTL__tgt_register_requires: { 2423 // Build void __tgt_register_requires(int64_t flags); 2424 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2425 auto *FnTy = 2426 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2427 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2428 break; 2429 } 2430 case OMPRTL__tgt_register_lib: { 2431 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 2432 QualType ParamTy = 2433 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2434 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2435 auto *FnTy = 2436 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2437 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 2438 break; 2439 } 2440 case OMPRTL__tgt_unregister_lib: { 2441 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 2442 QualType ParamTy = 2443 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2444 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2445 auto *FnTy = 2446 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2447 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 2448 break; 2449 } 2450 case OMPRTL__tgt_target_data_begin: { 2451 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2452 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2453 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2454 CGM.Int32Ty, 2455 CGM.VoidPtrPtrTy, 2456 CGM.VoidPtrPtrTy, 2457 CGM.Int64Ty->getPointerTo(), 2458 CGM.Int64Ty->getPointerTo()}; 2459 auto *FnTy = 2460 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2461 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2462 break; 2463 } 2464 case OMPRTL__tgt_target_data_begin_nowait: { 2465 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2466 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2467 // *arg_types); 2468 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2469 CGM.Int32Ty, 2470 CGM.VoidPtrPtrTy, 2471 CGM.VoidPtrPtrTy, 2472 CGM.Int64Ty->getPointerTo(), 2473 CGM.Int64Ty->getPointerTo()}; 2474 auto *FnTy = 2475 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2476 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2477 break; 2478 } 2479 case OMPRTL__tgt_target_data_end: { 2480 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2481 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2482 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2483 CGM.Int32Ty, 2484 CGM.VoidPtrPtrTy, 2485 CGM.VoidPtrPtrTy, 2486 CGM.Int64Ty->getPointerTo(), 2487 CGM.Int64Ty->getPointerTo()}; 2488 auto *FnTy = 2489 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2490 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2491 break; 2492 } 2493 case OMPRTL__tgt_target_data_end_nowait: { 2494 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2495 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2496 // *arg_types); 2497 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2498 CGM.Int32Ty, 2499 CGM.VoidPtrPtrTy, 2500 CGM.VoidPtrPtrTy, 2501 CGM.Int64Ty->getPointerTo(), 2502 CGM.Int64Ty->getPointerTo()}; 2503 auto *FnTy = 2504 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2505 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2506 break; 2507 } 2508 case OMPRTL__tgt_target_data_update: { 2509 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2510 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2511 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2512 CGM.Int32Ty, 2513 CGM.VoidPtrPtrTy, 2514 CGM.VoidPtrPtrTy, 2515 CGM.Int64Ty->getPointerTo(), 2516 CGM.Int64Ty->getPointerTo()}; 2517 auto *FnTy = 2518 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2519 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2520 break; 2521 } 2522 case OMPRTL__tgt_target_data_update_nowait: { 2523 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2524 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2525 // *arg_types); 2526 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2527 CGM.Int32Ty, 2528 CGM.VoidPtrPtrTy, 2529 CGM.VoidPtrPtrTy, 2530 CGM.Int64Ty->getPointerTo(), 2531 CGM.Int64Ty->getPointerTo()}; 2532 auto *FnTy = 2533 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2534 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2535 break; 2536 } 2537 case OMPRTL__tgt_mapper_num_components: { 2538 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2539 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2540 auto *FnTy = 2541 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2542 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2543 break; 2544 } 2545 case OMPRTL__tgt_push_mapper_component: { 2546 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2547 // *base, void *begin, int64_t size, int64_t type); 2548 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2549 CGM.Int64Ty, CGM.Int64Ty}; 2550 auto *FnTy = 2551 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2552 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2553 break; 2554 } 2555 } 2556 assert(RTLFn && "Unable to find OpenMP runtime function"); 2557 return RTLFn; 2558 } 2559 2560 llvm::FunctionCallee 2561 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2562 assert((IVSize == 32 || IVSize == 64) && 2563 "IV size is not compatible with the omp runtime"); 2564 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2565 : "__kmpc_for_static_init_4u") 2566 : (IVSigned ? "__kmpc_for_static_init_8" 2567 : "__kmpc_for_static_init_8u"); 2568 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2569 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2570 llvm::Type *TypeParams[] = { 2571 getIdentTyPointerTy(), // loc 2572 CGM.Int32Ty, // tid 2573 CGM.Int32Ty, // schedtype 2574 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2575 PtrTy, // p_lower 2576 PtrTy, // p_upper 2577 PtrTy, // p_stride 2578 ITy, // incr 2579 ITy // chunk 2580 }; 2581 auto *FnTy = 2582 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2583 return CGM.CreateRuntimeFunction(FnTy, Name); 2584 } 2585 2586 llvm::FunctionCallee 2587 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2588 assert((IVSize == 32 || IVSize == 64) && 2589 "IV size is not compatible with the omp runtime"); 2590 StringRef Name = 2591 IVSize == 32 2592 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2593 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2594 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2595 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2596 CGM.Int32Ty, // tid 2597 CGM.Int32Ty, // schedtype 2598 ITy, // lower 2599 ITy, // upper 2600 ITy, // stride 2601 ITy // chunk 2602 }; 2603 auto *FnTy = 2604 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2605 return CGM.CreateRuntimeFunction(FnTy, Name); 2606 } 2607 2608 llvm::FunctionCallee 2609 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2610 assert((IVSize == 32 || IVSize == 64) && 2611 "IV size is not compatible with the omp runtime"); 2612 StringRef Name = 2613 IVSize == 32 2614 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2615 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2616 llvm::Type *TypeParams[] = { 2617 getIdentTyPointerTy(), // loc 2618 CGM.Int32Ty, // tid 2619 }; 2620 auto *FnTy = 2621 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2622 return CGM.CreateRuntimeFunction(FnTy, Name); 2623 } 2624 2625 llvm::FunctionCallee 2626 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2627 assert((IVSize == 32 || IVSize == 64) && 2628 "IV size is not compatible with the omp runtime"); 2629 StringRef Name = 2630 IVSize == 32 2631 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2632 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2633 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2634 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2635 llvm::Type *TypeParams[] = { 2636 getIdentTyPointerTy(), // loc 2637 CGM.Int32Ty, // tid 2638 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2639 PtrTy, // p_lower 2640 PtrTy, // p_upper 2641 PtrTy // p_stride 2642 }; 2643 auto *FnTy = 2644 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2645 return CGM.CreateRuntimeFunction(FnTy, Name); 2646 } 2647 2648 /// Obtain information that uniquely identifies a target entry. This 2649 /// consists of the file and device IDs as well as line number associated with 2650 /// the relevant entry source location. 2651 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2652 unsigned &DeviceID, unsigned &FileID, 2653 unsigned &LineNum) { 2654 SourceManager &SM = C.getSourceManager(); 2655 2656 // The loc should be always valid and have a file ID (the user cannot use 2657 // #pragma directives in macros) 2658 2659 assert(Loc.isValid() && "Source location is expected to be always valid."); 2660 2661 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2662 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2663 2664 llvm::sys::fs::UniqueID ID; 2665 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2666 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2667 << PLoc.getFilename() << EC.message(); 2668 2669 DeviceID = ID.getDevice(); 2670 FileID = ID.getFile(); 2671 LineNum = PLoc.getLine(); 2672 } 2673 2674 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2675 if (CGM.getLangOpts().OpenMPSimd) 2676 return Address::invalid(); 2677 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2678 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2679 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2680 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2681 HasRequiresUnifiedSharedMemory))) { 2682 SmallString<64> PtrName; 2683 { 2684 llvm::raw_svector_ostream OS(PtrName); 2685 OS << CGM.getMangledName(GlobalDecl(VD)); 2686 if (!VD->isExternallyVisible()) { 2687 unsigned DeviceID, FileID, Line; 2688 getTargetEntryUniqueInfo(CGM.getContext(), 2689 VD->getCanonicalDecl()->getBeginLoc(), 2690 DeviceID, FileID, Line); 2691 OS << llvm::format("_%x", FileID); 2692 } 2693 OS << "_decl_tgt_ref_ptr"; 2694 } 2695 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2696 if (!Ptr) { 2697 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2698 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2699 PtrName); 2700 2701 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2702 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2703 2704 if (!CGM.getLangOpts().OpenMPIsDevice) 2705 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2706 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2707 } 2708 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2709 } 2710 return Address::invalid(); 2711 } 2712 2713 llvm::Constant * 2714 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2715 assert(!CGM.getLangOpts().OpenMPUseTLS || 2716 !CGM.getContext().getTargetInfo().isTLSSupported()); 2717 // Lookup the entry, lazily creating it if necessary. 2718 std::string Suffix = getName({"cache", ""}); 2719 return getOrCreateInternalVariable( 2720 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2721 } 2722 2723 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2724 const VarDecl *VD, 2725 Address VDAddr, 2726 SourceLocation Loc) { 2727 if (CGM.getLangOpts().OpenMPUseTLS && 2728 CGM.getContext().getTargetInfo().isTLSSupported()) 2729 return VDAddr; 2730 2731 llvm::Type *VarTy = VDAddr.getElementType(); 2732 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2733 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2734 CGM.Int8PtrTy), 2735 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2736 getOrCreateThreadPrivateCache(VD)}; 2737 return Address(CGF.EmitRuntimeCall( 2738 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2739 VDAddr.getAlignment()); 2740 } 2741 2742 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2743 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2744 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2745 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2746 // library. 2747 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2748 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2749 OMPLoc); 2750 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2751 // to register constructor/destructor for variable. 2752 llvm::Value *Args[] = { 2753 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2754 Ctor, CopyCtor, Dtor}; 2755 CGF.EmitRuntimeCall( 2756 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2757 } 2758 2759 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2760 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2761 bool PerformInit, CodeGenFunction *CGF) { 2762 if (CGM.getLangOpts().OpenMPUseTLS && 2763 CGM.getContext().getTargetInfo().isTLSSupported()) 2764 return nullptr; 2765 2766 VD = VD->getDefinition(CGM.getContext()); 2767 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2768 QualType ASTTy = VD->getType(); 2769 2770 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2771 const Expr *Init = VD->getAnyInitializer(); 2772 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2773 // Generate function that re-emits the declaration's initializer into the 2774 // threadprivate copy of the variable VD 2775 CodeGenFunction CtorCGF(CGM); 2776 FunctionArgList Args; 2777 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2778 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2779 ImplicitParamDecl::Other); 2780 Args.push_back(&Dst); 2781 2782 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2783 CGM.getContext().VoidPtrTy, Args); 2784 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2785 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2786 llvm::Function *Fn = 2787 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2788 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2789 Args, Loc, Loc); 2790 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2791 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2792 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2793 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2794 Arg = CtorCGF.Builder.CreateElementBitCast( 2795 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2796 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2797 /*IsInitializer=*/true); 2798 ArgVal = CtorCGF.EmitLoadOfScalar( 2799 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2800 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2801 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2802 CtorCGF.FinishFunction(); 2803 Ctor = Fn; 2804 } 2805 if (VD->getType().isDestructedType() != QualType::DK_none) { 2806 // Generate function that emits destructor call for the threadprivate copy 2807 // of the variable VD 2808 CodeGenFunction DtorCGF(CGM); 2809 FunctionArgList Args; 2810 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2811 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2812 ImplicitParamDecl::Other); 2813 Args.push_back(&Dst); 2814 2815 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2816 CGM.getContext().VoidTy, Args); 2817 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2818 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2819 llvm::Function *Fn = 2820 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2821 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2822 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2823 Loc, Loc); 2824 // Create a scope with an artificial location for the body of this function. 2825 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2826 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2827 DtorCGF.GetAddrOfLocalVar(&Dst), 2828 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2829 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2830 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2831 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2832 DtorCGF.FinishFunction(); 2833 Dtor = Fn; 2834 } 2835 // Do not emit init function if it is not required. 2836 if (!Ctor && !Dtor) 2837 return nullptr; 2838 2839 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2840 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2841 /*isVarArg=*/false) 2842 ->getPointerTo(); 2843 // Copying constructor for the threadprivate variable. 2844 // Must be NULL - reserved by runtime, but currently it requires that this 2845 // parameter is always NULL. Otherwise it fires assertion. 2846 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2847 if (Ctor == nullptr) { 2848 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2849 /*isVarArg=*/false) 2850 ->getPointerTo(); 2851 Ctor = llvm::Constant::getNullValue(CtorTy); 2852 } 2853 if (Dtor == nullptr) { 2854 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2855 /*isVarArg=*/false) 2856 ->getPointerTo(); 2857 Dtor = llvm::Constant::getNullValue(DtorTy); 2858 } 2859 if (!CGF) { 2860 auto *InitFunctionTy = 2861 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2862 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2863 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2864 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2865 CodeGenFunction InitCGF(CGM); 2866 FunctionArgList ArgList; 2867 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2868 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2869 Loc, Loc); 2870 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2871 InitCGF.FinishFunction(); 2872 return InitFunction; 2873 } 2874 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2875 } 2876 return nullptr; 2877 } 2878 2879 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2880 llvm::GlobalVariable *Addr, 2881 bool PerformInit) { 2882 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2883 !CGM.getLangOpts().OpenMPIsDevice) 2884 return false; 2885 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2886 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2887 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2888 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2889 HasRequiresUnifiedSharedMemory)) 2890 return CGM.getLangOpts().OpenMPIsDevice; 2891 VD = VD->getDefinition(CGM.getContext()); 2892 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2893 return CGM.getLangOpts().OpenMPIsDevice; 2894 2895 QualType ASTTy = VD->getType(); 2896 2897 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2898 // Produce the unique prefix to identify the new target regions. We use 2899 // the source location of the variable declaration which we know to not 2900 // conflict with any target region. 2901 unsigned DeviceID; 2902 unsigned FileID; 2903 unsigned Line; 2904 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2905 SmallString<128> Buffer, Out; 2906 { 2907 llvm::raw_svector_ostream OS(Buffer); 2908 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2909 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2910 } 2911 2912 const Expr *Init = VD->getAnyInitializer(); 2913 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2914 llvm::Constant *Ctor; 2915 llvm::Constant *ID; 2916 if (CGM.getLangOpts().OpenMPIsDevice) { 2917 // Generate function that re-emits the declaration's initializer into 2918 // the threadprivate copy of the variable VD 2919 CodeGenFunction CtorCGF(CGM); 2920 2921 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2922 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2923 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2924 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2925 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2926 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2927 FunctionArgList(), Loc, Loc); 2928 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2929 CtorCGF.EmitAnyExprToMem(Init, 2930 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2931 Init->getType().getQualifiers(), 2932 /*IsInitializer=*/true); 2933 CtorCGF.FinishFunction(); 2934 Ctor = Fn; 2935 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2936 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2937 } else { 2938 Ctor = new llvm::GlobalVariable( 2939 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2940 llvm::GlobalValue::PrivateLinkage, 2941 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2942 ID = Ctor; 2943 } 2944 2945 // Register the information for the entry associated with the constructor. 2946 Out.clear(); 2947 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2948 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2949 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2950 } 2951 if (VD->getType().isDestructedType() != QualType::DK_none) { 2952 llvm::Constant *Dtor; 2953 llvm::Constant *ID; 2954 if (CGM.getLangOpts().OpenMPIsDevice) { 2955 // Generate function that emits destructor call for the threadprivate 2956 // copy of the variable VD 2957 CodeGenFunction DtorCGF(CGM); 2958 2959 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2960 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2961 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2962 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2963 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2964 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2965 FunctionArgList(), Loc, Loc); 2966 // Create a scope with an artificial location for the body of this 2967 // function. 2968 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2969 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 2970 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2971 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2972 DtorCGF.FinishFunction(); 2973 Dtor = Fn; 2974 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2975 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 2976 } else { 2977 Dtor = new llvm::GlobalVariable( 2978 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2979 llvm::GlobalValue::PrivateLinkage, 2980 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 2981 ID = Dtor; 2982 } 2983 // Register the information for the entry associated with the destructor. 2984 Out.clear(); 2985 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2986 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2987 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2988 } 2989 return CGM.getLangOpts().OpenMPIsDevice; 2990 } 2991 2992 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2993 QualType VarType, 2994 StringRef Name) { 2995 std::string Suffix = getName({"artificial", ""}); 2996 std::string CacheSuffix = getName({"cache", ""}); 2997 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2998 llvm::Value *GAddr = 2999 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 3000 llvm::Value *Args[] = { 3001 emitUpdateLocation(CGF, SourceLocation()), 3002 getThreadID(CGF, SourceLocation()), 3003 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 3004 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 3005 /*isSigned=*/false), 3006 getOrCreateInternalVariable( 3007 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 3008 return Address( 3009 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3010 CGF.EmitRuntimeCall( 3011 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3012 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3013 CGM.getPointerAlign()); 3014 } 3015 3016 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 3017 const RegionCodeGenTy &ThenGen, 3018 const RegionCodeGenTy &ElseGen) { 3019 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3020 3021 // If the condition constant folds and can be elided, try to avoid emitting 3022 // the condition and the dead arm of the if/else. 3023 bool CondConstant; 3024 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3025 if (CondConstant) 3026 ThenGen(CGF); 3027 else 3028 ElseGen(CGF); 3029 return; 3030 } 3031 3032 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3033 // emit the conditional branch. 3034 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3035 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3036 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3037 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3038 3039 // Emit the 'then' code. 3040 CGF.EmitBlock(ThenBlock); 3041 ThenGen(CGF); 3042 CGF.EmitBranch(ContBlock); 3043 // Emit the 'else' code if present. 3044 // There is no need to emit line number for unconditional branch. 3045 (void)ApplyDebugLocation::CreateEmpty(CGF); 3046 CGF.EmitBlock(ElseBlock); 3047 ElseGen(CGF); 3048 // There is no need to emit line number for unconditional branch. 3049 (void)ApplyDebugLocation::CreateEmpty(CGF); 3050 CGF.EmitBranch(ContBlock); 3051 // Emit the continuation block for code after the if. 3052 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3053 } 3054 3055 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3056 llvm::Function *OutlinedFn, 3057 ArrayRef<llvm::Value *> CapturedVars, 3058 const Expr *IfCond) { 3059 if (!CGF.HaveInsertPoint()) 3060 return; 3061 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3062 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3063 PrePostActionTy &) { 3064 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3065 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3066 llvm::Value *Args[] = { 3067 RTLoc, 3068 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3069 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3070 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3071 RealArgs.append(std::begin(Args), std::end(Args)); 3072 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3073 3074 llvm::FunctionCallee RTLFn = 3075 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3076 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3077 }; 3078 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3079 PrePostActionTy &) { 3080 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3081 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3082 // Build calls: 3083 // __kmpc_serialized_parallel(&Loc, GTid); 3084 llvm::Value *Args[] = {RTLoc, ThreadID}; 3085 CGF.EmitRuntimeCall( 3086 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3087 3088 // OutlinedFn(>id, &zero_bound, CapturedStruct); 3089 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 3090 Address ZeroAddrBound = 3091 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3092 /*Name=*/".bound.zero.addr"); 3093 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 3094 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3095 // ThreadId for serialized parallels is 0. 3096 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 3097 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 3098 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3099 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3100 3101 // __kmpc_end_serialized_parallel(&Loc, GTid); 3102 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3103 CGF.EmitRuntimeCall( 3104 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3105 EndArgs); 3106 }; 3107 if (IfCond) { 3108 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 3109 } else { 3110 RegionCodeGenTy ThenRCG(ThenGen); 3111 ThenRCG(CGF); 3112 } 3113 } 3114 3115 // If we're inside an (outlined) parallel region, use the region info's 3116 // thread-ID variable (it is passed in a first argument of the outlined function 3117 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3118 // regular serial code region, get thread ID by calling kmp_int32 3119 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3120 // return the address of that temp. 3121 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3122 SourceLocation Loc) { 3123 if (auto *OMPRegionInfo = 3124 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3125 if (OMPRegionInfo->getThreadIDVariable()) 3126 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 3127 3128 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3129 QualType Int32Ty = 3130 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3131 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3132 CGF.EmitStoreOfScalar(ThreadID, 3133 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3134 3135 return ThreadIDTemp; 3136 } 3137 3138 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3139 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3140 SmallString<256> Buffer; 3141 llvm::raw_svector_ostream Out(Buffer); 3142 Out << Name; 3143 StringRef RuntimeName = Out.str(); 3144 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3145 if (Elem.second) { 3146 assert(Elem.second->getType()->getPointerElementType() == Ty && 3147 "OMP internal variable has different type than requested"); 3148 return &*Elem.second; 3149 } 3150 3151 return Elem.second = new llvm::GlobalVariable( 3152 CGM.getModule(), Ty, /*IsConstant*/ false, 3153 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3154 Elem.first(), /*InsertBefore=*/nullptr, 3155 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3156 } 3157 3158 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3159 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3160 std::string Name = getName({Prefix, "var"}); 3161 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3162 } 3163 3164 namespace { 3165 /// Common pre(post)-action for different OpenMP constructs. 3166 class CommonActionTy final : public PrePostActionTy { 3167 llvm::FunctionCallee EnterCallee; 3168 ArrayRef<llvm::Value *> EnterArgs; 3169 llvm::FunctionCallee ExitCallee; 3170 ArrayRef<llvm::Value *> ExitArgs; 3171 bool Conditional; 3172 llvm::BasicBlock *ContBlock = nullptr; 3173 3174 public: 3175 CommonActionTy(llvm::FunctionCallee EnterCallee, 3176 ArrayRef<llvm::Value *> EnterArgs, 3177 llvm::FunctionCallee ExitCallee, 3178 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3179 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3180 ExitArgs(ExitArgs), Conditional(Conditional) {} 3181 void Enter(CodeGenFunction &CGF) override { 3182 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3183 if (Conditional) { 3184 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3185 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3186 ContBlock = CGF.createBasicBlock("omp_if.end"); 3187 // Generate the branch (If-stmt) 3188 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3189 CGF.EmitBlock(ThenBlock); 3190 } 3191 } 3192 void Done(CodeGenFunction &CGF) { 3193 // Emit the rest of blocks/branches 3194 CGF.EmitBranch(ContBlock); 3195 CGF.EmitBlock(ContBlock, true); 3196 } 3197 void Exit(CodeGenFunction &CGF) override { 3198 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3199 } 3200 }; 3201 } // anonymous namespace 3202 3203 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3204 StringRef CriticalName, 3205 const RegionCodeGenTy &CriticalOpGen, 3206 SourceLocation Loc, const Expr *Hint) { 3207 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3208 // CriticalOpGen(); 3209 // __kmpc_end_critical(ident_t *, gtid, Lock); 3210 // Prepare arguments and build a call to __kmpc_critical 3211 if (!CGF.HaveInsertPoint()) 3212 return; 3213 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3214 getCriticalRegionLock(CriticalName)}; 3215 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3216 std::end(Args)); 3217 if (Hint) { 3218 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3219 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3220 } 3221 CommonActionTy Action( 3222 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3223 : OMPRTL__kmpc_critical), 3224 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3225 CriticalOpGen.setAction(Action); 3226 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3227 } 3228 3229 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3230 const RegionCodeGenTy &MasterOpGen, 3231 SourceLocation Loc) { 3232 if (!CGF.HaveInsertPoint()) 3233 return; 3234 // if(__kmpc_master(ident_t *, gtid)) { 3235 // MasterOpGen(); 3236 // __kmpc_end_master(ident_t *, gtid); 3237 // } 3238 // Prepare arguments and build a call to __kmpc_master 3239 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3240 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3241 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3242 /*Conditional=*/true); 3243 MasterOpGen.setAction(Action); 3244 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3245 Action.Done(CGF); 3246 } 3247 3248 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3249 SourceLocation Loc) { 3250 if (!CGF.HaveInsertPoint()) 3251 return; 3252 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3253 llvm::Value *Args[] = { 3254 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3255 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3256 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3257 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3258 Region->emitUntiedSwitch(CGF); 3259 } 3260 3261 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3262 const RegionCodeGenTy &TaskgroupOpGen, 3263 SourceLocation Loc) { 3264 if (!CGF.HaveInsertPoint()) 3265 return; 3266 // __kmpc_taskgroup(ident_t *, gtid); 3267 // TaskgroupOpGen(); 3268 // __kmpc_end_taskgroup(ident_t *, gtid); 3269 // Prepare arguments and build a call to __kmpc_taskgroup 3270 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3271 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3272 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3273 Args); 3274 TaskgroupOpGen.setAction(Action); 3275 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3276 } 3277 3278 /// Given an array of pointers to variables, project the address of a 3279 /// given variable. 3280 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3281 unsigned Index, const VarDecl *Var) { 3282 // Pull out the pointer to the variable. 3283 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3284 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3285 3286 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3287 Addr = CGF.Builder.CreateElementBitCast( 3288 Addr, CGF.ConvertTypeForMem(Var->getType())); 3289 return Addr; 3290 } 3291 3292 static llvm::Value *emitCopyprivateCopyFunction( 3293 CodeGenModule &CGM, llvm::Type *ArgsType, 3294 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3295 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3296 SourceLocation Loc) { 3297 ASTContext &C = CGM.getContext(); 3298 // void copy_func(void *LHSArg, void *RHSArg); 3299 FunctionArgList Args; 3300 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3301 ImplicitParamDecl::Other); 3302 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3303 ImplicitParamDecl::Other); 3304 Args.push_back(&LHSArg); 3305 Args.push_back(&RHSArg); 3306 const auto &CGFI = 3307 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3308 std::string Name = 3309 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3310 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3311 llvm::GlobalValue::InternalLinkage, Name, 3312 &CGM.getModule()); 3313 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3314 Fn->setDoesNotRecurse(); 3315 CodeGenFunction CGF(CGM); 3316 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3317 // Dest = (void*[n])(LHSArg); 3318 // Src = (void*[n])(RHSArg); 3319 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3320 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3321 ArgsType), CGF.getPointerAlign()); 3322 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3323 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3324 ArgsType), CGF.getPointerAlign()); 3325 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3326 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3327 // ... 3328 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3329 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3330 const auto *DestVar = 3331 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3332 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3333 3334 const auto *SrcVar = 3335 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3336 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3337 3338 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3339 QualType Type = VD->getType(); 3340 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3341 } 3342 CGF.FinishFunction(); 3343 return Fn; 3344 } 3345 3346 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3347 const RegionCodeGenTy &SingleOpGen, 3348 SourceLocation Loc, 3349 ArrayRef<const Expr *> CopyprivateVars, 3350 ArrayRef<const Expr *> SrcExprs, 3351 ArrayRef<const Expr *> DstExprs, 3352 ArrayRef<const Expr *> AssignmentOps) { 3353 if (!CGF.HaveInsertPoint()) 3354 return; 3355 assert(CopyprivateVars.size() == SrcExprs.size() && 3356 CopyprivateVars.size() == DstExprs.size() && 3357 CopyprivateVars.size() == AssignmentOps.size()); 3358 ASTContext &C = CGM.getContext(); 3359 // int32 did_it = 0; 3360 // if(__kmpc_single(ident_t *, gtid)) { 3361 // SingleOpGen(); 3362 // __kmpc_end_single(ident_t *, gtid); 3363 // did_it = 1; 3364 // } 3365 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3366 // <copy_func>, did_it); 3367 3368 Address DidIt = Address::invalid(); 3369 if (!CopyprivateVars.empty()) { 3370 // int32 did_it = 0; 3371 QualType KmpInt32Ty = 3372 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3373 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3374 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3375 } 3376 // Prepare arguments and build a call to __kmpc_single 3377 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3378 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3379 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3380 /*Conditional=*/true); 3381 SingleOpGen.setAction(Action); 3382 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3383 if (DidIt.isValid()) { 3384 // did_it = 1; 3385 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3386 } 3387 Action.Done(CGF); 3388 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3389 // <copy_func>, did_it); 3390 if (DidIt.isValid()) { 3391 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3392 QualType CopyprivateArrayTy = C.getConstantArrayType( 3393 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3394 /*IndexTypeQuals=*/0); 3395 // Create a list of all private variables for copyprivate. 3396 Address CopyprivateList = 3397 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3398 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3399 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3400 CGF.Builder.CreateStore( 3401 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3402 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 3403 CGF.VoidPtrTy), 3404 Elem); 3405 } 3406 // Build function that copies private values from single region to all other 3407 // threads in the corresponding parallel region. 3408 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3409 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3410 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3411 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3412 Address CL = 3413 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3414 CGF.VoidPtrTy); 3415 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3416 llvm::Value *Args[] = { 3417 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3418 getThreadID(CGF, Loc), // i32 <gtid> 3419 BufSize, // size_t <buf_size> 3420 CL.getPointer(), // void *<copyprivate list> 3421 CpyFn, // void (*) (void *, void *) <copy_func> 3422 DidItVal // i32 did_it 3423 }; 3424 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3425 } 3426 } 3427 3428 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3429 const RegionCodeGenTy &OrderedOpGen, 3430 SourceLocation Loc, bool IsThreads) { 3431 if (!CGF.HaveInsertPoint()) 3432 return; 3433 // __kmpc_ordered(ident_t *, gtid); 3434 // OrderedOpGen(); 3435 // __kmpc_end_ordered(ident_t *, gtid); 3436 // Prepare arguments and build a call to __kmpc_ordered 3437 if (IsThreads) { 3438 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3439 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3440 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3441 Args); 3442 OrderedOpGen.setAction(Action); 3443 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3444 return; 3445 } 3446 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3447 } 3448 3449 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3450 unsigned Flags; 3451 if (Kind == OMPD_for) 3452 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3453 else if (Kind == OMPD_sections) 3454 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3455 else if (Kind == OMPD_single) 3456 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3457 else if (Kind == OMPD_barrier) 3458 Flags = OMP_IDENT_BARRIER_EXPL; 3459 else 3460 Flags = OMP_IDENT_BARRIER_IMPL; 3461 return Flags; 3462 } 3463 3464 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3465 CodeGenFunction &CGF, const OMPLoopDirective &S, 3466 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3467 // Check if the loop directive is actually a doacross loop directive. In this 3468 // case choose static, 1 schedule. 3469 if (llvm::any_of( 3470 S.getClausesOfKind<OMPOrderedClause>(), 3471 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3472 ScheduleKind = OMPC_SCHEDULE_static; 3473 // Chunk size is 1 in this case. 3474 llvm::APInt ChunkSize(32, 1); 3475 ChunkExpr = IntegerLiteral::Create( 3476 CGF.getContext(), ChunkSize, 3477 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3478 SourceLocation()); 3479 } 3480 } 3481 3482 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3483 OpenMPDirectiveKind Kind, bool EmitChecks, 3484 bool ForceSimpleCall) { 3485 // Check if we should use the OMPBuilder 3486 auto *OMPRegionInfo = 3487 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 3488 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3489 if (OMPBuilder) { 3490 // TODO: Move cancelation point handling into the IRBuilder. 3491 if (EmitChecks && !ForceSimpleCall && OMPRegionInfo && 3492 OMPRegionInfo->hasCancel() && CGF.Builder.GetInsertBlock()) { 3493 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 3494 llvm::BasicBlock *ExitBB = CGF.createBasicBlock( 3495 ".cancel.exit", CGF.Builder.GetInsertBlock()->getParent()); 3496 OMPBuilder->setCancellationBlock(ExitBB); 3497 CGF.Builder.SetInsertPoint(ExitBB); 3498 CodeGenFunction::JumpDest CancelDestination = 3499 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3500 CGF.EmitBranchThroughCleanup(CancelDestination); 3501 } 3502 auto IP = OMPBuilder->CreateBarrier(CGF.Builder, Kind, ForceSimpleCall, 3503 EmitChecks); 3504 CGF.Builder.restoreIP(IP); 3505 return; 3506 } 3507 3508 if (!CGF.HaveInsertPoint()) 3509 return; 3510 // Build call __kmpc_cancel_barrier(loc, thread_id); 3511 // Build call __kmpc_barrier(loc, thread_id); 3512 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3513 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3514 // thread_id); 3515 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3516 getThreadID(CGF, Loc)}; 3517 if (OMPRegionInfo) { 3518 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3519 llvm::Value *Result = CGF.EmitRuntimeCall( 3520 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3521 if (EmitChecks) { 3522 // if (__kmpc_cancel_barrier()) { 3523 // exit from construct; 3524 // } 3525 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3526 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3527 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3528 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3529 CGF.EmitBlock(ExitBB); 3530 // exit from construct; 3531 CodeGenFunction::JumpDest CancelDestination = 3532 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3533 CGF.EmitBranchThroughCleanup(CancelDestination); 3534 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3535 } 3536 return; 3537 } 3538 } 3539 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3540 } 3541 3542 /// Map the OpenMP loop schedule to the runtime enumeration. 3543 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3544 bool Chunked, bool Ordered) { 3545 switch (ScheduleKind) { 3546 case OMPC_SCHEDULE_static: 3547 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3548 : (Ordered ? OMP_ord_static : OMP_sch_static); 3549 case OMPC_SCHEDULE_dynamic: 3550 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3551 case OMPC_SCHEDULE_guided: 3552 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3553 case OMPC_SCHEDULE_runtime: 3554 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3555 case OMPC_SCHEDULE_auto: 3556 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3557 case OMPC_SCHEDULE_unknown: 3558 assert(!Chunked && "chunk was specified but schedule kind not known"); 3559 return Ordered ? OMP_ord_static : OMP_sch_static; 3560 } 3561 llvm_unreachable("Unexpected runtime schedule"); 3562 } 3563 3564 /// Map the OpenMP distribute schedule to the runtime enumeration. 3565 static OpenMPSchedType 3566 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3567 // only static is allowed for dist_schedule 3568 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3569 } 3570 3571 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3572 bool Chunked) const { 3573 OpenMPSchedType Schedule = 3574 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3575 return Schedule == OMP_sch_static; 3576 } 3577 3578 bool CGOpenMPRuntime::isStaticNonchunked( 3579 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3580 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3581 return Schedule == OMP_dist_sch_static; 3582 } 3583 3584 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3585 bool Chunked) const { 3586 OpenMPSchedType Schedule = 3587 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3588 return Schedule == OMP_sch_static_chunked; 3589 } 3590 3591 bool CGOpenMPRuntime::isStaticChunked( 3592 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3593 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3594 return Schedule == OMP_dist_sch_static_chunked; 3595 } 3596 3597 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3598 OpenMPSchedType Schedule = 3599 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3600 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3601 return Schedule != OMP_sch_static; 3602 } 3603 3604 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3605 OpenMPScheduleClauseModifier M1, 3606 OpenMPScheduleClauseModifier M2) { 3607 int Modifier = 0; 3608 switch (M1) { 3609 case OMPC_SCHEDULE_MODIFIER_monotonic: 3610 Modifier = OMP_sch_modifier_monotonic; 3611 break; 3612 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3613 Modifier = OMP_sch_modifier_nonmonotonic; 3614 break; 3615 case OMPC_SCHEDULE_MODIFIER_simd: 3616 if (Schedule == OMP_sch_static_chunked) 3617 Schedule = OMP_sch_static_balanced_chunked; 3618 break; 3619 case OMPC_SCHEDULE_MODIFIER_last: 3620 case OMPC_SCHEDULE_MODIFIER_unknown: 3621 break; 3622 } 3623 switch (M2) { 3624 case OMPC_SCHEDULE_MODIFIER_monotonic: 3625 Modifier = OMP_sch_modifier_monotonic; 3626 break; 3627 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3628 Modifier = OMP_sch_modifier_nonmonotonic; 3629 break; 3630 case OMPC_SCHEDULE_MODIFIER_simd: 3631 if (Schedule == OMP_sch_static_chunked) 3632 Schedule = OMP_sch_static_balanced_chunked; 3633 break; 3634 case OMPC_SCHEDULE_MODIFIER_last: 3635 case OMPC_SCHEDULE_MODIFIER_unknown: 3636 break; 3637 } 3638 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3639 // If the static schedule kind is specified or if the ordered clause is 3640 // specified, and if the nonmonotonic modifier is not specified, the effect is 3641 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3642 // modifier is specified, the effect is as if the nonmonotonic modifier is 3643 // specified. 3644 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3645 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3646 Schedule == OMP_sch_static_balanced_chunked || 3647 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 3648 Schedule == OMP_dist_sch_static_chunked || 3649 Schedule == OMP_dist_sch_static)) 3650 Modifier = OMP_sch_modifier_nonmonotonic; 3651 } 3652 return Schedule | Modifier; 3653 } 3654 3655 void CGOpenMPRuntime::emitForDispatchInit( 3656 CodeGenFunction &CGF, SourceLocation Loc, 3657 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3658 bool Ordered, const DispatchRTInput &DispatchValues) { 3659 if (!CGF.HaveInsertPoint()) 3660 return; 3661 OpenMPSchedType Schedule = getRuntimeSchedule( 3662 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3663 assert(Ordered || 3664 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3665 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3666 Schedule != OMP_sch_static_balanced_chunked)); 3667 // Call __kmpc_dispatch_init( 3668 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3669 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3670 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3671 3672 // If the Chunk was not specified in the clause - use default value 1. 3673 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3674 : CGF.Builder.getIntN(IVSize, 1); 3675 llvm::Value *Args[] = { 3676 emitUpdateLocation(CGF, Loc), 3677 getThreadID(CGF, Loc), 3678 CGF.Builder.getInt32(addMonoNonMonoModifier( 3679 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3680 DispatchValues.LB, // Lower 3681 DispatchValues.UB, // Upper 3682 CGF.Builder.getIntN(IVSize, 1), // Stride 3683 Chunk // Chunk 3684 }; 3685 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3686 } 3687 3688 static void emitForStaticInitCall( 3689 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3690 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3691 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3692 const CGOpenMPRuntime::StaticRTInput &Values) { 3693 if (!CGF.HaveInsertPoint()) 3694 return; 3695 3696 assert(!Values.Ordered); 3697 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3698 Schedule == OMP_sch_static_balanced_chunked || 3699 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3700 Schedule == OMP_dist_sch_static || 3701 Schedule == OMP_dist_sch_static_chunked); 3702 3703 // Call __kmpc_for_static_init( 3704 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3705 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3706 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3707 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3708 llvm::Value *Chunk = Values.Chunk; 3709 if (Chunk == nullptr) { 3710 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3711 Schedule == OMP_dist_sch_static) && 3712 "expected static non-chunked schedule"); 3713 // If the Chunk was not specified in the clause - use default value 1. 3714 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3715 } else { 3716 assert((Schedule == OMP_sch_static_chunked || 3717 Schedule == OMP_sch_static_balanced_chunked || 3718 Schedule == OMP_ord_static_chunked || 3719 Schedule == OMP_dist_sch_static_chunked) && 3720 "expected static chunked schedule"); 3721 } 3722 llvm::Value *Args[] = { 3723 UpdateLocation, 3724 ThreadId, 3725 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3726 M2)), // Schedule type 3727 Values.IL.getPointer(), // &isLastIter 3728 Values.LB.getPointer(), // &LB 3729 Values.UB.getPointer(), // &UB 3730 Values.ST.getPointer(), // &Stride 3731 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3732 Chunk // Chunk 3733 }; 3734 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3735 } 3736 3737 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3738 SourceLocation Loc, 3739 OpenMPDirectiveKind DKind, 3740 const OpenMPScheduleTy &ScheduleKind, 3741 const StaticRTInput &Values) { 3742 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3743 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3744 assert(isOpenMPWorksharingDirective(DKind) && 3745 "Expected loop-based or sections-based directive."); 3746 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3747 isOpenMPLoopDirective(DKind) 3748 ? OMP_IDENT_WORK_LOOP 3749 : OMP_IDENT_WORK_SECTIONS); 3750 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3751 llvm::FunctionCallee StaticInitFunction = 3752 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3753 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3754 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3755 } 3756 3757 void CGOpenMPRuntime::emitDistributeStaticInit( 3758 CodeGenFunction &CGF, SourceLocation Loc, 3759 OpenMPDistScheduleClauseKind SchedKind, 3760 const CGOpenMPRuntime::StaticRTInput &Values) { 3761 OpenMPSchedType ScheduleNum = 3762 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3763 llvm::Value *UpdatedLocation = 3764 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3765 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3766 llvm::FunctionCallee StaticInitFunction = 3767 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3768 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3769 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3770 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3771 } 3772 3773 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3774 SourceLocation Loc, 3775 OpenMPDirectiveKind DKind) { 3776 if (!CGF.HaveInsertPoint()) 3777 return; 3778 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3779 llvm::Value *Args[] = { 3780 emitUpdateLocation(CGF, Loc, 3781 isOpenMPDistributeDirective(DKind) 3782 ? OMP_IDENT_WORK_DISTRIBUTE 3783 : isOpenMPLoopDirective(DKind) 3784 ? OMP_IDENT_WORK_LOOP 3785 : OMP_IDENT_WORK_SECTIONS), 3786 getThreadID(CGF, Loc)}; 3787 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3788 Args); 3789 } 3790 3791 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3792 SourceLocation Loc, 3793 unsigned IVSize, 3794 bool IVSigned) { 3795 if (!CGF.HaveInsertPoint()) 3796 return; 3797 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3798 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3799 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3800 } 3801 3802 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3803 SourceLocation Loc, unsigned IVSize, 3804 bool IVSigned, Address IL, 3805 Address LB, Address UB, 3806 Address ST) { 3807 // Call __kmpc_dispatch_next( 3808 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3809 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3810 // kmp_int[32|64] *p_stride); 3811 llvm::Value *Args[] = { 3812 emitUpdateLocation(CGF, Loc), 3813 getThreadID(CGF, Loc), 3814 IL.getPointer(), // &isLastIter 3815 LB.getPointer(), // &Lower 3816 UB.getPointer(), // &Upper 3817 ST.getPointer() // &Stride 3818 }; 3819 llvm::Value *Call = 3820 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3821 return CGF.EmitScalarConversion( 3822 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3823 CGF.getContext().BoolTy, Loc); 3824 } 3825 3826 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3827 llvm::Value *NumThreads, 3828 SourceLocation Loc) { 3829 if (!CGF.HaveInsertPoint()) 3830 return; 3831 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3832 llvm::Value *Args[] = { 3833 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3834 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3835 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3836 Args); 3837 } 3838 3839 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3840 OpenMPProcBindClauseKind ProcBind, 3841 SourceLocation Loc) { 3842 if (!CGF.HaveInsertPoint()) 3843 return; 3844 // Constants for proc bind value accepted by the runtime. 3845 enum ProcBindTy { 3846 ProcBindFalse = 0, 3847 ProcBindTrue, 3848 ProcBindMaster, 3849 ProcBindClose, 3850 ProcBindSpread, 3851 ProcBindIntel, 3852 ProcBindDefault 3853 } RuntimeProcBind; 3854 switch (ProcBind) { 3855 case OMPC_PROC_BIND_master: 3856 RuntimeProcBind = ProcBindMaster; 3857 break; 3858 case OMPC_PROC_BIND_close: 3859 RuntimeProcBind = ProcBindClose; 3860 break; 3861 case OMPC_PROC_BIND_spread: 3862 RuntimeProcBind = ProcBindSpread; 3863 break; 3864 case OMPC_PROC_BIND_unknown: 3865 llvm_unreachable("Unsupported proc_bind value."); 3866 } 3867 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3868 llvm::Value *Args[] = { 3869 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3870 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 3871 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3872 } 3873 3874 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3875 SourceLocation Loc) { 3876 if (!CGF.HaveInsertPoint()) 3877 return; 3878 // Build call void __kmpc_flush(ident_t *loc) 3879 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3880 emitUpdateLocation(CGF, Loc)); 3881 } 3882 3883 namespace { 3884 /// Indexes of fields for type kmp_task_t. 3885 enum KmpTaskTFields { 3886 /// List of shared variables. 3887 KmpTaskTShareds, 3888 /// Task routine. 3889 KmpTaskTRoutine, 3890 /// Partition id for the untied tasks. 3891 KmpTaskTPartId, 3892 /// Function with call of destructors for private variables. 3893 Data1, 3894 /// Task priority. 3895 Data2, 3896 /// (Taskloops only) Lower bound. 3897 KmpTaskTLowerBound, 3898 /// (Taskloops only) Upper bound. 3899 KmpTaskTUpperBound, 3900 /// (Taskloops only) Stride. 3901 KmpTaskTStride, 3902 /// (Taskloops only) Is last iteration flag. 3903 KmpTaskTLastIter, 3904 /// (Taskloops only) Reduction data. 3905 KmpTaskTReductions, 3906 }; 3907 } // anonymous namespace 3908 3909 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3910 return OffloadEntriesTargetRegion.empty() && 3911 OffloadEntriesDeviceGlobalVar.empty(); 3912 } 3913 3914 /// Initialize target region entry. 3915 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3916 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3917 StringRef ParentName, unsigned LineNum, 3918 unsigned Order) { 3919 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3920 "only required for the device " 3921 "code generation."); 3922 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3923 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3924 OMPTargetRegionEntryTargetRegion); 3925 ++OffloadingEntriesNum; 3926 } 3927 3928 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3929 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3930 StringRef ParentName, unsigned LineNum, 3931 llvm::Constant *Addr, llvm::Constant *ID, 3932 OMPTargetRegionEntryKind Flags) { 3933 // If we are emitting code for a target, the entry is already initialized, 3934 // only has to be registered. 3935 if (CGM.getLangOpts().OpenMPIsDevice) { 3936 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3937 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3938 DiagnosticsEngine::Error, 3939 "Unable to find target region on line '%0' in the device code."); 3940 CGM.getDiags().Report(DiagID) << LineNum; 3941 return; 3942 } 3943 auto &Entry = 3944 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3945 assert(Entry.isValid() && "Entry not initialized!"); 3946 Entry.setAddress(Addr); 3947 Entry.setID(ID); 3948 Entry.setFlags(Flags); 3949 } else { 3950 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3951 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3952 ++OffloadingEntriesNum; 3953 } 3954 } 3955 3956 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3957 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3958 unsigned LineNum) const { 3959 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3960 if (PerDevice == OffloadEntriesTargetRegion.end()) 3961 return false; 3962 auto PerFile = PerDevice->second.find(FileID); 3963 if (PerFile == PerDevice->second.end()) 3964 return false; 3965 auto PerParentName = PerFile->second.find(ParentName); 3966 if (PerParentName == PerFile->second.end()) 3967 return false; 3968 auto PerLine = PerParentName->second.find(LineNum); 3969 if (PerLine == PerParentName->second.end()) 3970 return false; 3971 // Fail if this entry is already registered. 3972 if (PerLine->second.getAddress() || PerLine->second.getID()) 3973 return false; 3974 return true; 3975 } 3976 3977 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3978 const OffloadTargetRegionEntryInfoActTy &Action) { 3979 // Scan all target region entries and perform the provided action. 3980 for (const auto &D : OffloadEntriesTargetRegion) 3981 for (const auto &F : D.second) 3982 for (const auto &P : F.second) 3983 for (const auto &L : P.second) 3984 Action(D.first, F.first, P.first(), L.first, L.second); 3985 } 3986 3987 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3988 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3989 OMPTargetGlobalVarEntryKind Flags, 3990 unsigned Order) { 3991 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3992 "only required for the device " 3993 "code generation."); 3994 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3995 ++OffloadingEntriesNum; 3996 } 3997 3998 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3999 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 4000 CharUnits VarSize, 4001 OMPTargetGlobalVarEntryKind Flags, 4002 llvm::GlobalValue::LinkageTypes Linkage) { 4003 if (CGM.getLangOpts().OpenMPIsDevice) { 4004 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4005 assert(Entry.isValid() && Entry.getFlags() == Flags && 4006 "Entry not initialized!"); 4007 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4008 "Resetting with the new address."); 4009 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 4010 if (Entry.getVarSize().isZero()) { 4011 Entry.setVarSize(VarSize); 4012 Entry.setLinkage(Linkage); 4013 } 4014 return; 4015 } 4016 Entry.setVarSize(VarSize); 4017 Entry.setLinkage(Linkage); 4018 Entry.setAddress(Addr); 4019 } else { 4020 if (hasDeviceGlobalVarEntryInfo(VarName)) { 4021 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4022 assert(Entry.isValid() && Entry.getFlags() == Flags && 4023 "Entry not initialized!"); 4024 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4025 "Resetting with the new address."); 4026 if (Entry.getVarSize().isZero()) { 4027 Entry.setVarSize(VarSize); 4028 Entry.setLinkage(Linkage); 4029 } 4030 return; 4031 } 4032 OffloadEntriesDeviceGlobalVar.try_emplace( 4033 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 4034 ++OffloadingEntriesNum; 4035 } 4036 } 4037 4038 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4039 actOnDeviceGlobalVarEntriesInfo( 4040 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4041 // Scan all target region entries and perform the provided action. 4042 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4043 Action(E.getKey(), E.getValue()); 4044 } 4045 4046 void CGOpenMPRuntime::createOffloadEntry( 4047 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4048 llvm::GlobalValue::LinkageTypes Linkage) { 4049 StringRef Name = Addr->getName(); 4050 llvm::Module &M = CGM.getModule(); 4051 llvm::LLVMContext &C = M.getContext(); 4052 4053 // Create constant string with the name. 4054 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4055 4056 std::string StringName = getName({"omp_offloading", "entry_name"}); 4057 auto *Str = new llvm::GlobalVariable( 4058 M, StrPtrInit->getType(), /*isConstant=*/true, 4059 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4060 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4061 4062 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4063 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4064 llvm::ConstantInt::get(CGM.SizeTy, Size), 4065 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4066 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4067 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4068 llvm::GlobalVariable *Entry = createGlobalStruct( 4069 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4070 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4071 4072 // The entry has to be created in the section the linker expects it to be. 4073 Entry->setSection("omp_offloading_entries"); 4074 } 4075 4076 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4077 // Emit the offloading entries and metadata so that the device codegen side 4078 // can easily figure out what to emit. The produced metadata looks like 4079 // this: 4080 // 4081 // !omp_offload.info = !{!1, ...} 4082 // 4083 // Right now we only generate metadata for function that contain target 4084 // regions. 4085 4086 // If we are in simd mode or there are no entries, we don't need to do 4087 // anything. 4088 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4089 return; 4090 4091 llvm::Module &M = CGM.getModule(); 4092 llvm::LLVMContext &C = M.getContext(); 4093 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4094 SourceLocation, StringRef>, 4095 16> 4096 OrderedEntries(OffloadEntriesInfoManager.size()); 4097 llvm::SmallVector<StringRef, 16> ParentFunctions( 4098 OffloadEntriesInfoManager.size()); 4099 4100 // Auxiliary methods to create metadata values and strings. 4101 auto &&GetMDInt = [this](unsigned V) { 4102 return llvm::ConstantAsMetadata::get( 4103 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4104 }; 4105 4106 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4107 4108 // Create the offloading info metadata node. 4109 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4110 4111 // Create function that emits metadata for each target region entry; 4112 auto &&TargetRegionMetadataEmitter = 4113 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4114 &GetMDString]( 4115 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4116 unsigned Line, 4117 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4118 // Generate metadata for target regions. Each entry of this metadata 4119 // contains: 4120 // - Entry 0 -> Kind of this type of metadata (0). 4121 // - Entry 1 -> Device ID of the file where the entry was identified. 4122 // - Entry 2 -> File ID of the file where the entry was identified. 4123 // - Entry 3 -> Mangled name of the function where the entry was 4124 // identified. 4125 // - Entry 4 -> Line in the file where the entry was identified. 4126 // - Entry 5 -> Order the entry was created. 4127 // The first element of the metadata node is the kind. 4128 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4129 GetMDInt(FileID), GetMDString(ParentName), 4130 GetMDInt(Line), GetMDInt(E.getOrder())}; 4131 4132 SourceLocation Loc; 4133 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4134 E = CGM.getContext().getSourceManager().fileinfo_end(); 4135 I != E; ++I) { 4136 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4137 I->getFirst()->getUniqueID().getFile() == FileID) { 4138 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4139 I->getFirst(), Line, 1); 4140 break; 4141 } 4142 } 4143 // Save this entry in the right position of the ordered entries array. 4144 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4145 ParentFunctions[E.getOrder()] = ParentName; 4146 4147 // Add metadata to the named metadata node. 4148 MD->addOperand(llvm::MDNode::get(C, Ops)); 4149 }; 4150 4151 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4152 TargetRegionMetadataEmitter); 4153 4154 // Create function that emits metadata for each device global variable entry; 4155 auto &&DeviceGlobalVarMetadataEmitter = 4156 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4157 MD](StringRef MangledName, 4158 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4159 &E) { 4160 // Generate metadata for global variables. Each entry of this metadata 4161 // contains: 4162 // - Entry 0 -> Kind of this type of metadata (1). 4163 // - Entry 1 -> Mangled name of the variable. 4164 // - Entry 2 -> Declare target kind. 4165 // - Entry 3 -> Order the entry was created. 4166 // The first element of the metadata node is the kind. 4167 llvm::Metadata *Ops[] = { 4168 GetMDInt(E.getKind()), GetMDString(MangledName), 4169 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4170 4171 // Save this entry in the right position of the ordered entries array. 4172 OrderedEntries[E.getOrder()] = 4173 std::make_tuple(&E, SourceLocation(), MangledName); 4174 4175 // Add metadata to the named metadata node. 4176 MD->addOperand(llvm::MDNode::get(C, Ops)); 4177 }; 4178 4179 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4180 DeviceGlobalVarMetadataEmitter); 4181 4182 for (const auto &E : OrderedEntries) { 4183 assert(std::get<0>(E) && "All ordered entries must exist!"); 4184 if (const auto *CE = 4185 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4186 std::get<0>(E))) { 4187 if (!CE->getID() || !CE->getAddress()) { 4188 // Do not blame the entry if the parent funtion is not emitted. 4189 StringRef FnName = ParentFunctions[CE->getOrder()]; 4190 if (!CGM.GetGlobalValue(FnName)) 4191 continue; 4192 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4193 DiagnosticsEngine::Error, 4194 "Offloading entry for target region in %0 is incorrect: either the " 4195 "address or the ID is invalid."); 4196 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4197 continue; 4198 } 4199 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4200 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4201 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4202 OffloadEntryInfoDeviceGlobalVar>( 4203 std::get<0>(E))) { 4204 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4205 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4206 CE->getFlags()); 4207 switch (Flags) { 4208 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4209 if (CGM.getLangOpts().OpenMPIsDevice && 4210 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4211 continue; 4212 if (!CE->getAddress()) { 4213 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4214 DiagnosticsEngine::Error, "Offloading entry for declare target " 4215 "variable %0 is incorrect: the " 4216 "address is invalid."); 4217 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4218 continue; 4219 } 4220 // The vaiable has no definition - no need to add the entry. 4221 if (CE->getVarSize().isZero()) 4222 continue; 4223 break; 4224 } 4225 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4226 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4227 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4228 "Declaret target link address is set."); 4229 if (CGM.getLangOpts().OpenMPIsDevice) 4230 continue; 4231 if (!CE->getAddress()) { 4232 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4233 DiagnosticsEngine::Error, 4234 "Offloading entry for declare target variable is incorrect: the " 4235 "address is invalid."); 4236 CGM.getDiags().Report(DiagID); 4237 continue; 4238 } 4239 break; 4240 } 4241 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4242 CE->getVarSize().getQuantity(), Flags, 4243 CE->getLinkage()); 4244 } else { 4245 llvm_unreachable("Unsupported entry kind."); 4246 } 4247 } 4248 } 4249 4250 /// Loads all the offload entries information from the host IR 4251 /// metadata. 4252 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4253 // If we are in target mode, load the metadata from the host IR. This code has 4254 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4255 4256 if (!CGM.getLangOpts().OpenMPIsDevice) 4257 return; 4258 4259 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4260 return; 4261 4262 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4263 if (auto EC = Buf.getError()) { 4264 CGM.getDiags().Report(diag::err_cannot_open_file) 4265 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4266 return; 4267 } 4268 4269 llvm::LLVMContext C; 4270 auto ME = expectedToErrorOrAndEmitErrors( 4271 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4272 4273 if (auto EC = ME.getError()) { 4274 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4275 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4276 CGM.getDiags().Report(DiagID) 4277 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4278 return; 4279 } 4280 4281 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4282 if (!MD) 4283 return; 4284 4285 for (llvm::MDNode *MN : MD->operands()) { 4286 auto &&GetMDInt = [MN](unsigned Idx) { 4287 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4288 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4289 }; 4290 4291 auto &&GetMDString = [MN](unsigned Idx) { 4292 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4293 return V->getString(); 4294 }; 4295 4296 switch (GetMDInt(0)) { 4297 default: 4298 llvm_unreachable("Unexpected metadata!"); 4299 break; 4300 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4301 OffloadingEntryInfoTargetRegion: 4302 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4303 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4304 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4305 /*Order=*/GetMDInt(5)); 4306 break; 4307 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4308 OffloadingEntryInfoDeviceGlobalVar: 4309 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4310 /*MangledName=*/GetMDString(1), 4311 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4312 /*Flags=*/GetMDInt(2)), 4313 /*Order=*/GetMDInt(3)); 4314 break; 4315 } 4316 } 4317 } 4318 4319 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4320 if (!KmpRoutineEntryPtrTy) { 4321 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4322 ASTContext &C = CGM.getContext(); 4323 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4324 FunctionProtoType::ExtProtoInfo EPI; 4325 KmpRoutineEntryPtrQTy = C.getPointerType( 4326 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4327 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4328 } 4329 } 4330 4331 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4332 // Make sure the type of the entry is already created. This is the type we 4333 // have to create: 4334 // struct __tgt_offload_entry{ 4335 // void *addr; // Pointer to the offload entry info. 4336 // // (function or global) 4337 // char *name; // Name of the function or global. 4338 // size_t size; // Size of the entry info (0 if it a function). 4339 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4340 // int32_t reserved; // Reserved, to use by the runtime library. 4341 // }; 4342 if (TgtOffloadEntryQTy.isNull()) { 4343 ASTContext &C = CGM.getContext(); 4344 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4345 RD->startDefinition(); 4346 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4347 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4348 addFieldToRecordDecl(C, RD, C.getSizeType()); 4349 addFieldToRecordDecl( 4350 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4351 addFieldToRecordDecl( 4352 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4353 RD->completeDefinition(); 4354 RD->addAttr(PackedAttr::CreateImplicit(C)); 4355 TgtOffloadEntryQTy = C.getRecordType(RD); 4356 } 4357 return TgtOffloadEntryQTy; 4358 } 4359 4360 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 4361 // These are the types we need to build: 4362 // struct __tgt_device_image{ 4363 // void *ImageStart; // Pointer to the target code start. 4364 // void *ImageEnd; // Pointer to the target code end. 4365 // // We also add the host entries to the device image, as it may be useful 4366 // // for the target runtime to have access to that information. 4367 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 4368 // // the entries. 4369 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4370 // // entries (non inclusive). 4371 // }; 4372 if (TgtDeviceImageQTy.isNull()) { 4373 ASTContext &C = CGM.getContext(); 4374 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image"); 4375 RD->startDefinition(); 4376 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4377 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4378 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4379 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4380 RD->completeDefinition(); 4381 TgtDeviceImageQTy = C.getRecordType(RD); 4382 } 4383 return TgtDeviceImageQTy; 4384 } 4385 4386 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 4387 // struct __tgt_bin_desc{ 4388 // int32_t NumDevices; // Number of devices supported. 4389 // __tgt_device_image *DeviceImages; // Arrays of device images 4390 // // (one per device). 4391 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 4392 // // entries. 4393 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4394 // // entries (non inclusive). 4395 // }; 4396 if (TgtBinaryDescriptorQTy.isNull()) { 4397 ASTContext &C = CGM.getContext(); 4398 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc"); 4399 RD->startDefinition(); 4400 addFieldToRecordDecl( 4401 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4402 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 4403 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4404 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4405 RD->completeDefinition(); 4406 TgtBinaryDescriptorQTy = C.getRecordType(RD); 4407 } 4408 return TgtBinaryDescriptorQTy; 4409 } 4410 4411 namespace { 4412 struct PrivateHelpersTy { 4413 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4414 const VarDecl *PrivateElemInit) 4415 : Original(Original), PrivateCopy(PrivateCopy), 4416 PrivateElemInit(PrivateElemInit) {} 4417 const VarDecl *Original; 4418 const VarDecl *PrivateCopy; 4419 const VarDecl *PrivateElemInit; 4420 }; 4421 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4422 } // anonymous namespace 4423 4424 static RecordDecl * 4425 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4426 if (!Privates.empty()) { 4427 ASTContext &C = CGM.getContext(); 4428 // Build struct .kmp_privates_t. { 4429 // /* private vars */ 4430 // }; 4431 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4432 RD->startDefinition(); 4433 for (const auto &Pair : Privates) { 4434 const VarDecl *VD = Pair.second.Original; 4435 QualType Type = VD->getType().getNonReferenceType(); 4436 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4437 if (VD->hasAttrs()) { 4438 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4439 E(VD->getAttrs().end()); 4440 I != E; ++I) 4441 FD->addAttr(*I); 4442 } 4443 } 4444 RD->completeDefinition(); 4445 return RD; 4446 } 4447 return nullptr; 4448 } 4449 4450 static RecordDecl * 4451 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4452 QualType KmpInt32Ty, 4453 QualType KmpRoutineEntryPointerQTy) { 4454 ASTContext &C = CGM.getContext(); 4455 // Build struct kmp_task_t { 4456 // void * shareds; 4457 // kmp_routine_entry_t routine; 4458 // kmp_int32 part_id; 4459 // kmp_cmplrdata_t data1; 4460 // kmp_cmplrdata_t data2; 4461 // For taskloops additional fields: 4462 // kmp_uint64 lb; 4463 // kmp_uint64 ub; 4464 // kmp_int64 st; 4465 // kmp_int32 liter; 4466 // void * reductions; 4467 // }; 4468 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4469 UD->startDefinition(); 4470 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4471 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4472 UD->completeDefinition(); 4473 QualType KmpCmplrdataTy = C.getRecordType(UD); 4474 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4475 RD->startDefinition(); 4476 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4477 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4478 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4479 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4480 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4481 if (isOpenMPTaskLoopDirective(Kind)) { 4482 QualType KmpUInt64Ty = 4483 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4484 QualType KmpInt64Ty = 4485 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4486 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4487 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4488 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4489 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4490 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4491 } 4492 RD->completeDefinition(); 4493 return RD; 4494 } 4495 4496 static RecordDecl * 4497 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4498 ArrayRef<PrivateDataTy> Privates) { 4499 ASTContext &C = CGM.getContext(); 4500 // Build struct kmp_task_t_with_privates { 4501 // kmp_task_t task_data; 4502 // .kmp_privates_t. privates; 4503 // }; 4504 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4505 RD->startDefinition(); 4506 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4507 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4508 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4509 RD->completeDefinition(); 4510 return RD; 4511 } 4512 4513 /// Emit a proxy function which accepts kmp_task_t as the second 4514 /// argument. 4515 /// \code 4516 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4517 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4518 /// For taskloops: 4519 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4520 /// tt->reductions, tt->shareds); 4521 /// return 0; 4522 /// } 4523 /// \endcode 4524 static llvm::Function * 4525 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4526 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4527 QualType KmpTaskTWithPrivatesPtrQTy, 4528 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4529 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4530 llvm::Value *TaskPrivatesMap) { 4531 ASTContext &C = CGM.getContext(); 4532 FunctionArgList Args; 4533 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4534 ImplicitParamDecl::Other); 4535 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4536 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4537 ImplicitParamDecl::Other); 4538 Args.push_back(&GtidArg); 4539 Args.push_back(&TaskTypeArg); 4540 const auto &TaskEntryFnInfo = 4541 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4542 llvm::FunctionType *TaskEntryTy = 4543 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4544 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4545 auto *TaskEntry = llvm::Function::Create( 4546 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4547 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4548 TaskEntry->setDoesNotRecurse(); 4549 CodeGenFunction CGF(CGM); 4550 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4551 Loc, Loc); 4552 4553 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4554 // tt, 4555 // For taskloops: 4556 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4557 // tt->task_data.shareds); 4558 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4559 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4560 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4561 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4562 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4563 const auto *KmpTaskTWithPrivatesQTyRD = 4564 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4565 LValue Base = 4566 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4567 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4568 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4569 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4570 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 4571 4572 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4573 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4574 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4575 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4576 CGF.ConvertTypeForMem(SharedsPtrTy)); 4577 4578 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4579 llvm::Value *PrivatesParam; 4580 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4581 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4582 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4583 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 4584 } else { 4585 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4586 } 4587 4588 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4589 TaskPrivatesMap, 4590 CGF.Builder 4591 .CreatePointerBitCastOrAddrSpaceCast( 4592 TDBase.getAddress(CGF), CGF.VoidPtrTy) 4593 .getPointer()}; 4594 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4595 std::end(CommonArgs)); 4596 if (isOpenMPTaskLoopDirective(Kind)) { 4597 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4598 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4599 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4600 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4601 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4602 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4603 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4604 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4605 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4606 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4607 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4608 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4609 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4610 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4611 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4612 CallArgs.push_back(LBParam); 4613 CallArgs.push_back(UBParam); 4614 CallArgs.push_back(StParam); 4615 CallArgs.push_back(LIParam); 4616 CallArgs.push_back(RParam); 4617 } 4618 CallArgs.push_back(SharedsParam); 4619 4620 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4621 CallArgs); 4622 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4623 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4624 CGF.FinishFunction(); 4625 return TaskEntry; 4626 } 4627 4628 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4629 SourceLocation Loc, 4630 QualType KmpInt32Ty, 4631 QualType KmpTaskTWithPrivatesPtrQTy, 4632 QualType KmpTaskTWithPrivatesQTy) { 4633 ASTContext &C = CGM.getContext(); 4634 FunctionArgList Args; 4635 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4636 ImplicitParamDecl::Other); 4637 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4638 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4639 ImplicitParamDecl::Other); 4640 Args.push_back(&GtidArg); 4641 Args.push_back(&TaskTypeArg); 4642 const auto &DestructorFnInfo = 4643 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4644 llvm::FunctionType *DestructorFnTy = 4645 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4646 std::string Name = 4647 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4648 auto *DestructorFn = 4649 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4650 Name, &CGM.getModule()); 4651 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4652 DestructorFnInfo); 4653 DestructorFn->setDoesNotRecurse(); 4654 CodeGenFunction CGF(CGM); 4655 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4656 Args, Loc, Loc); 4657 4658 LValue Base = CGF.EmitLoadOfPointerLValue( 4659 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4660 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4661 const auto *KmpTaskTWithPrivatesQTyRD = 4662 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4663 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4664 Base = CGF.EmitLValueForField(Base, *FI); 4665 for (const auto *Field : 4666 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4667 if (QualType::DestructionKind DtorKind = 4668 Field->getType().isDestructedType()) { 4669 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4670 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 4671 } 4672 } 4673 CGF.FinishFunction(); 4674 return DestructorFn; 4675 } 4676 4677 /// Emit a privates mapping function for correct handling of private and 4678 /// firstprivate variables. 4679 /// \code 4680 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4681 /// **noalias priv1,..., <tyn> **noalias privn) { 4682 /// *priv1 = &.privates.priv1; 4683 /// ...; 4684 /// *privn = &.privates.privn; 4685 /// } 4686 /// \endcode 4687 static llvm::Value * 4688 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4689 ArrayRef<const Expr *> PrivateVars, 4690 ArrayRef<const Expr *> FirstprivateVars, 4691 ArrayRef<const Expr *> LastprivateVars, 4692 QualType PrivatesQTy, 4693 ArrayRef<PrivateDataTy> Privates) { 4694 ASTContext &C = CGM.getContext(); 4695 FunctionArgList Args; 4696 ImplicitParamDecl TaskPrivatesArg( 4697 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4698 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4699 ImplicitParamDecl::Other); 4700 Args.push_back(&TaskPrivatesArg); 4701 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4702 unsigned Counter = 1; 4703 for (const Expr *E : PrivateVars) { 4704 Args.push_back(ImplicitParamDecl::Create( 4705 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4706 C.getPointerType(C.getPointerType(E->getType())) 4707 .withConst() 4708 .withRestrict(), 4709 ImplicitParamDecl::Other)); 4710 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4711 PrivateVarsPos[VD] = Counter; 4712 ++Counter; 4713 } 4714 for (const Expr *E : FirstprivateVars) { 4715 Args.push_back(ImplicitParamDecl::Create( 4716 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4717 C.getPointerType(C.getPointerType(E->getType())) 4718 .withConst() 4719 .withRestrict(), 4720 ImplicitParamDecl::Other)); 4721 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4722 PrivateVarsPos[VD] = Counter; 4723 ++Counter; 4724 } 4725 for (const Expr *E : LastprivateVars) { 4726 Args.push_back(ImplicitParamDecl::Create( 4727 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4728 C.getPointerType(C.getPointerType(E->getType())) 4729 .withConst() 4730 .withRestrict(), 4731 ImplicitParamDecl::Other)); 4732 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4733 PrivateVarsPos[VD] = Counter; 4734 ++Counter; 4735 } 4736 const auto &TaskPrivatesMapFnInfo = 4737 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4738 llvm::FunctionType *TaskPrivatesMapTy = 4739 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4740 std::string Name = 4741 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4742 auto *TaskPrivatesMap = llvm::Function::Create( 4743 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4744 &CGM.getModule()); 4745 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4746 TaskPrivatesMapFnInfo); 4747 if (CGM.getLangOpts().Optimize) { 4748 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4749 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4750 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4751 } 4752 CodeGenFunction CGF(CGM); 4753 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4754 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4755 4756 // *privi = &.privates.privi; 4757 LValue Base = CGF.EmitLoadOfPointerLValue( 4758 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4759 TaskPrivatesArg.getType()->castAs<PointerType>()); 4760 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4761 Counter = 0; 4762 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4763 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4764 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4765 LValue RefLVal = 4766 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4767 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4768 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 4769 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 4770 ++Counter; 4771 } 4772 CGF.FinishFunction(); 4773 return TaskPrivatesMap; 4774 } 4775 4776 /// Emit initialization for private variables in task-based directives. 4777 static void emitPrivatesInit(CodeGenFunction &CGF, 4778 const OMPExecutableDirective &D, 4779 Address KmpTaskSharedsPtr, LValue TDBase, 4780 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4781 QualType SharedsTy, QualType SharedsPtrTy, 4782 const OMPTaskDataTy &Data, 4783 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4784 ASTContext &C = CGF.getContext(); 4785 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4786 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4787 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4788 ? OMPD_taskloop 4789 : OMPD_task; 4790 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4791 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4792 LValue SrcBase; 4793 bool IsTargetTask = 4794 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4795 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4796 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4797 // PointersArray and SizesArray. The original variables for these arrays are 4798 // not captured and we get their addresses explicitly. 4799 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4800 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4801 SrcBase = CGF.MakeAddrLValue( 4802 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4803 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4804 SharedsTy); 4805 } 4806 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4807 for (const PrivateDataTy &Pair : Privates) { 4808 const VarDecl *VD = Pair.second.PrivateCopy; 4809 const Expr *Init = VD->getAnyInitializer(); 4810 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4811 !CGF.isTrivialInitializer(Init)))) { 4812 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4813 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4814 const VarDecl *OriginalVD = Pair.second.Original; 4815 // Check if the variable is the target-based BasePointersArray, 4816 // PointersArray or SizesArray. 4817 LValue SharedRefLValue; 4818 QualType Type = PrivateLValue.getType(); 4819 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4820 if (IsTargetTask && !SharedField) { 4821 assert(isa<ImplicitParamDecl>(OriginalVD) && 4822 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4823 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4824 ->getNumParams() == 0 && 4825 isa<TranslationUnitDecl>( 4826 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4827 ->getDeclContext()) && 4828 "Expected artificial target data variable."); 4829 SharedRefLValue = 4830 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4831 } else { 4832 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4833 SharedRefLValue = CGF.MakeAddrLValue( 4834 Address(SharedRefLValue.getPointer(CGF), 4835 C.getDeclAlign(OriginalVD)), 4836 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4837 SharedRefLValue.getTBAAInfo()); 4838 } 4839 if (Type->isArrayType()) { 4840 // Initialize firstprivate array. 4841 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4842 // Perform simple memcpy. 4843 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4844 } else { 4845 // Initialize firstprivate array using element-by-element 4846 // initialization. 4847 CGF.EmitOMPAggregateAssign( 4848 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 4849 Type, 4850 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4851 Address SrcElement) { 4852 // Clean up any temporaries needed by the initialization. 4853 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4854 InitScope.addPrivate( 4855 Elem, [SrcElement]() -> Address { return SrcElement; }); 4856 (void)InitScope.Privatize(); 4857 // Emit initialization for single element. 4858 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4859 CGF, &CapturesInfo); 4860 CGF.EmitAnyExprToMem(Init, DestElement, 4861 Init->getType().getQualifiers(), 4862 /*IsInitializer=*/false); 4863 }); 4864 } 4865 } else { 4866 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4867 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 4868 return SharedRefLValue.getAddress(CGF); 4869 }); 4870 (void)InitScope.Privatize(); 4871 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4872 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4873 /*capturedByInit=*/false); 4874 } 4875 } else { 4876 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4877 } 4878 } 4879 ++FI; 4880 } 4881 } 4882 4883 /// Check if duplication function is required for taskloops. 4884 static bool checkInitIsRequired(CodeGenFunction &CGF, 4885 ArrayRef<PrivateDataTy> Privates) { 4886 bool InitRequired = false; 4887 for (const PrivateDataTy &Pair : Privates) { 4888 const VarDecl *VD = Pair.second.PrivateCopy; 4889 const Expr *Init = VD->getAnyInitializer(); 4890 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4891 !CGF.isTrivialInitializer(Init)); 4892 if (InitRequired) 4893 break; 4894 } 4895 return InitRequired; 4896 } 4897 4898 4899 /// Emit task_dup function (for initialization of 4900 /// private/firstprivate/lastprivate vars and last_iter flag) 4901 /// \code 4902 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4903 /// lastpriv) { 4904 /// // setup lastprivate flag 4905 /// task_dst->last = lastpriv; 4906 /// // could be constructor calls here... 4907 /// } 4908 /// \endcode 4909 static llvm::Value * 4910 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4911 const OMPExecutableDirective &D, 4912 QualType KmpTaskTWithPrivatesPtrQTy, 4913 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4914 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4915 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4916 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4917 ASTContext &C = CGM.getContext(); 4918 FunctionArgList Args; 4919 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4920 KmpTaskTWithPrivatesPtrQTy, 4921 ImplicitParamDecl::Other); 4922 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4923 KmpTaskTWithPrivatesPtrQTy, 4924 ImplicitParamDecl::Other); 4925 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4926 ImplicitParamDecl::Other); 4927 Args.push_back(&DstArg); 4928 Args.push_back(&SrcArg); 4929 Args.push_back(&LastprivArg); 4930 const auto &TaskDupFnInfo = 4931 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4932 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4933 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4934 auto *TaskDup = llvm::Function::Create( 4935 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4936 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4937 TaskDup->setDoesNotRecurse(); 4938 CodeGenFunction CGF(CGM); 4939 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4940 Loc); 4941 4942 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4943 CGF.GetAddrOfLocalVar(&DstArg), 4944 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4945 // task_dst->liter = lastpriv; 4946 if (WithLastIter) { 4947 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4948 LValue Base = CGF.EmitLValueForField( 4949 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4950 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4951 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4952 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4953 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4954 } 4955 4956 // Emit initial values for private copies (if any). 4957 assert(!Privates.empty()); 4958 Address KmpTaskSharedsPtr = Address::invalid(); 4959 if (!Data.FirstprivateVars.empty()) { 4960 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4961 CGF.GetAddrOfLocalVar(&SrcArg), 4962 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4963 LValue Base = CGF.EmitLValueForField( 4964 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4965 KmpTaskSharedsPtr = Address( 4966 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4967 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4968 KmpTaskTShareds)), 4969 Loc), 4970 CGF.getNaturalTypeAlignment(SharedsTy)); 4971 } 4972 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4973 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4974 CGF.FinishFunction(); 4975 return TaskDup; 4976 } 4977 4978 /// Checks if destructor function is required to be generated. 4979 /// \return true if cleanups are required, false otherwise. 4980 static bool 4981 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4982 bool NeedsCleanup = false; 4983 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4984 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4985 for (const FieldDecl *FD : PrivateRD->fields()) { 4986 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4987 if (NeedsCleanup) 4988 break; 4989 } 4990 return NeedsCleanup; 4991 } 4992 4993 CGOpenMPRuntime::TaskResultTy 4994 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4995 const OMPExecutableDirective &D, 4996 llvm::Function *TaskFunction, QualType SharedsTy, 4997 Address Shareds, const OMPTaskDataTy &Data) { 4998 ASTContext &C = CGM.getContext(); 4999 llvm::SmallVector<PrivateDataTy, 4> Privates; 5000 // Aggregate privates and sort them by the alignment. 5001 auto I = Data.PrivateCopies.begin(); 5002 for (const Expr *E : Data.PrivateVars) { 5003 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5004 Privates.emplace_back( 5005 C.getDeclAlign(VD), 5006 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5007 /*PrivateElemInit=*/nullptr)); 5008 ++I; 5009 } 5010 I = Data.FirstprivateCopies.begin(); 5011 auto IElemInitRef = Data.FirstprivateInits.begin(); 5012 for (const Expr *E : Data.FirstprivateVars) { 5013 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5014 Privates.emplace_back( 5015 C.getDeclAlign(VD), 5016 PrivateHelpersTy( 5017 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5018 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 5019 ++I; 5020 ++IElemInitRef; 5021 } 5022 I = Data.LastprivateCopies.begin(); 5023 for (const Expr *E : Data.LastprivateVars) { 5024 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 5025 Privates.emplace_back( 5026 C.getDeclAlign(VD), 5027 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 5028 /*PrivateElemInit=*/nullptr)); 5029 ++I; 5030 } 5031 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 5032 return L.first > R.first; 5033 }); 5034 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 5035 // Build type kmp_routine_entry_t (if not built yet). 5036 emitKmpRoutineEntryT(KmpInt32Ty); 5037 // Build type kmp_task_t (if not built yet). 5038 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5039 if (SavedKmpTaskloopTQTy.isNull()) { 5040 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5041 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5042 } 5043 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5044 } else { 5045 assert((D.getDirectiveKind() == OMPD_task || 5046 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5047 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5048 "Expected taskloop, task or target directive"); 5049 if (SavedKmpTaskTQTy.isNull()) { 5050 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5051 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5052 } 5053 KmpTaskTQTy = SavedKmpTaskTQTy; 5054 } 5055 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5056 // Build particular struct kmp_task_t for the given task. 5057 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5058 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5059 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5060 QualType KmpTaskTWithPrivatesPtrQTy = 5061 C.getPointerType(KmpTaskTWithPrivatesQTy); 5062 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5063 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5064 KmpTaskTWithPrivatesTy->getPointerTo(); 5065 llvm::Value *KmpTaskTWithPrivatesTySize = 5066 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5067 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5068 5069 // Emit initial values for private copies (if any). 5070 llvm::Value *TaskPrivatesMap = nullptr; 5071 llvm::Type *TaskPrivatesMapTy = 5072 std::next(TaskFunction->arg_begin(), 3)->getType(); 5073 if (!Privates.empty()) { 5074 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5075 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5076 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5077 FI->getType(), Privates); 5078 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5079 TaskPrivatesMap, TaskPrivatesMapTy); 5080 } else { 5081 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5082 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5083 } 5084 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5085 // kmp_task_t *tt); 5086 llvm::Function *TaskEntry = emitProxyTaskFunction( 5087 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5088 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5089 TaskPrivatesMap); 5090 5091 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5092 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5093 // kmp_routine_entry_t *task_entry); 5094 // Task flags. Format is taken from 5095 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5096 // description of kmp_tasking_flags struct. 5097 enum { 5098 TiedFlag = 0x1, 5099 FinalFlag = 0x2, 5100 DestructorsFlag = 0x8, 5101 PriorityFlag = 0x20 5102 }; 5103 unsigned Flags = Data.Tied ? TiedFlag : 0; 5104 bool NeedsCleanup = false; 5105 if (!Privates.empty()) { 5106 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5107 if (NeedsCleanup) 5108 Flags = Flags | DestructorsFlag; 5109 } 5110 if (Data.Priority.getInt()) 5111 Flags = Flags | PriorityFlag; 5112 llvm::Value *TaskFlags = 5113 Data.Final.getPointer() 5114 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5115 CGF.Builder.getInt32(FinalFlag), 5116 CGF.Builder.getInt32(/*C=*/0)) 5117 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5118 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5119 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5120 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5121 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5122 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5123 TaskEntry, KmpRoutineEntryPtrTy)}; 5124 llvm::Value *NewTask; 5125 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5126 // Check if we have any device clause associated with the directive. 5127 const Expr *Device = nullptr; 5128 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5129 Device = C->getDevice(); 5130 // Emit device ID if any otherwise use default value. 5131 llvm::Value *DeviceID; 5132 if (Device) 5133 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5134 CGF.Int64Ty, /*isSigned=*/true); 5135 else 5136 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5137 AllocArgs.push_back(DeviceID); 5138 NewTask = CGF.EmitRuntimeCall( 5139 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5140 } else { 5141 NewTask = CGF.EmitRuntimeCall( 5142 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5143 } 5144 llvm::Value *NewTaskNewTaskTTy = 5145 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5146 NewTask, KmpTaskTWithPrivatesPtrTy); 5147 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5148 KmpTaskTWithPrivatesQTy); 5149 LValue TDBase = 5150 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5151 // Fill the data in the resulting kmp_task_t record. 5152 // Copy shareds if there are any. 5153 Address KmpTaskSharedsPtr = Address::invalid(); 5154 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5155 KmpTaskSharedsPtr = 5156 Address(CGF.EmitLoadOfScalar( 5157 CGF.EmitLValueForField( 5158 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5159 KmpTaskTShareds)), 5160 Loc), 5161 CGF.getNaturalTypeAlignment(SharedsTy)); 5162 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5163 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5164 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5165 } 5166 // Emit initial values for private copies (if any). 5167 TaskResultTy Result; 5168 if (!Privates.empty()) { 5169 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5170 SharedsTy, SharedsPtrTy, Data, Privates, 5171 /*ForDup=*/false); 5172 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5173 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5174 Result.TaskDupFn = emitTaskDupFunction( 5175 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5176 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5177 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5178 } 5179 } 5180 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5181 enum { Priority = 0, Destructors = 1 }; 5182 // Provide pointer to function with destructors for privates. 5183 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5184 const RecordDecl *KmpCmplrdataUD = 5185 (*FI)->getType()->getAsUnionType()->getDecl(); 5186 if (NeedsCleanup) { 5187 llvm::Value *DestructorFn = emitDestructorsFunction( 5188 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5189 KmpTaskTWithPrivatesQTy); 5190 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5191 LValue DestructorsLV = CGF.EmitLValueForField( 5192 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5193 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5194 DestructorFn, KmpRoutineEntryPtrTy), 5195 DestructorsLV); 5196 } 5197 // Set priority. 5198 if (Data.Priority.getInt()) { 5199 LValue Data2LV = CGF.EmitLValueForField( 5200 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5201 LValue PriorityLV = CGF.EmitLValueForField( 5202 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5203 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5204 } 5205 Result.NewTask = NewTask; 5206 Result.TaskEntry = TaskEntry; 5207 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5208 Result.TDBase = TDBase; 5209 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5210 return Result; 5211 } 5212 5213 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5214 const OMPExecutableDirective &D, 5215 llvm::Function *TaskFunction, 5216 QualType SharedsTy, Address Shareds, 5217 const Expr *IfCond, 5218 const OMPTaskDataTy &Data) { 5219 if (!CGF.HaveInsertPoint()) 5220 return; 5221 5222 TaskResultTy Result = 5223 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5224 llvm::Value *NewTask = Result.NewTask; 5225 llvm::Function *TaskEntry = Result.TaskEntry; 5226 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5227 LValue TDBase = Result.TDBase; 5228 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5229 ASTContext &C = CGM.getContext(); 5230 // Process list of dependences. 5231 Address DependenciesArray = Address::invalid(); 5232 unsigned NumDependencies = Data.Dependences.size(); 5233 if (NumDependencies) { 5234 // Dependence kind for RTL. 5235 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5236 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5237 RecordDecl *KmpDependInfoRD; 5238 QualType FlagsTy = 5239 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5240 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5241 if (KmpDependInfoTy.isNull()) { 5242 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5243 KmpDependInfoRD->startDefinition(); 5244 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5245 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5246 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5247 KmpDependInfoRD->completeDefinition(); 5248 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5249 } else { 5250 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5251 } 5252 // Define type kmp_depend_info[<Dependences.size()>]; 5253 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5254 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5255 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5256 // kmp_depend_info[<Dependences.size()>] deps; 5257 DependenciesArray = 5258 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5259 for (unsigned I = 0; I < NumDependencies; ++I) { 5260 const Expr *E = Data.Dependences[I].second; 5261 LValue Addr = CGF.EmitLValue(E); 5262 llvm::Value *Size; 5263 QualType Ty = E->getType(); 5264 if (const auto *ASE = 5265 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5266 LValue UpAddrLVal = 5267 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5268 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 5269 UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 5270 llvm::Value *LowIntPtr = 5271 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy); 5272 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5273 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5274 } else { 5275 Size = CGF.getTypeSize(Ty); 5276 } 5277 LValue Base = CGF.MakeAddrLValue( 5278 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5279 KmpDependInfoTy); 5280 // deps[i].base_addr = &<Dependences[i].second>; 5281 LValue BaseAddrLVal = CGF.EmitLValueForField( 5282 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5283 CGF.EmitStoreOfScalar( 5284 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy), 5285 BaseAddrLVal); 5286 // deps[i].len = sizeof(<Dependences[i].second>); 5287 LValue LenLVal = CGF.EmitLValueForField( 5288 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5289 CGF.EmitStoreOfScalar(Size, LenLVal); 5290 // deps[i].flags = <Dependences[i].first>; 5291 RTLDependenceKindTy DepKind; 5292 switch (Data.Dependences[I].first) { 5293 case OMPC_DEPEND_in: 5294 DepKind = DepIn; 5295 break; 5296 // Out and InOut dependencies must use the same code. 5297 case OMPC_DEPEND_out: 5298 case OMPC_DEPEND_inout: 5299 DepKind = DepInOut; 5300 break; 5301 case OMPC_DEPEND_mutexinoutset: 5302 DepKind = DepMutexInOutSet; 5303 break; 5304 case OMPC_DEPEND_source: 5305 case OMPC_DEPEND_sink: 5306 case OMPC_DEPEND_unknown: 5307 llvm_unreachable("Unknown task dependence type"); 5308 } 5309 LValue FlagsLVal = CGF.EmitLValueForField( 5310 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5311 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5312 FlagsLVal); 5313 } 5314 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5315 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5316 } 5317 5318 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5319 // libcall. 5320 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5321 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5322 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5323 // list is not empty 5324 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5325 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5326 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5327 llvm::Value *DepTaskArgs[7]; 5328 if (NumDependencies) { 5329 DepTaskArgs[0] = UpLoc; 5330 DepTaskArgs[1] = ThreadID; 5331 DepTaskArgs[2] = NewTask; 5332 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5333 DepTaskArgs[4] = DependenciesArray.getPointer(); 5334 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5335 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5336 } 5337 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5338 &TaskArgs, 5339 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5340 if (!Data.Tied) { 5341 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5342 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5343 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5344 } 5345 if (NumDependencies) { 5346 CGF.EmitRuntimeCall( 5347 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5348 } else { 5349 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5350 TaskArgs); 5351 } 5352 // Check if parent region is untied and build return for untied task; 5353 if (auto *Region = 5354 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5355 Region->emitUntiedSwitch(CGF); 5356 }; 5357 5358 llvm::Value *DepWaitTaskArgs[6]; 5359 if (NumDependencies) { 5360 DepWaitTaskArgs[0] = UpLoc; 5361 DepWaitTaskArgs[1] = ThreadID; 5362 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5363 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5364 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5365 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5366 } 5367 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5368 NumDependencies, &DepWaitTaskArgs, 5369 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5370 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5371 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5372 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5373 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5374 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5375 // is specified. 5376 if (NumDependencies) 5377 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5378 DepWaitTaskArgs); 5379 // Call proxy_task_entry(gtid, new_task); 5380 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5381 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5382 Action.Enter(CGF); 5383 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5384 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5385 OutlinedFnArgs); 5386 }; 5387 5388 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5389 // kmp_task_t *new_task); 5390 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5391 // kmp_task_t *new_task); 5392 RegionCodeGenTy RCG(CodeGen); 5393 CommonActionTy Action( 5394 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5395 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5396 RCG.setAction(Action); 5397 RCG(CGF); 5398 }; 5399 5400 if (IfCond) { 5401 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5402 } else { 5403 RegionCodeGenTy ThenRCG(ThenCodeGen); 5404 ThenRCG(CGF); 5405 } 5406 } 5407 5408 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5409 const OMPLoopDirective &D, 5410 llvm::Function *TaskFunction, 5411 QualType SharedsTy, Address Shareds, 5412 const Expr *IfCond, 5413 const OMPTaskDataTy &Data) { 5414 if (!CGF.HaveInsertPoint()) 5415 return; 5416 TaskResultTy Result = 5417 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5418 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5419 // libcall. 5420 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5421 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5422 // sched, kmp_uint64 grainsize, void *task_dup); 5423 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5424 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5425 llvm::Value *IfVal; 5426 if (IfCond) { 5427 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5428 /*isSigned=*/true); 5429 } else { 5430 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5431 } 5432 5433 LValue LBLVal = CGF.EmitLValueForField( 5434 Result.TDBase, 5435 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5436 const auto *LBVar = 5437 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5438 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5439 LBLVal.getQuals(), 5440 /*IsInitializer=*/true); 5441 LValue UBLVal = CGF.EmitLValueForField( 5442 Result.TDBase, 5443 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5444 const auto *UBVar = 5445 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5446 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5447 UBLVal.getQuals(), 5448 /*IsInitializer=*/true); 5449 LValue StLVal = CGF.EmitLValueForField( 5450 Result.TDBase, 5451 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5452 const auto *StVar = 5453 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5454 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5455 StLVal.getQuals(), 5456 /*IsInitializer=*/true); 5457 // Store reductions address. 5458 LValue RedLVal = CGF.EmitLValueForField( 5459 Result.TDBase, 5460 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5461 if (Data.Reductions) { 5462 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5463 } else { 5464 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5465 CGF.getContext().VoidPtrTy); 5466 } 5467 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5468 llvm::Value *TaskArgs[] = { 5469 UpLoc, 5470 ThreadID, 5471 Result.NewTask, 5472 IfVal, 5473 LBLVal.getPointer(CGF), 5474 UBLVal.getPointer(CGF), 5475 CGF.EmitLoadOfScalar(StLVal, Loc), 5476 llvm::ConstantInt::getSigned( 5477 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5478 llvm::ConstantInt::getSigned( 5479 CGF.IntTy, Data.Schedule.getPointer() 5480 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5481 : NoSchedule), 5482 Data.Schedule.getPointer() 5483 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5484 /*isSigned=*/false) 5485 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5486 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5487 Result.TaskDupFn, CGF.VoidPtrTy) 5488 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5489 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5490 } 5491 5492 /// Emit reduction operation for each element of array (required for 5493 /// array sections) LHS op = RHS. 5494 /// \param Type Type of array. 5495 /// \param LHSVar Variable on the left side of the reduction operation 5496 /// (references element of array in original variable). 5497 /// \param RHSVar Variable on the right side of the reduction operation 5498 /// (references element of array in original variable). 5499 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5500 /// RHSVar. 5501 static void EmitOMPAggregateReduction( 5502 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5503 const VarDecl *RHSVar, 5504 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5505 const Expr *, const Expr *)> &RedOpGen, 5506 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5507 const Expr *UpExpr = nullptr) { 5508 // Perform element-by-element initialization. 5509 QualType ElementTy; 5510 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5511 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5512 5513 // Drill down to the base element type on both arrays. 5514 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5515 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5516 5517 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5518 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5519 // Cast from pointer to array type to pointer to single element. 5520 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5521 // The basic structure here is a while-do loop. 5522 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5523 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5524 llvm::Value *IsEmpty = 5525 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5526 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5527 5528 // Enter the loop body, making that address the current address. 5529 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5530 CGF.EmitBlock(BodyBB); 5531 5532 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5533 5534 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5535 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5536 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5537 Address RHSElementCurrent = 5538 Address(RHSElementPHI, 5539 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5540 5541 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5542 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5543 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5544 Address LHSElementCurrent = 5545 Address(LHSElementPHI, 5546 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5547 5548 // Emit copy. 5549 CodeGenFunction::OMPPrivateScope Scope(CGF); 5550 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5551 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5552 Scope.Privatize(); 5553 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5554 Scope.ForceCleanup(); 5555 5556 // Shift the address forward by one element. 5557 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5558 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5559 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5560 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5561 // Check whether we've reached the end. 5562 llvm::Value *Done = 5563 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5564 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5565 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5566 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5567 5568 // Done. 5569 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5570 } 5571 5572 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5573 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5574 /// UDR combiner function. 5575 static void emitReductionCombiner(CodeGenFunction &CGF, 5576 const Expr *ReductionOp) { 5577 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5578 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5579 if (const auto *DRE = 5580 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5581 if (const auto *DRD = 5582 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5583 std::pair<llvm::Function *, llvm::Function *> Reduction = 5584 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5585 RValue Func = RValue::get(Reduction.first); 5586 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5587 CGF.EmitIgnoredExpr(ReductionOp); 5588 return; 5589 } 5590 CGF.EmitIgnoredExpr(ReductionOp); 5591 } 5592 5593 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5594 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5595 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5596 ArrayRef<const Expr *> ReductionOps) { 5597 ASTContext &C = CGM.getContext(); 5598 5599 // void reduction_func(void *LHSArg, void *RHSArg); 5600 FunctionArgList Args; 5601 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5602 ImplicitParamDecl::Other); 5603 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5604 ImplicitParamDecl::Other); 5605 Args.push_back(&LHSArg); 5606 Args.push_back(&RHSArg); 5607 const auto &CGFI = 5608 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5609 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5610 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5611 llvm::GlobalValue::InternalLinkage, Name, 5612 &CGM.getModule()); 5613 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5614 Fn->setDoesNotRecurse(); 5615 CodeGenFunction CGF(CGM); 5616 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5617 5618 // Dst = (void*[n])(LHSArg); 5619 // Src = (void*[n])(RHSArg); 5620 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5621 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5622 ArgsType), CGF.getPointerAlign()); 5623 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5624 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5625 ArgsType), CGF.getPointerAlign()); 5626 5627 // ... 5628 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5629 // ... 5630 CodeGenFunction::OMPPrivateScope Scope(CGF); 5631 auto IPriv = Privates.begin(); 5632 unsigned Idx = 0; 5633 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5634 const auto *RHSVar = 5635 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5636 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5637 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5638 }); 5639 const auto *LHSVar = 5640 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5641 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5642 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5643 }); 5644 QualType PrivTy = (*IPriv)->getType(); 5645 if (PrivTy->isVariablyModifiedType()) { 5646 // Get array size and emit VLA type. 5647 ++Idx; 5648 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5649 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5650 const VariableArrayType *VLA = 5651 CGF.getContext().getAsVariableArrayType(PrivTy); 5652 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5653 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5654 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5655 CGF.EmitVariablyModifiedType(PrivTy); 5656 } 5657 } 5658 Scope.Privatize(); 5659 IPriv = Privates.begin(); 5660 auto ILHS = LHSExprs.begin(); 5661 auto IRHS = RHSExprs.begin(); 5662 for (const Expr *E : ReductionOps) { 5663 if ((*IPriv)->getType()->isArrayType()) { 5664 // Emit reduction for array section. 5665 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5666 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5667 EmitOMPAggregateReduction( 5668 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5669 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5670 emitReductionCombiner(CGF, E); 5671 }); 5672 } else { 5673 // Emit reduction for array subscript or single variable. 5674 emitReductionCombiner(CGF, E); 5675 } 5676 ++IPriv; 5677 ++ILHS; 5678 ++IRHS; 5679 } 5680 Scope.ForceCleanup(); 5681 CGF.FinishFunction(); 5682 return Fn; 5683 } 5684 5685 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5686 const Expr *ReductionOp, 5687 const Expr *PrivateRef, 5688 const DeclRefExpr *LHS, 5689 const DeclRefExpr *RHS) { 5690 if (PrivateRef->getType()->isArrayType()) { 5691 // Emit reduction for array section. 5692 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5693 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5694 EmitOMPAggregateReduction( 5695 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5696 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5697 emitReductionCombiner(CGF, ReductionOp); 5698 }); 5699 } else { 5700 // Emit reduction for array subscript or single variable. 5701 emitReductionCombiner(CGF, ReductionOp); 5702 } 5703 } 5704 5705 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5706 ArrayRef<const Expr *> Privates, 5707 ArrayRef<const Expr *> LHSExprs, 5708 ArrayRef<const Expr *> RHSExprs, 5709 ArrayRef<const Expr *> ReductionOps, 5710 ReductionOptionsTy Options) { 5711 if (!CGF.HaveInsertPoint()) 5712 return; 5713 5714 bool WithNowait = Options.WithNowait; 5715 bool SimpleReduction = Options.SimpleReduction; 5716 5717 // Next code should be emitted for reduction: 5718 // 5719 // static kmp_critical_name lock = { 0 }; 5720 // 5721 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5722 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5723 // ... 5724 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5725 // *(Type<n>-1*)rhs[<n>-1]); 5726 // } 5727 // 5728 // ... 5729 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5730 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5731 // RedList, reduce_func, &<lock>)) { 5732 // case 1: 5733 // ... 5734 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5735 // ... 5736 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5737 // break; 5738 // case 2: 5739 // ... 5740 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5741 // ... 5742 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5743 // break; 5744 // default:; 5745 // } 5746 // 5747 // if SimpleReduction is true, only the next code is generated: 5748 // ... 5749 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5750 // ... 5751 5752 ASTContext &C = CGM.getContext(); 5753 5754 if (SimpleReduction) { 5755 CodeGenFunction::RunCleanupsScope Scope(CGF); 5756 auto IPriv = Privates.begin(); 5757 auto ILHS = LHSExprs.begin(); 5758 auto IRHS = RHSExprs.begin(); 5759 for (const Expr *E : ReductionOps) { 5760 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5761 cast<DeclRefExpr>(*IRHS)); 5762 ++IPriv; 5763 ++ILHS; 5764 ++IRHS; 5765 } 5766 return; 5767 } 5768 5769 // 1. Build a list of reduction variables. 5770 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5771 auto Size = RHSExprs.size(); 5772 for (const Expr *E : Privates) { 5773 if (E->getType()->isVariablyModifiedType()) 5774 // Reserve place for array size. 5775 ++Size; 5776 } 5777 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5778 QualType ReductionArrayTy = 5779 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5780 /*IndexTypeQuals=*/0); 5781 Address ReductionList = 5782 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5783 auto IPriv = Privates.begin(); 5784 unsigned Idx = 0; 5785 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5786 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5787 CGF.Builder.CreateStore( 5788 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5789 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5790 Elem); 5791 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5792 // Store array size. 5793 ++Idx; 5794 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5795 llvm::Value *Size = CGF.Builder.CreateIntCast( 5796 CGF.getVLASize( 5797 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5798 .NumElts, 5799 CGF.SizeTy, /*isSigned=*/false); 5800 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5801 Elem); 5802 } 5803 } 5804 5805 // 2. Emit reduce_func(). 5806 llvm::Function *ReductionFn = emitReductionFunction( 5807 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5808 LHSExprs, RHSExprs, ReductionOps); 5809 5810 // 3. Create static kmp_critical_name lock = { 0 }; 5811 std::string Name = getName({"reduction"}); 5812 llvm::Value *Lock = getCriticalRegionLock(Name); 5813 5814 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5815 // RedList, reduce_func, &<lock>); 5816 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5817 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5818 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5819 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5820 ReductionList.getPointer(), CGF.VoidPtrTy); 5821 llvm::Value *Args[] = { 5822 IdentTLoc, // ident_t *<loc> 5823 ThreadId, // i32 <gtid> 5824 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5825 ReductionArrayTySize, // size_type sizeof(RedList) 5826 RL, // void *RedList 5827 ReductionFn, // void (*) (void *, void *) <reduce_func> 5828 Lock // kmp_critical_name *&<lock> 5829 }; 5830 llvm::Value *Res = CGF.EmitRuntimeCall( 5831 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5832 : OMPRTL__kmpc_reduce), 5833 Args); 5834 5835 // 5. Build switch(res) 5836 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5837 llvm::SwitchInst *SwInst = 5838 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5839 5840 // 6. Build case 1: 5841 // ... 5842 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5843 // ... 5844 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5845 // break; 5846 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5847 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5848 CGF.EmitBlock(Case1BB); 5849 5850 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5851 llvm::Value *EndArgs[] = { 5852 IdentTLoc, // ident_t *<loc> 5853 ThreadId, // i32 <gtid> 5854 Lock // kmp_critical_name *&<lock> 5855 }; 5856 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5857 CodeGenFunction &CGF, PrePostActionTy &Action) { 5858 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5859 auto IPriv = Privates.begin(); 5860 auto ILHS = LHSExprs.begin(); 5861 auto IRHS = RHSExprs.begin(); 5862 for (const Expr *E : ReductionOps) { 5863 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5864 cast<DeclRefExpr>(*IRHS)); 5865 ++IPriv; 5866 ++ILHS; 5867 ++IRHS; 5868 } 5869 }; 5870 RegionCodeGenTy RCG(CodeGen); 5871 CommonActionTy Action( 5872 nullptr, llvm::None, 5873 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5874 : OMPRTL__kmpc_end_reduce), 5875 EndArgs); 5876 RCG.setAction(Action); 5877 RCG(CGF); 5878 5879 CGF.EmitBranch(DefaultBB); 5880 5881 // 7. Build case 2: 5882 // ... 5883 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5884 // ... 5885 // break; 5886 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5887 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5888 CGF.EmitBlock(Case2BB); 5889 5890 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5891 CodeGenFunction &CGF, PrePostActionTy &Action) { 5892 auto ILHS = LHSExprs.begin(); 5893 auto IRHS = RHSExprs.begin(); 5894 auto IPriv = Privates.begin(); 5895 for (const Expr *E : ReductionOps) { 5896 const Expr *XExpr = nullptr; 5897 const Expr *EExpr = nullptr; 5898 const Expr *UpExpr = nullptr; 5899 BinaryOperatorKind BO = BO_Comma; 5900 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5901 if (BO->getOpcode() == BO_Assign) { 5902 XExpr = BO->getLHS(); 5903 UpExpr = BO->getRHS(); 5904 } 5905 } 5906 // Try to emit update expression as a simple atomic. 5907 const Expr *RHSExpr = UpExpr; 5908 if (RHSExpr) { 5909 // Analyze RHS part of the whole expression. 5910 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5911 RHSExpr->IgnoreParenImpCasts())) { 5912 // If this is a conditional operator, analyze its condition for 5913 // min/max reduction operator. 5914 RHSExpr = ACO->getCond(); 5915 } 5916 if (const auto *BORHS = 5917 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5918 EExpr = BORHS->getRHS(); 5919 BO = BORHS->getOpcode(); 5920 } 5921 } 5922 if (XExpr) { 5923 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5924 auto &&AtomicRedGen = [BO, VD, 5925 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5926 const Expr *EExpr, const Expr *UpExpr) { 5927 LValue X = CGF.EmitLValue(XExpr); 5928 RValue E; 5929 if (EExpr) 5930 E = CGF.EmitAnyExpr(EExpr); 5931 CGF.EmitOMPAtomicSimpleUpdateExpr( 5932 X, E, BO, /*IsXLHSInRHSPart=*/true, 5933 llvm::AtomicOrdering::Monotonic, Loc, 5934 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5935 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5936 PrivateScope.addPrivate( 5937 VD, [&CGF, VD, XRValue, Loc]() { 5938 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5939 CGF.emitOMPSimpleStore( 5940 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5941 VD->getType().getNonReferenceType(), Loc); 5942 return LHSTemp; 5943 }); 5944 (void)PrivateScope.Privatize(); 5945 return CGF.EmitAnyExpr(UpExpr); 5946 }); 5947 }; 5948 if ((*IPriv)->getType()->isArrayType()) { 5949 // Emit atomic reduction for array section. 5950 const auto *RHSVar = 5951 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5952 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5953 AtomicRedGen, XExpr, EExpr, UpExpr); 5954 } else { 5955 // Emit atomic reduction for array subscript or single variable. 5956 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5957 } 5958 } else { 5959 // Emit as a critical region. 5960 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5961 const Expr *, const Expr *) { 5962 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5963 std::string Name = RT.getName({"atomic_reduction"}); 5964 RT.emitCriticalRegion( 5965 CGF, Name, 5966 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5967 Action.Enter(CGF); 5968 emitReductionCombiner(CGF, E); 5969 }, 5970 Loc); 5971 }; 5972 if ((*IPriv)->getType()->isArrayType()) { 5973 const auto *LHSVar = 5974 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5975 const auto *RHSVar = 5976 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5977 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5978 CritRedGen); 5979 } else { 5980 CritRedGen(CGF, nullptr, nullptr, nullptr); 5981 } 5982 } 5983 ++ILHS; 5984 ++IRHS; 5985 ++IPriv; 5986 } 5987 }; 5988 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5989 if (!WithNowait) { 5990 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5991 llvm::Value *EndArgs[] = { 5992 IdentTLoc, // ident_t *<loc> 5993 ThreadId, // i32 <gtid> 5994 Lock // kmp_critical_name *&<lock> 5995 }; 5996 CommonActionTy Action(nullptr, llvm::None, 5997 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 5998 EndArgs); 5999 AtomicRCG.setAction(Action); 6000 AtomicRCG(CGF); 6001 } else { 6002 AtomicRCG(CGF); 6003 } 6004 6005 CGF.EmitBranch(DefaultBB); 6006 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 6007 } 6008 6009 /// Generates unique name for artificial threadprivate variables. 6010 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 6011 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 6012 const Expr *Ref) { 6013 SmallString<256> Buffer; 6014 llvm::raw_svector_ostream Out(Buffer); 6015 const clang::DeclRefExpr *DE; 6016 const VarDecl *D = ::getBaseDecl(Ref, DE); 6017 if (!D) 6018 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 6019 D = D->getCanonicalDecl(); 6020 std::string Name = CGM.getOpenMPRuntime().getName( 6021 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 6022 Out << Prefix << Name << "_" 6023 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 6024 return Out.str(); 6025 } 6026 6027 /// Emits reduction initializer function: 6028 /// \code 6029 /// void @.red_init(void* %arg) { 6030 /// %0 = bitcast void* %arg to <type>* 6031 /// store <type> <init>, <type>* %0 6032 /// ret void 6033 /// } 6034 /// \endcode 6035 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6036 SourceLocation Loc, 6037 ReductionCodeGen &RCG, unsigned N) { 6038 ASTContext &C = CGM.getContext(); 6039 FunctionArgList Args; 6040 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6041 ImplicitParamDecl::Other); 6042 Args.emplace_back(&Param); 6043 const auto &FnInfo = 6044 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6045 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6046 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6047 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6048 Name, &CGM.getModule()); 6049 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6050 Fn->setDoesNotRecurse(); 6051 CodeGenFunction CGF(CGM); 6052 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6053 Address PrivateAddr = CGF.EmitLoadOfPointer( 6054 CGF.GetAddrOfLocalVar(&Param), 6055 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6056 llvm::Value *Size = nullptr; 6057 // If the size of the reduction item is non-constant, load it from global 6058 // threadprivate variable. 6059 if (RCG.getSizes(N).second) { 6060 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6061 CGF, CGM.getContext().getSizeType(), 6062 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6063 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6064 CGM.getContext().getSizeType(), Loc); 6065 } 6066 RCG.emitAggregateType(CGF, N, Size); 6067 LValue SharedLVal; 6068 // If initializer uses initializer from declare reduction construct, emit a 6069 // pointer to the address of the original reduction item (reuired by reduction 6070 // initializer) 6071 if (RCG.usesReductionInitializer(N)) { 6072 Address SharedAddr = 6073 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6074 CGF, CGM.getContext().VoidPtrTy, 6075 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6076 SharedAddr = CGF.EmitLoadOfPointer( 6077 SharedAddr, 6078 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6079 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6080 } else { 6081 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6082 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6083 CGM.getContext().VoidPtrTy); 6084 } 6085 // Emit the initializer: 6086 // %0 = bitcast void* %arg to <type>* 6087 // store <type> <init>, <type>* %0 6088 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6089 [](CodeGenFunction &) { return false; }); 6090 CGF.FinishFunction(); 6091 return Fn; 6092 } 6093 6094 /// Emits reduction combiner function: 6095 /// \code 6096 /// void @.red_comb(void* %arg0, void* %arg1) { 6097 /// %lhs = bitcast void* %arg0 to <type>* 6098 /// %rhs = bitcast void* %arg1 to <type>* 6099 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6100 /// store <type> %2, <type>* %lhs 6101 /// ret void 6102 /// } 6103 /// \endcode 6104 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6105 SourceLocation Loc, 6106 ReductionCodeGen &RCG, unsigned N, 6107 const Expr *ReductionOp, 6108 const Expr *LHS, const Expr *RHS, 6109 const Expr *PrivateRef) { 6110 ASTContext &C = CGM.getContext(); 6111 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6112 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6113 FunctionArgList Args; 6114 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6115 C.VoidPtrTy, ImplicitParamDecl::Other); 6116 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6117 ImplicitParamDecl::Other); 6118 Args.emplace_back(&ParamInOut); 6119 Args.emplace_back(&ParamIn); 6120 const auto &FnInfo = 6121 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6122 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6123 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6124 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6125 Name, &CGM.getModule()); 6126 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6127 Fn->setDoesNotRecurse(); 6128 CodeGenFunction CGF(CGM); 6129 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6130 llvm::Value *Size = nullptr; 6131 // If the size of the reduction item is non-constant, load it from global 6132 // threadprivate variable. 6133 if (RCG.getSizes(N).second) { 6134 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6135 CGF, CGM.getContext().getSizeType(), 6136 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6137 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6138 CGM.getContext().getSizeType(), Loc); 6139 } 6140 RCG.emitAggregateType(CGF, N, Size); 6141 // Remap lhs and rhs variables to the addresses of the function arguments. 6142 // %lhs = bitcast void* %arg0 to <type>* 6143 // %rhs = bitcast void* %arg1 to <type>* 6144 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6145 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6146 // Pull out the pointer to the variable. 6147 Address PtrAddr = CGF.EmitLoadOfPointer( 6148 CGF.GetAddrOfLocalVar(&ParamInOut), 6149 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6150 return CGF.Builder.CreateElementBitCast( 6151 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6152 }); 6153 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6154 // Pull out the pointer to the variable. 6155 Address PtrAddr = CGF.EmitLoadOfPointer( 6156 CGF.GetAddrOfLocalVar(&ParamIn), 6157 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6158 return CGF.Builder.CreateElementBitCast( 6159 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6160 }); 6161 PrivateScope.Privatize(); 6162 // Emit the combiner body: 6163 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6164 // store <type> %2, <type>* %lhs 6165 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6166 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6167 cast<DeclRefExpr>(RHS)); 6168 CGF.FinishFunction(); 6169 return Fn; 6170 } 6171 6172 /// Emits reduction finalizer function: 6173 /// \code 6174 /// void @.red_fini(void* %arg) { 6175 /// %0 = bitcast void* %arg to <type>* 6176 /// <destroy>(<type>* %0) 6177 /// ret void 6178 /// } 6179 /// \endcode 6180 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6181 SourceLocation Loc, 6182 ReductionCodeGen &RCG, unsigned N) { 6183 if (!RCG.needCleanups(N)) 6184 return nullptr; 6185 ASTContext &C = CGM.getContext(); 6186 FunctionArgList Args; 6187 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6188 ImplicitParamDecl::Other); 6189 Args.emplace_back(&Param); 6190 const auto &FnInfo = 6191 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6192 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6193 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6194 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6195 Name, &CGM.getModule()); 6196 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6197 Fn->setDoesNotRecurse(); 6198 CodeGenFunction CGF(CGM); 6199 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6200 Address PrivateAddr = CGF.EmitLoadOfPointer( 6201 CGF.GetAddrOfLocalVar(&Param), 6202 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6203 llvm::Value *Size = nullptr; 6204 // If the size of the reduction item is non-constant, load it from global 6205 // threadprivate variable. 6206 if (RCG.getSizes(N).second) { 6207 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6208 CGF, CGM.getContext().getSizeType(), 6209 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6210 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6211 CGM.getContext().getSizeType(), Loc); 6212 } 6213 RCG.emitAggregateType(CGF, N, Size); 6214 // Emit the finalizer body: 6215 // <destroy>(<type>* %0) 6216 RCG.emitCleanups(CGF, N, PrivateAddr); 6217 CGF.FinishFunction(Loc); 6218 return Fn; 6219 } 6220 6221 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6222 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6223 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6224 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6225 return nullptr; 6226 6227 // Build typedef struct: 6228 // kmp_task_red_input { 6229 // void *reduce_shar; // shared reduction item 6230 // size_t reduce_size; // size of data item 6231 // void *reduce_init; // data initialization routine 6232 // void *reduce_fini; // data finalization routine 6233 // void *reduce_comb; // data combiner routine 6234 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6235 // } kmp_task_red_input_t; 6236 ASTContext &C = CGM.getContext(); 6237 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6238 RD->startDefinition(); 6239 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6240 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6241 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6242 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6243 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6244 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6245 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6246 RD->completeDefinition(); 6247 QualType RDType = C.getRecordType(RD); 6248 unsigned Size = Data.ReductionVars.size(); 6249 llvm::APInt ArraySize(/*numBits=*/64, Size); 6250 QualType ArrayRDType = C.getConstantArrayType( 6251 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6252 // kmp_task_red_input_t .rd_input.[Size]; 6253 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6254 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6255 Data.ReductionOps); 6256 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6257 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6258 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6259 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6260 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6261 TaskRedInput.getPointer(), Idxs, 6262 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6263 ".rd_input.gep."); 6264 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6265 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6266 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6267 RCG.emitSharedLValue(CGF, Cnt); 6268 llvm::Value *CastedShared = 6269 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6270 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6271 RCG.emitAggregateType(CGF, Cnt); 6272 llvm::Value *SizeValInChars; 6273 llvm::Value *SizeVal; 6274 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6275 // We use delayed creation/initialization for VLAs, array sections and 6276 // custom reduction initializations. It is required because runtime does not 6277 // provide the way to pass the sizes of VLAs/array sections to 6278 // initializer/combiner/finalizer functions and does not pass the pointer to 6279 // original reduction item to the initializer. Instead threadprivate global 6280 // variables are used to store these values and use them in the functions. 6281 bool DelayedCreation = !!SizeVal; 6282 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6283 /*isSigned=*/false); 6284 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6285 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6286 // ElemLVal.reduce_init = init; 6287 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6288 llvm::Value *InitAddr = 6289 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6290 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6291 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6292 // ElemLVal.reduce_fini = fini; 6293 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6294 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6295 llvm::Value *FiniAddr = Fini 6296 ? CGF.EmitCastToVoidPtr(Fini) 6297 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6298 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6299 // ElemLVal.reduce_comb = comb; 6300 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6301 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6302 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6303 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6304 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6305 // ElemLVal.flags = 0; 6306 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6307 if (DelayedCreation) { 6308 CGF.EmitStoreOfScalar( 6309 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6310 FlagsLVal); 6311 } else 6312 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6313 FlagsLVal.getType()); 6314 } 6315 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6316 // *data); 6317 llvm::Value *Args[] = { 6318 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6319 /*isSigned=*/true), 6320 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6321 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6322 CGM.VoidPtrTy)}; 6323 return CGF.EmitRuntimeCall( 6324 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6325 } 6326 6327 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6328 SourceLocation Loc, 6329 ReductionCodeGen &RCG, 6330 unsigned N) { 6331 auto Sizes = RCG.getSizes(N); 6332 // Emit threadprivate global variable if the type is non-constant 6333 // (Sizes.second = nullptr). 6334 if (Sizes.second) { 6335 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6336 /*isSigned=*/false); 6337 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6338 CGF, CGM.getContext().getSizeType(), 6339 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6340 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6341 } 6342 // Store address of the original reduction item if custom initializer is used. 6343 if (RCG.usesReductionInitializer(N)) { 6344 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6345 CGF, CGM.getContext().VoidPtrTy, 6346 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6347 CGF.Builder.CreateStore( 6348 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6349 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy), 6350 SharedAddr, /*IsVolatile=*/false); 6351 } 6352 } 6353 6354 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6355 SourceLocation Loc, 6356 llvm::Value *ReductionsPtr, 6357 LValue SharedLVal) { 6358 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6359 // *d); 6360 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6361 CGM.IntTy, 6362 /*isSigned=*/true), 6363 ReductionsPtr, 6364 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6365 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6366 return Address( 6367 CGF.EmitRuntimeCall( 6368 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6369 SharedLVal.getAlignment()); 6370 } 6371 6372 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6373 SourceLocation Loc) { 6374 if (!CGF.HaveInsertPoint()) 6375 return; 6376 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6377 // global_tid); 6378 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6379 // Ignore return result until untied tasks are supported. 6380 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6381 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6382 Region->emitUntiedSwitch(CGF); 6383 } 6384 6385 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6386 OpenMPDirectiveKind InnerKind, 6387 const RegionCodeGenTy &CodeGen, 6388 bool HasCancel) { 6389 if (!CGF.HaveInsertPoint()) 6390 return; 6391 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6392 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6393 } 6394 6395 namespace { 6396 enum RTCancelKind { 6397 CancelNoreq = 0, 6398 CancelParallel = 1, 6399 CancelLoop = 2, 6400 CancelSections = 3, 6401 CancelTaskgroup = 4 6402 }; 6403 } // anonymous namespace 6404 6405 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6406 RTCancelKind CancelKind = CancelNoreq; 6407 if (CancelRegion == OMPD_parallel) 6408 CancelKind = CancelParallel; 6409 else if (CancelRegion == OMPD_for) 6410 CancelKind = CancelLoop; 6411 else if (CancelRegion == OMPD_sections) 6412 CancelKind = CancelSections; 6413 else { 6414 assert(CancelRegion == OMPD_taskgroup); 6415 CancelKind = CancelTaskgroup; 6416 } 6417 return CancelKind; 6418 } 6419 6420 void CGOpenMPRuntime::emitCancellationPointCall( 6421 CodeGenFunction &CGF, SourceLocation Loc, 6422 OpenMPDirectiveKind CancelRegion) { 6423 if (!CGF.HaveInsertPoint()) 6424 return; 6425 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6426 // global_tid, kmp_int32 cncl_kind); 6427 if (auto *OMPRegionInfo = 6428 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6429 // For 'cancellation point taskgroup', the task region info may not have a 6430 // cancel. This may instead happen in another adjacent task. 6431 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6432 llvm::Value *Args[] = { 6433 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6434 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6435 // Ignore return result until untied tasks are supported. 6436 llvm::Value *Result = CGF.EmitRuntimeCall( 6437 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6438 // if (__kmpc_cancellationpoint()) { 6439 // exit from construct; 6440 // } 6441 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6442 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6443 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6444 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6445 CGF.EmitBlock(ExitBB); 6446 // exit from construct; 6447 CodeGenFunction::JumpDest CancelDest = 6448 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6449 CGF.EmitBranchThroughCleanup(CancelDest); 6450 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6451 } 6452 } 6453 } 6454 6455 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6456 const Expr *IfCond, 6457 OpenMPDirectiveKind CancelRegion) { 6458 if (!CGF.HaveInsertPoint()) 6459 return; 6460 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6461 // kmp_int32 cncl_kind); 6462 if (auto *OMPRegionInfo = 6463 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6464 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6465 PrePostActionTy &) { 6466 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6467 llvm::Value *Args[] = { 6468 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6469 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6470 // Ignore return result until untied tasks are supported. 6471 llvm::Value *Result = CGF.EmitRuntimeCall( 6472 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6473 // if (__kmpc_cancel()) { 6474 // exit from construct; 6475 // } 6476 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6477 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6478 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6479 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6480 CGF.EmitBlock(ExitBB); 6481 // exit from construct; 6482 CodeGenFunction::JumpDest CancelDest = 6483 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6484 CGF.EmitBranchThroughCleanup(CancelDest); 6485 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6486 }; 6487 if (IfCond) { 6488 emitIfClause(CGF, IfCond, ThenGen, 6489 [](CodeGenFunction &, PrePostActionTy &) {}); 6490 } else { 6491 RegionCodeGenTy ThenRCG(ThenGen); 6492 ThenRCG(CGF); 6493 } 6494 } 6495 } 6496 6497 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6498 const OMPExecutableDirective &D, StringRef ParentName, 6499 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6500 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6501 assert(!ParentName.empty() && "Invalid target region parent name!"); 6502 HasEmittedTargetRegion = true; 6503 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6504 IsOffloadEntry, CodeGen); 6505 } 6506 6507 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6508 const OMPExecutableDirective &D, StringRef ParentName, 6509 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6510 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6511 // Create a unique name for the entry function using the source location 6512 // information of the current target region. The name will be something like: 6513 // 6514 // __omp_offloading_DD_FFFF_PP_lBB 6515 // 6516 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6517 // mangled name of the function that encloses the target region and BB is the 6518 // line number of the target region. 6519 6520 unsigned DeviceID; 6521 unsigned FileID; 6522 unsigned Line; 6523 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6524 Line); 6525 SmallString<64> EntryFnName; 6526 { 6527 llvm::raw_svector_ostream OS(EntryFnName); 6528 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6529 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6530 } 6531 6532 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6533 6534 CodeGenFunction CGF(CGM, true); 6535 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6536 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6537 6538 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 6539 6540 // If this target outline function is not an offload entry, we don't need to 6541 // register it. 6542 if (!IsOffloadEntry) 6543 return; 6544 6545 // The target region ID is used by the runtime library to identify the current 6546 // target region, so it only has to be unique and not necessarily point to 6547 // anything. It could be the pointer to the outlined function that implements 6548 // the target region, but we aren't using that so that the compiler doesn't 6549 // need to keep that, and could therefore inline the host function if proven 6550 // worthwhile during optimization. In the other hand, if emitting code for the 6551 // device, the ID has to be the function address so that it can retrieved from 6552 // the offloading entry and launched by the runtime library. We also mark the 6553 // outlined function to have external linkage in case we are emitting code for 6554 // the device, because these functions will be entry points to the device. 6555 6556 if (CGM.getLangOpts().OpenMPIsDevice) { 6557 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6558 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6559 OutlinedFn->setDSOLocal(false); 6560 } else { 6561 std::string Name = getName({EntryFnName, "region_id"}); 6562 OutlinedFnID = new llvm::GlobalVariable( 6563 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6564 llvm::GlobalValue::WeakAnyLinkage, 6565 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6566 } 6567 6568 // Register the information for the entry associated with this target region. 6569 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6570 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6571 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6572 } 6573 6574 /// Checks if the expression is constant or does not have non-trivial function 6575 /// calls. 6576 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6577 // We can skip constant expressions. 6578 // We can skip expressions with trivial calls or simple expressions. 6579 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6580 !E->hasNonTrivialCall(Ctx)) && 6581 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6582 } 6583 6584 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6585 const Stmt *Body) { 6586 const Stmt *Child = Body->IgnoreContainers(); 6587 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6588 Child = nullptr; 6589 for (const Stmt *S : C->body()) { 6590 if (const auto *E = dyn_cast<Expr>(S)) { 6591 if (isTrivial(Ctx, E)) 6592 continue; 6593 } 6594 // Some of the statements can be ignored. 6595 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6596 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6597 continue; 6598 // Analyze declarations. 6599 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6600 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6601 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6602 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6603 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6604 isa<UsingDirectiveDecl>(D) || 6605 isa<OMPDeclareReductionDecl>(D) || 6606 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6607 return true; 6608 const auto *VD = dyn_cast<VarDecl>(D); 6609 if (!VD) 6610 return false; 6611 return VD->isConstexpr() || 6612 ((VD->getType().isTrivialType(Ctx) || 6613 VD->getType()->isReferenceType()) && 6614 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6615 })) 6616 continue; 6617 } 6618 // Found multiple children - cannot get the one child only. 6619 if (Child) 6620 return nullptr; 6621 Child = S; 6622 } 6623 if (Child) 6624 Child = Child->IgnoreContainers(); 6625 } 6626 return Child; 6627 } 6628 6629 /// Emit the number of teams for a target directive. Inspect the num_teams 6630 /// clause associated with a teams construct combined or closely nested 6631 /// with the target directive. 6632 /// 6633 /// Emit a team of size one for directives such as 'target parallel' that 6634 /// have no associated teams construct. 6635 /// 6636 /// Otherwise, return nullptr. 6637 static llvm::Value * 6638 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6639 const OMPExecutableDirective &D) { 6640 assert(!CGF.getLangOpts().OpenMPIsDevice && 6641 "Clauses associated with the teams directive expected to be emitted " 6642 "only for the host!"); 6643 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6644 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6645 "Expected target-based executable directive."); 6646 CGBuilderTy &Bld = CGF.Builder; 6647 switch (DirectiveKind) { 6648 case OMPD_target: { 6649 const auto *CS = D.getInnermostCapturedStmt(); 6650 const auto *Body = 6651 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6652 const Stmt *ChildStmt = 6653 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6654 if (const auto *NestedDir = 6655 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6656 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6657 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6658 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6659 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6660 const Expr *NumTeams = 6661 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6662 llvm::Value *NumTeamsVal = 6663 CGF.EmitScalarExpr(NumTeams, 6664 /*IgnoreResultAssign*/ true); 6665 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6666 /*isSigned=*/true); 6667 } 6668 return Bld.getInt32(0); 6669 } 6670 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6671 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6672 return Bld.getInt32(1); 6673 return Bld.getInt32(0); 6674 } 6675 return nullptr; 6676 } 6677 case OMPD_target_teams: 6678 case OMPD_target_teams_distribute: 6679 case OMPD_target_teams_distribute_simd: 6680 case OMPD_target_teams_distribute_parallel_for: 6681 case OMPD_target_teams_distribute_parallel_for_simd: { 6682 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6683 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6684 const Expr *NumTeams = 6685 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6686 llvm::Value *NumTeamsVal = 6687 CGF.EmitScalarExpr(NumTeams, 6688 /*IgnoreResultAssign*/ true); 6689 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6690 /*isSigned=*/true); 6691 } 6692 return Bld.getInt32(0); 6693 } 6694 case OMPD_target_parallel: 6695 case OMPD_target_parallel_for: 6696 case OMPD_target_parallel_for_simd: 6697 case OMPD_target_simd: 6698 return Bld.getInt32(1); 6699 case OMPD_parallel: 6700 case OMPD_for: 6701 case OMPD_parallel_for: 6702 case OMPD_parallel_master: 6703 case OMPD_parallel_sections: 6704 case OMPD_for_simd: 6705 case OMPD_parallel_for_simd: 6706 case OMPD_cancel: 6707 case OMPD_cancellation_point: 6708 case OMPD_ordered: 6709 case OMPD_threadprivate: 6710 case OMPD_allocate: 6711 case OMPD_task: 6712 case OMPD_simd: 6713 case OMPD_sections: 6714 case OMPD_section: 6715 case OMPD_single: 6716 case OMPD_master: 6717 case OMPD_critical: 6718 case OMPD_taskyield: 6719 case OMPD_barrier: 6720 case OMPD_taskwait: 6721 case OMPD_taskgroup: 6722 case OMPD_atomic: 6723 case OMPD_flush: 6724 case OMPD_teams: 6725 case OMPD_target_data: 6726 case OMPD_target_exit_data: 6727 case OMPD_target_enter_data: 6728 case OMPD_distribute: 6729 case OMPD_distribute_simd: 6730 case OMPD_distribute_parallel_for: 6731 case OMPD_distribute_parallel_for_simd: 6732 case OMPD_teams_distribute: 6733 case OMPD_teams_distribute_simd: 6734 case OMPD_teams_distribute_parallel_for: 6735 case OMPD_teams_distribute_parallel_for_simd: 6736 case OMPD_target_update: 6737 case OMPD_declare_simd: 6738 case OMPD_declare_variant: 6739 case OMPD_declare_target: 6740 case OMPD_end_declare_target: 6741 case OMPD_declare_reduction: 6742 case OMPD_declare_mapper: 6743 case OMPD_taskloop: 6744 case OMPD_taskloop_simd: 6745 case OMPD_master_taskloop: 6746 case OMPD_master_taskloop_simd: 6747 case OMPD_parallel_master_taskloop: 6748 case OMPD_parallel_master_taskloop_simd: 6749 case OMPD_requires: 6750 case OMPD_unknown: 6751 break; 6752 } 6753 llvm_unreachable("Unexpected directive kind."); 6754 } 6755 6756 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6757 llvm::Value *DefaultThreadLimitVal) { 6758 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6759 CGF.getContext(), CS->getCapturedStmt()); 6760 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6761 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6762 llvm::Value *NumThreads = nullptr; 6763 llvm::Value *CondVal = nullptr; 6764 // Handle if clause. If if clause present, the number of threads is 6765 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6766 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6767 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6768 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6769 const OMPIfClause *IfClause = nullptr; 6770 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6771 if (C->getNameModifier() == OMPD_unknown || 6772 C->getNameModifier() == OMPD_parallel) { 6773 IfClause = C; 6774 break; 6775 } 6776 } 6777 if (IfClause) { 6778 const Expr *Cond = IfClause->getCondition(); 6779 bool Result; 6780 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6781 if (!Result) 6782 return CGF.Builder.getInt32(1); 6783 } else { 6784 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6785 if (const auto *PreInit = 6786 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6787 for (const auto *I : PreInit->decls()) { 6788 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6789 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6790 } else { 6791 CodeGenFunction::AutoVarEmission Emission = 6792 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6793 CGF.EmitAutoVarCleanups(Emission); 6794 } 6795 } 6796 } 6797 CondVal = CGF.EvaluateExprAsBool(Cond); 6798 } 6799 } 6800 } 6801 // Check the value of num_threads clause iff if clause was not specified 6802 // or is not evaluated to false. 6803 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6804 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6805 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6806 const auto *NumThreadsClause = 6807 Dir->getSingleClause<OMPNumThreadsClause>(); 6808 CodeGenFunction::LexicalScope Scope( 6809 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6810 if (const auto *PreInit = 6811 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6812 for (const auto *I : PreInit->decls()) { 6813 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6814 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6815 } else { 6816 CodeGenFunction::AutoVarEmission Emission = 6817 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6818 CGF.EmitAutoVarCleanups(Emission); 6819 } 6820 } 6821 } 6822 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6823 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6824 /*isSigned=*/false); 6825 if (DefaultThreadLimitVal) 6826 NumThreads = CGF.Builder.CreateSelect( 6827 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6828 DefaultThreadLimitVal, NumThreads); 6829 } else { 6830 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6831 : CGF.Builder.getInt32(0); 6832 } 6833 // Process condition of the if clause. 6834 if (CondVal) { 6835 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6836 CGF.Builder.getInt32(1)); 6837 } 6838 return NumThreads; 6839 } 6840 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6841 return CGF.Builder.getInt32(1); 6842 return DefaultThreadLimitVal; 6843 } 6844 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6845 : CGF.Builder.getInt32(0); 6846 } 6847 6848 /// Emit the number of threads for a target directive. Inspect the 6849 /// thread_limit clause associated with a teams construct combined or closely 6850 /// nested with the target directive. 6851 /// 6852 /// Emit the num_threads clause for directives such as 'target parallel' that 6853 /// have no associated teams construct. 6854 /// 6855 /// Otherwise, return nullptr. 6856 static llvm::Value * 6857 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6858 const OMPExecutableDirective &D) { 6859 assert(!CGF.getLangOpts().OpenMPIsDevice && 6860 "Clauses associated with the teams directive expected to be emitted " 6861 "only for the host!"); 6862 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6863 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6864 "Expected target-based executable directive."); 6865 CGBuilderTy &Bld = CGF.Builder; 6866 llvm::Value *ThreadLimitVal = nullptr; 6867 llvm::Value *NumThreadsVal = nullptr; 6868 switch (DirectiveKind) { 6869 case OMPD_target: { 6870 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6871 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6872 return NumThreads; 6873 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6874 CGF.getContext(), CS->getCapturedStmt()); 6875 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6876 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6877 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6878 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6879 const auto *ThreadLimitClause = 6880 Dir->getSingleClause<OMPThreadLimitClause>(); 6881 CodeGenFunction::LexicalScope Scope( 6882 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6883 if (const auto *PreInit = 6884 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6885 for (const auto *I : PreInit->decls()) { 6886 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6887 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6888 } else { 6889 CodeGenFunction::AutoVarEmission Emission = 6890 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6891 CGF.EmitAutoVarCleanups(Emission); 6892 } 6893 } 6894 } 6895 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6896 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6897 ThreadLimitVal = 6898 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6899 } 6900 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6901 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6902 CS = Dir->getInnermostCapturedStmt(); 6903 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6904 CGF.getContext(), CS->getCapturedStmt()); 6905 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6906 } 6907 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6908 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6909 CS = Dir->getInnermostCapturedStmt(); 6910 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6911 return NumThreads; 6912 } 6913 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6914 return Bld.getInt32(1); 6915 } 6916 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6917 } 6918 case OMPD_target_teams: { 6919 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6920 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6921 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6922 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6923 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6924 ThreadLimitVal = 6925 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6926 } 6927 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6928 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6929 return NumThreads; 6930 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6931 CGF.getContext(), CS->getCapturedStmt()); 6932 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6933 if (Dir->getDirectiveKind() == OMPD_distribute) { 6934 CS = Dir->getInnermostCapturedStmt(); 6935 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6936 return NumThreads; 6937 } 6938 } 6939 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6940 } 6941 case OMPD_target_teams_distribute: 6942 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6943 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6944 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6945 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6946 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6947 ThreadLimitVal = 6948 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6949 } 6950 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6951 case OMPD_target_parallel: 6952 case OMPD_target_parallel_for: 6953 case OMPD_target_parallel_for_simd: 6954 case OMPD_target_teams_distribute_parallel_for: 6955 case OMPD_target_teams_distribute_parallel_for_simd: { 6956 llvm::Value *CondVal = nullptr; 6957 // Handle if clause. If if clause present, the number of threads is 6958 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6959 if (D.hasClausesOfKind<OMPIfClause>()) { 6960 const OMPIfClause *IfClause = nullptr; 6961 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6962 if (C->getNameModifier() == OMPD_unknown || 6963 C->getNameModifier() == OMPD_parallel) { 6964 IfClause = C; 6965 break; 6966 } 6967 } 6968 if (IfClause) { 6969 const Expr *Cond = IfClause->getCondition(); 6970 bool Result; 6971 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6972 if (!Result) 6973 return Bld.getInt32(1); 6974 } else { 6975 CodeGenFunction::RunCleanupsScope Scope(CGF); 6976 CondVal = CGF.EvaluateExprAsBool(Cond); 6977 } 6978 } 6979 } 6980 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6981 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6982 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6983 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6984 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6985 ThreadLimitVal = 6986 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6987 } 6988 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6989 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6990 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6991 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6992 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6993 NumThreadsVal = 6994 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6995 ThreadLimitVal = ThreadLimitVal 6996 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6997 ThreadLimitVal), 6998 NumThreadsVal, ThreadLimitVal) 6999 : NumThreadsVal; 7000 } 7001 if (!ThreadLimitVal) 7002 ThreadLimitVal = Bld.getInt32(0); 7003 if (CondVal) 7004 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 7005 return ThreadLimitVal; 7006 } 7007 case OMPD_target_teams_distribute_simd: 7008 case OMPD_target_simd: 7009 return Bld.getInt32(1); 7010 case OMPD_parallel: 7011 case OMPD_for: 7012 case OMPD_parallel_for: 7013 case OMPD_parallel_master: 7014 case OMPD_parallel_sections: 7015 case OMPD_for_simd: 7016 case OMPD_parallel_for_simd: 7017 case OMPD_cancel: 7018 case OMPD_cancellation_point: 7019 case OMPD_ordered: 7020 case OMPD_threadprivate: 7021 case OMPD_allocate: 7022 case OMPD_task: 7023 case OMPD_simd: 7024 case OMPD_sections: 7025 case OMPD_section: 7026 case OMPD_single: 7027 case OMPD_master: 7028 case OMPD_critical: 7029 case OMPD_taskyield: 7030 case OMPD_barrier: 7031 case OMPD_taskwait: 7032 case OMPD_taskgroup: 7033 case OMPD_atomic: 7034 case OMPD_flush: 7035 case OMPD_teams: 7036 case OMPD_target_data: 7037 case OMPD_target_exit_data: 7038 case OMPD_target_enter_data: 7039 case OMPD_distribute: 7040 case OMPD_distribute_simd: 7041 case OMPD_distribute_parallel_for: 7042 case OMPD_distribute_parallel_for_simd: 7043 case OMPD_teams_distribute: 7044 case OMPD_teams_distribute_simd: 7045 case OMPD_teams_distribute_parallel_for: 7046 case OMPD_teams_distribute_parallel_for_simd: 7047 case OMPD_target_update: 7048 case OMPD_declare_simd: 7049 case OMPD_declare_variant: 7050 case OMPD_declare_target: 7051 case OMPD_end_declare_target: 7052 case OMPD_declare_reduction: 7053 case OMPD_declare_mapper: 7054 case OMPD_taskloop: 7055 case OMPD_taskloop_simd: 7056 case OMPD_master_taskloop: 7057 case OMPD_master_taskloop_simd: 7058 case OMPD_parallel_master_taskloop: 7059 case OMPD_parallel_master_taskloop_simd: 7060 case OMPD_requires: 7061 case OMPD_unknown: 7062 break; 7063 } 7064 llvm_unreachable("Unsupported directive kind."); 7065 } 7066 7067 namespace { 7068 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7069 7070 // Utility to handle information from clauses associated with a given 7071 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7072 // It provides a convenient interface to obtain the information and generate 7073 // code for that information. 7074 class MappableExprsHandler { 7075 public: 7076 /// Values for bit flags used to specify the mapping type for 7077 /// offloading. 7078 enum OpenMPOffloadMappingFlags : uint64_t { 7079 /// No flags 7080 OMP_MAP_NONE = 0x0, 7081 /// Allocate memory on the device and move data from host to device. 7082 OMP_MAP_TO = 0x01, 7083 /// Allocate memory on the device and move data from device to host. 7084 OMP_MAP_FROM = 0x02, 7085 /// Always perform the requested mapping action on the element, even 7086 /// if it was already mapped before. 7087 OMP_MAP_ALWAYS = 0x04, 7088 /// Delete the element from the device environment, ignoring the 7089 /// current reference count associated with the element. 7090 OMP_MAP_DELETE = 0x08, 7091 /// The element being mapped is a pointer-pointee pair; both the 7092 /// pointer and the pointee should be mapped. 7093 OMP_MAP_PTR_AND_OBJ = 0x10, 7094 /// This flags signals that the base address of an entry should be 7095 /// passed to the target kernel as an argument. 7096 OMP_MAP_TARGET_PARAM = 0x20, 7097 /// Signal that the runtime library has to return the device pointer 7098 /// in the current position for the data being mapped. Used when we have the 7099 /// use_device_ptr clause. 7100 OMP_MAP_RETURN_PARAM = 0x40, 7101 /// This flag signals that the reference being passed is a pointer to 7102 /// private data. 7103 OMP_MAP_PRIVATE = 0x80, 7104 /// Pass the element to the device by value. 7105 OMP_MAP_LITERAL = 0x100, 7106 /// Implicit map 7107 OMP_MAP_IMPLICIT = 0x200, 7108 /// Close is a hint to the runtime to allocate memory close to 7109 /// the target device. 7110 OMP_MAP_CLOSE = 0x400, 7111 /// The 16 MSBs of the flags indicate whether the entry is member of some 7112 /// struct/class. 7113 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7114 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7115 }; 7116 7117 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7118 static unsigned getFlagMemberOffset() { 7119 unsigned Offset = 0; 7120 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7121 Remain = Remain >> 1) 7122 Offset++; 7123 return Offset; 7124 } 7125 7126 /// Class that associates information with a base pointer to be passed to the 7127 /// runtime library. 7128 class BasePointerInfo { 7129 /// The base pointer. 7130 llvm::Value *Ptr = nullptr; 7131 /// The base declaration that refers to this device pointer, or null if 7132 /// there is none. 7133 const ValueDecl *DevPtrDecl = nullptr; 7134 7135 public: 7136 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7137 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7138 llvm::Value *operator*() const { return Ptr; } 7139 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7140 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7141 }; 7142 7143 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7144 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7145 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7146 7147 /// Map between a struct and the its lowest & highest elements which have been 7148 /// mapped. 7149 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7150 /// HE(FieldIndex, Pointer)} 7151 struct StructRangeInfoTy { 7152 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7153 0, Address::invalid()}; 7154 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7155 0, Address::invalid()}; 7156 Address Base = Address::invalid(); 7157 }; 7158 7159 private: 7160 /// Kind that defines how a device pointer has to be returned. 7161 struct MapInfo { 7162 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7163 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7164 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7165 bool ReturnDevicePointer = false; 7166 bool IsImplicit = false; 7167 7168 MapInfo() = default; 7169 MapInfo( 7170 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7171 OpenMPMapClauseKind MapType, 7172 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7173 bool ReturnDevicePointer, bool IsImplicit) 7174 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7175 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7176 }; 7177 7178 /// If use_device_ptr is used on a pointer which is a struct member and there 7179 /// is no map information about it, then emission of that entry is deferred 7180 /// until the whole struct has been processed. 7181 struct DeferredDevicePtrEntryTy { 7182 const Expr *IE = nullptr; 7183 const ValueDecl *VD = nullptr; 7184 7185 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7186 : IE(IE), VD(VD) {} 7187 }; 7188 7189 /// The target directive from where the mappable clauses were extracted. It 7190 /// is either a executable directive or a user-defined mapper directive. 7191 llvm::PointerUnion<const OMPExecutableDirective *, 7192 const OMPDeclareMapperDecl *> 7193 CurDir; 7194 7195 /// Function the directive is being generated for. 7196 CodeGenFunction &CGF; 7197 7198 /// Set of all first private variables in the current directive. 7199 /// bool data is set to true if the variable is implicitly marked as 7200 /// firstprivate, false otherwise. 7201 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7202 7203 /// Map between device pointer declarations and their expression components. 7204 /// The key value for declarations in 'this' is null. 7205 llvm::DenseMap< 7206 const ValueDecl *, 7207 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7208 DevPointersMap; 7209 7210 llvm::Value *getExprTypeSize(const Expr *E) const { 7211 QualType ExprTy = E->getType().getCanonicalType(); 7212 7213 // Reference types are ignored for mapping purposes. 7214 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7215 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7216 7217 // Given that an array section is considered a built-in type, we need to 7218 // do the calculation based on the length of the section instead of relying 7219 // on CGF.getTypeSize(E->getType()). 7220 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7221 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7222 OAE->getBase()->IgnoreParenImpCasts()) 7223 .getCanonicalType(); 7224 7225 // If there is no length associated with the expression and lower bound is 7226 // not specified too, that means we are using the whole length of the 7227 // base. 7228 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7229 !OAE->getLowerBound()) 7230 return CGF.getTypeSize(BaseTy); 7231 7232 llvm::Value *ElemSize; 7233 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7234 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7235 } else { 7236 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7237 assert(ATy && "Expecting array type if not a pointer type."); 7238 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7239 } 7240 7241 // If we don't have a length at this point, that is because we have an 7242 // array section with a single element. 7243 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7244 return ElemSize; 7245 7246 if (const Expr *LenExpr = OAE->getLength()) { 7247 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7248 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7249 CGF.getContext().getSizeType(), 7250 LenExpr->getExprLoc()); 7251 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7252 } 7253 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7254 OAE->getLowerBound() && "expected array_section[lb:]."); 7255 // Size = sizetype - lb * elemtype; 7256 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7257 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7258 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7259 CGF.getContext().getSizeType(), 7260 OAE->getLowerBound()->getExprLoc()); 7261 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7262 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7263 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7264 LengthVal = CGF.Builder.CreateSelect( 7265 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7266 return LengthVal; 7267 } 7268 return CGF.getTypeSize(ExprTy); 7269 } 7270 7271 /// Return the corresponding bits for a given map clause modifier. Add 7272 /// a flag marking the map as a pointer if requested. Add a flag marking the 7273 /// map as the first one of a series of maps that relate to the same map 7274 /// expression. 7275 OpenMPOffloadMappingFlags getMapTypeBits( 7276 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7277 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7278 OpenMPOffloadMappingFlags Bits = 7279 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7280 switch (MapType) { 7281 case OMPC_MAP_alloc: 7282 case OMPC_MAP_release: 7283 // alloc and release is the default behavior in the runtime library, i.e. 7284 // if we don't pass any bits alloc/release that is what the runtime is 7285 // going to do. Therefore, we don't need to signal anything for these two 7286 // type modifiers. 7287 break; 7288 case OMPC_MAP_to: 7289 Bits |= OMP_MAP_TO; 7290 break; 7291 case OMPC_MAP_from: 7292 Bits |= OMP_MAP_FROM; 7293 break; 7294 case OMPC_MAP_tofrom: 7295 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7296 break; 7297 case OMPC_MAP_delete: 7298 Bits |= OMP_MAP_DELETE; 7299 break; 7300 case OMPC_MAP_unknown: 7301 llvm_unreachable("Unexpected map type!"); 7302 } 7303 if (AddPtrFlag) 7304 Bits |= OMP_MAP_PTR_AND_OBJ; 7305 if (AddIsTargetParamFlag) 7306 Bits |= OMP_MAP_TARGET_PARAM; 7307 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7308 != MapModifiers.end()) 7309 Bits |= OMP_MAP_ALWAYS; 7310 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7311 != MapModifiers.end()) 7312 Bits |= OMP_MAP_CLOSE; 7313 return Bits; 7314 } 7315 7316 /// Return true if the provided expression is a final array section. A 7317 /// final array section, is one whose length can't be proved to be one. 7318 bool isFinalArraySectionExpression(const Expr *E) const { 7319 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7320 7321 // It is not an array section and therefore not a unity-size one. 7322 if (!OASE) 7323 return false; 7324 7325 // An array section with no colon always refer to a single element. 7326 if (OASE->getColonLoc().isInvalid()) 7327 return false; 7328 7329 const Expr *Length = OASE->getLength(); 7330 7331 // If we don't have a length we have to check if the array has size 1 7332 // for this dimension. Also, we should always expect a length if the 7333 // base type is pointer. 7334 if (!Length) { 7335 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7336 OASE->getBase()->IgnoreParenImpCasts()) 7337 .getCanonicalType(); 7338 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7339 return ATy->getSize().getSExtValue() != 1; 7340 // If we don't have a constant dimension length, we have to consider 7341 // the current section as having any size, so it is not necessarily 7342 // unitary. If it happen to be unity size, that's user fault. 7343 return true; 7344 } 7345 7346 // Check if the length evaluates to 1. 7347 Expr::EvalResult Result; 7348 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7349 return true; // Can have more that size 1. 7350 7351 llvm::APSInt ConstLength = Result.Val.getInt(); 7352 return ConstLength.getSExtValue() != 1; 7353 } 7354 7355 /// Generate the base pointers, section pointers, sizes and map type 7356 /// bits for the provided map type, map modifier, and expression components. 7357 /// \a IsFirstComponent should be set to true if the provided set of 7358 /// components is the first associated with a capture. 7359 void generateInfoForComponentList( 7360 OpenMPMapClauseKind MapType, 7361 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7362 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7363 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7364 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7365 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7366 bool IsImplicit, 7367 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7368 OverlappedElements = llvm::None) const { 7369 // The following summarizes what has to be generated for each map and the 7370 // types below. The generated information is expressed in this order: 7371 // base pointer, section pointer, size, flags 7372 // (to add to the ones that come from the map type and modifier). 7373 // 7374 // double d; 7375 // int i[100]; 7376 // float *p; 7377 // 7378 // struct S1 { 7379 // int i; 7380 // float f[50]; 7381 // } 7382 // struct S2 { 7383 // int i; 7384 // float f[50]; 7385 // S1 s; 7386 // double *p; 7387 // struct S2 *ps; 7388 // } 7389 // S2 s; 7390 // S2 *ps; 7391 // 7392 // map(d) 7393 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7394 // 7395 // map(i) 7396 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7397 // 7398 // map(i[1:23]) 7399 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7400 // 7401 // map(p) 7402 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7403 // 7404 // map(p[1:24]) 7405 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7406 // 7407 // map(s) 7408 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7409 // 7410 // map(s.i) 7411 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7412 // 7413 // map(s.s.f) 7414 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7415 // 7416 // map(s.p) 7417 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7418 // 7419 // map(to: s.p[:22]) 7420 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7421 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7422 // &(s.p), &(s.p[0]), 22*sizeof(double), 7423 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7424 // (*) alloc space for struct members, only this is a target parameter 7425 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7426 // optimizes this entry out, same in the examples below) 7427 // (***) map the pointee (map: to) 7428 // 7429 // map(s.ps) 7430 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7431 // 7432 // map(from: s.ps->s.i) 7433 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7434 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7435 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7436 // 7437 // map(to: s.ps->ps) 7438 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7439 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7440 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7441 // 7442 // map(s.ps->ps->ps) 7443 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7444 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7445 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7446 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7447 // 7448 // map(to: s.ps->ps->s.f[:22]) 7449 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7450 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7451 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7452 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7453 // 7454 // map(ps) 7455 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7456 // 7457 // map(ps->i) 7458 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7459 // 7460 // map(ps->s.f) 7461 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7462 // 7463 // map(from: ps->p) 7464 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7465 // 7466 // map(to: ps->p[:22]) 7467 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7468 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7469 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7470 // 7471 // map(ps->ps) 7472 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7473 // 7474 // map(from: ps->ps->s.i) 7475 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7476 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7477 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7478 // 7479 // map(from: ps->ps->ps) 7480 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7481 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7482 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7483 // 7484 // map(ps->ps->ps->ps) 7485 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7486 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7487 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7488 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7489 // 7490 // map(to: ps->ps->ps->s.f[:22]) 7491 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7492 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7493 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7494 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7495 // 7496 // map(to: s.f[:22]) map(from: s.p[:33]) 7497 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7498 // sizeof(double*) (**), TARGET_PARAM 7499 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7500 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7501 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7502 // (*) allocate contiguous space needed to fit all mapped members even if 7503 // we allocate space for members not mapped (in this example, 7504 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7505 // them as well because they fall between &s.f[0] and &s.p) 7506 // 7507 // map(from: s.f[:22]) map(to: ps->p[:33]) 7508 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7509 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7510 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7511 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7512 // (*) the struct this entry pertains to is the 2nd element in the list of 7513 // arguments, hence MEMBER_OF(2) 7514 // 7515 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7516 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7517 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7518 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7519 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7520 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7521 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7522 // (*) the struct this entry pertains to is the 4th element in the list 7523 // of arguments, hence MEMBER_OF(4) 7524 7525 // Track if the map information being generated is the first for a capture. 7526 bool IsCaptureFirstInfo = IsFirstComponentList; 7527 // When the variable is on a declare target link or in a to clause with 7528 // unified memory, a reference is needed to hold the host/device address 7529 // of the variable. 7530 bool RequiresReference = false; 7531 7532 // Scan the components from the base to the complete expression. 7533 auto CI = Components.rbegin(); 7534 auto CE = Components.rend(); 7535 auto I = CI; 7536 7537 // Track if the map information being generated is the first for a list of 7538 // components. 7539 bool IsExpressionFirstInfo = true; 7540 Address BP = Address::invalid(); 7541 const Expr *AssocExpr = I->getAssociatedExpression(); 7542 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7543 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7544 7545 if (isa<MemberExpr>(AssocExpr)) { 7546 // The base is the 'this' pointer. The content of the pointer is going 7547 // to be the base of the field being mapped. 7548 BP = CGF.LoadCXXThisAddress(); 7549 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7550 (OASE && 7551 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7552 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7553 } else { 7554 // The base is the reference to the variable. 7555 // BP = &Var. 7556 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7557 if (const auto *VD = 7558 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7559 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7560 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7561 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7562 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7563 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7564 RequiresReference = true; 7565 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7566 } 7567 } 7568 } 7569 7570 // If the variable is a pointer and is being dereferenced (i.e. is not 7571 // the last component), the base has to be the pointer itself, not its 7572 // reference. References are ignored for mapping purposes. 7573 QualType Ty = 7574 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7575 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7576 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7577 7578 // We do not need to generate individual map information for the 7579 // pointer, it can be associated with the combined storage. 7580 ++I; 7581 } 7582 } 7583 7584 // Track whether a component of the list should be marked as MEMBER_OF some 7585 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7586 // in a component list should be marked as MEMBER_OF, all subsequent entries 7587 // do not belong to the base struct. E.g. 7588 // struct S2 s; 7589 // s.ps->ps->ps->f[:] 7590 // (1) (2) (3) (4) 7591 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7592 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7593 // is the pointee of ps(2) which is not member of struct s, so it should not 7594 // be marked as such (it is still PTR_AND_OBJ). 7595 // The variable is initialized to false so that PTR_AND_OBJ entries which 7596 // are not struct members are not considered (e.g. array of pointers to 7597 // data). 7598 bool ShouldBeMemberOf = false; 7599 7600 // Variable keeping track of whether or not we have encountered a component 7601 // in the component list which is a member expression. Useful when we have a 7602 // pointer or a final array section, in which case it is the previous 7603 // component in the list which tells us whether we have a member expression. 7604 // E.g. X.f[:] 7605 // While processing the final array section "[:]" it is "f" which tells us 7606 // whether we are dealing with a member of a declared struct. 7607 const MemberExpr *EncounteredME = nullptr; 7608 7609 for (; I != CE; ++I) { 7610 // If the current component is member of a struct (parent struct) mark it. 7611 if (!EncounteredME) { 7612 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7613 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7614 // as MEMBER_OF the parent struct. 7615 if (EncounteredME) 7616 ShouldBeMemberOf = true; 7617 } 7618 7619 auto Next = std::next(I); 7620 7621 // We need to generate the addresses and sizes if this is the last 7622 // component, if the component is a pointer or if it is an array section 7623 // whose length can't be proved to be one. If this is a pointer, it 7624 // becomes the base address for the following components. 7625 7626 // A final array section, is one whose length can't be proved to be one. 7627 bool IsFinalArraySection = 7628 isFinalArraySectionExpression(I->getAssociatedExpression()); 7629 7630 // Get information on whether the element is a pointer. Have to do a 7631 // special treatment for array sections given that they are built-in 7632 // types. 7633 const auto *OASE = 7634 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7635 bool IsPointer = 7636 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7637 .getCanonicalType() 7638 ->isAnyPointerType()) || 7639 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7640 7641 if (Next == CE || IsPointer || IsFinalArraySection) { 7642 // If this is not the last component, we expect the pointer to be 7643 // associated with an array expression or member expression. 7644 assert((Next == CE || 7645 isa<MemberExpr>(Next->getAssociatedExpression()) || 7646 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7647 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 7648 "Unexpected expression"); 7649 7650 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7651 .getAddress(CGF); 7652 7653 // If this component is a pointer inside the base struct then we don't 7654 // need to create any entry for it - it will be combined with the object 7655 // it is pointing to into a single PTR_AND_OBJ entry. 7656 bool IsMemberPointer = 7657 IsPointer && EncounteredME && 7658 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7659 EncounteredME); 7660 if (!OverlappedElements.empty()) { 7661 // Handle base element with the info for overlapped elements. 7662 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7663 assert(Next == CE && 7664 "Expected last element for the overlapped elements."); 7665 assert(!IsPointer && 7666 "Unexpected base element with the pointer type."); 7667 // Mark the whole struct as the struct that requires allocation on the 7668 // device. 7669 PartialStruct.LowestElem = {0, LB}; 7670 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7671 I->getAssociatedExpression()->getType()); 7672 Address HB = CGF.Builder.CreateConstGEP( 7673 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7674 CGF.VoidPtrTy), 7675 TypeSize.getQuantity() - 1); 7676 PartialStruct.HighestElem = { 7677 std::numeric_limits<decltype( 7678 PartialStruct.HighestElem.first)>::max(), 7679 HB}; 7680 PartialStruct.Base = BP; 7681 // Emit data for non-overlapped data. 7682 OpenMPOffloadMappingFlags Flags = 7683 OMP_MAP_MEMBER_OF | 7684 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7685 /*AddPtrFlag=*/false, 7686 /*AddIsTargetParamFlag=*/false); 7687 LB = BP; 7688 llvm::Value *Size = nullptr; 7689 // Do bitcopy of all non-overlapped structure elements. 7690 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7691 Component : OverlappedElements) { 7692 Address ComponentLB = Address::invalid(); 7693 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7694 Component) { 7695 if (MC.getAssociatedDeclaration()) { 7696 ComponentLB = 7697 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7698 .getAddress(CGF); 7699 Size = CGF.Builder.CreatePtrDiff( 7700 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7701 CGF.EmitCastToVoidPtr(LB.getPointer())); 7702 break; 7703 } 7704 } 7705 BasePointers.push_back(BP.getPointer()); 7706 Pointers.push_back(LB.getPointer()); 7707 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7708 /*isSigned=*/true)); 7709 Types.push_back(Flags); 7710 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7711 } 7712 BasePointers.push_back(BP.getPointer()); 7713 Pointers.push_back(LB.getPointer()); 7714 Size = CGF.Builder.CreatePtrDiff( 7715 CGF.EmitCastToVoidPtr( 7716 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7717 CGF.EmitCastToVoidPtr(LB.getPointer())); 7718 Sizes.push_back( 7719 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7720 Types.push_back(Flags); 7721 break; 7722 } 7723 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7724 if (!IsMemberPointer) { 7725 BasePointers.push_back(BP.getPointer()); 7726 Pointers.push_back(LB.getPointer()); 7727 Sizes.push_back( 7728 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7729 7730 // We need to add a pointer flag for each map that comes from the 7731 // same expression except for the first one. We also need to signal 7732 // this map is the first one that relates with the current capture 7733 // (there is a set of entries for each capture). 7734 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7735 MapType, MapModifiers, IsImplicit, 7736 !IsExpressionFirstInfo || RequiresReference, 7737 IsCaptureFirstInfo && !RequiresReference); 7738 7739 if (!IsExpressionFirstInfo) { 7740 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7741 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7742 if (IsPointer) 7743 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7744 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7745 7746 if (ShouldBeMemberOf) { 7747 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7748 // should be later updated with the correct value of MEMBER_OF. 7749 Flags |= OMP_MAP_MEMBER_OF; 7750 // From now on, all subsequent PTR_AND_OBJ entries should not be 7751 // marked as MEMBER_OF. 7752 ShouldBeMemberOf = false; 7753 } 7754 } 7755 7756 Types.push_back(Flags); 7757 } 7758 7759 // If we have encountered a member expression so far, keep track of the 7760 // mapped member. If the parent is "*this", then the value declaration 7761 // is nullptr. 7762 if (EncounteredME) { 7763 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); 7764 unsigned FieldIndex = FD->getFieldIndex(); 7765 7766 // Update info about the lowest and highest elements for this struct 7767 if (!PartialStruct.Base.isValid()) { 7768 PartialStruct.LowestElem = {FieldIndex, LB}; 7769 PartialStruct.HighestElem = {FieldIndex, LB}; 7770 PartialStruct.Base = BP; 7771 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7772 PartialStruct.LowestElem = {FieldIndex, LB}; 7773 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7774 PartialStruct.HighestElem = {FieldIndex, LB}; 7775 } 7776 } 7777 7778 // If we have a final array section, we are done with this expression. 7779 if (IsFinalArraySection) 7780 break; 7781 7782 // The pointer becomes the base for the next element. 7783 if (Next != CE) 7784 BP = LB; 7785 7786 IsExpressionFirstInfo = false; 7787 IsCaptureFirstInfo = false; 7788 } 7789 } 7790 } 7791 7792 /// Return the adjusted map modifiers if the declaration a capture refers to 7793 /// appears in a first-private clause. This is expected to be used only with 7794 /// directives that start with 'target'. 7795 MappableExprsHandler::OpenMPOffloadMappingFlags 7796 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7797 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7798 7799 // A first private variable captured by reference will use only the 7800 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7801 // declaration is known as first-private in this handler. 7802 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7803 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7804 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7805 return MappableExprsHandler::OMP_MAP_ALWAYS | 7806 MappableExprsHandler::OMP_MAP_TO; 7807 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7808 return MappableExprsHandler::OMP_MAP_TO | 7809 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7810 return MappableExprsHandler::OMP_MAP_PRIVATE | 7811 MappableExprsHandler::OMP_MAP_TO; 7812 } 7813 return MappableExprsHandler::OMP_MAP_TO | 7814 MappableExprsHandler::OMP_MAP_FROM; 7815 } 7816 7817 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7818 // Rotate by getFlagMemberOffset() bits. 7819 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7820 << getFlagMemberOffset()); 7821 } 7822 7823 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7824 OpenMPOffloadMappingFlags MemberOfFlag) { 7825 // If the entry is PTR_AND_OBJ but has not been marked with the special 7826 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7827 // marked as MEMBER_OF. 7828 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7829 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7830 return; 7831 7832 // Reset the placeholder value to prepare the flag for the assignment of the 7833 // proper MEMBER_OF value. 7834 Flags &= ~OMP_MAP_MEMBER_OF; 7835 Flags |= MemberOfFlag; 7836 } 7837 7838 void getPlainLayout(const CXXRecordDecl *RD, 7839 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7840 bool AsBase) const { 7841 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7842 7843 llvm::StructType *St = 7844 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7845 7846 unsigned NumElements = St->getNumElements(); 7847 llvm::SmallVector< 7848 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7849 RecordLayout(NumElements); 7850 7851 // Fill bases. 7852 for (const auto &I : RD->bases()) { 7853 if (I.isVirtual()) 7854 continue; 7855 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7856 // Ignore empty bases. 7857 if (Base->isEmpty() || CGF.getContext() 7858 .getASTRecordLayout(Base) 7859 .getNonVirtualSize() 7860 .isZero()) 7861 continue; 7862 7863 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7864 RecordLayout[FieldIndex] = Base; 7865 } 7866 // Fill in virtual bases. 7867 for (const auto &I : RD->vbases()) { 7868 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7869 // Ignore empty bases. 7870 if (Base->isEmpty()) 7871 continue; 7872 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7873 if (RecordLayout[FieldIndex]) 7874 continue; 7875 RecordLayout[FieldIndex] = Base; 7876 } 7877 // Fill in all the fields. 7878 assert(!RD->isUnion() && "Unexpected union."); 7879 for (const auto *Field : RD->fields()) { 7880 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7881 // will fill in later.) 7882 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7883 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7884 RecordLayout[FieldIndex] = Field; 7885 } 7886 } 7887 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7888 &Data : RecordLayout) { 7889 if (Data.isNull()) 7890 continue; 7891 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7892 getPlainLayout(Base, Layout, /*AsBase=*/true); 7893 else 7894 Layout.push_back(Data.get<const FieldDecl *>()); 7895 } 7896 } 7897 7898 public: 7899 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7900 : CurDir(&Dir), CGF(CGF) { 7901 // Extract firstprivate clause information. 7902 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7903 for (const auto *D : C->varlists()) 7904 FirstPrivateDecls.try_emplace( 7905 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 7906 // Extract device pointer clause information. 7907 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7908 for (auto L : C->component_lists()) 7909 DevPointersMap[L.first].push_back(L.second); 7910 } 7911 7912 /// Constructor for the declare mapper directive. 7913 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 7914 : CurDir(&Dir), CGF(CGF) {} 7915 7916 /// Generate code for the combined entry if we have a partially mapped struct 7917 /// and take care of the mapping flags of the arguments corresponding to 7918 /// individual struct members. 7919 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 7920 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7921 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 7922 const StructRangeInfoTy &PartialStruct) const { 7923 // Base is the base of the struct 7924 BasePointers.push_back(PartialStruct.Base.getPointer()); 7925 // Pointer is the address of the lowest element 7926 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7927 Pointers.push_back(LB); 7928 // Size is (addr of {highest+1} element) - (addr of lowest element) 7929 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7930 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7931 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7932 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7933 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7934 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 7935 /*isSigned=*/false); 7936 Sizes.push_back(Size); 7937 // Map type is always TARGET_PARAM 7938 Types.push_back(OMP_MAP_TARGET_PARAM); 7939 // Remove TARGET_PARAM flag from the first element 7940 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7941 7942 // All other current entries will be MEMBER_OF the combined entry 7943 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7944 // 0xFFFF in the MEMBER_OF field). 7945 OpenMPOffloadMappingFlags MemberOfFlag = 7946 getMemberOfFlag(BasePointers.size() - 1); 7947 for (auto &M : CurTypes) 7948 setCorrectMemberOfFlag(M, MemberOfFlag); 7949 } 7950 7951 /// Generate all the base pointers, section pointers, sizes and map 7952 /// types for the extracted mappable expressions. Also, for each item that 7953 /// relates with a device pointer, a pair of the relevant declaration and 7954 /// index where it occurs is appended to the device pointers info array. 7955 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 7956 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7957 MapFlagsArrayTy &Types) const { 7958 // We have to process the component lists that relate with the same 7959 // declaration in a single chunk so that we can generate the map flags 7960 // correctly. Therefore, we organize all lists in a map. 7961 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7962 7963 // Helper function to fill the information map for the different supported 7964 // clauses. 7965 auto &&InfoGen = [&Info]( 7966 const ValueDecl *D, 7967 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7968 OpenMPMapClauseKind MapType, 7969 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7970 bool ReturnDevicePointer, bool IsImplicit) { 7971 const ValueDecl *VD = 7972 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7973 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7974 IsImplicit); 7975 }; 7976 7977 assert(CurDir.is<const OMPExecutableDirective *>() && 7978 "Expect a executable directive"); 7979 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 7980 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 7981 for (const auto L : C->component_lists()) { 7982 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 7983 /*ReturnDevicePointer=*/false, C->isImplicit()); 7984 } 7985 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 7986 for (const auto L : C->component_lists()) { 7987 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 7988 /*ReturnDevicePointer=*/false, C->isImplicit()); 7989 } 7990 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 7991 for (const auto L : C->component_lists()) { 7992 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 7993 /*ReturnDevicePointer=*/false, C->isImplicit()); 7994 } 7995 7996 // Look at the use_device_ptr clause information and mark the existing map 7997 // entries as such. If there is no map information for an entry in the 7998 // use_device_ptr list, we create one with map type 'alloc' and zero size 7999 // section. It is the user fault if that was not mapped before. If there is 8000 // no map information and the pointer is a struct member, then we defer the 8001 // emission of that entry until the whole struct has been processed. 8002 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 8003 DeferredInfo; 8004 8005 for (const auto *C : 8006 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 8007 for (const auto L : C->component_lists()) { 8008 assert(!L.second.empty() && "Not expecting empty list of components!"); 8009 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 8010 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 8011 const Expr *IE = L.second.back().getAssociatedExpression(); 8012 // If the first component is a member expression, we have to look into 8013 // 'this', which maps to null in the map of map information. Otherwise 8014 // look directly for the information. 8015 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 8016 8017 // We potentially have map information for this declaration already. 8018 // Look for the first set of components that refer to it. 8019 if (It != Info.end()) { 8020 auto CI = std::find_if( 8021 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 8022 return MI.Components.back().getAssociatedDeclaration() == VD; 8023 }); 8024 // If we found a map entry, signal that the pointer has to be returned 8025 // and move on to the next declaration. 8026 if (CI != It->second.end()) { 8027 CI->ReturnDevicePointer = true; 8028 continue; 8029 } 8030 } 8031 8032 // We didn't find any match in our map information - generate a zero 8033 // size array section - if the pointer is a struct member we defer this 8034 // action until the whole struct has been processed. 8035 if (isa<MemberExpr>(IE)) { 8036 // Insert the pointer into Info to be processed by 8037 // generateInfoForComponentList. Because it is a member pointer 8038 // without a pointee, no entry will be generated for it, therefore 8039 // we need to generate one after the whole struct has been processed. 8040 // Nonetheless, generateInfoForComponentList must be called to take 8041 // the pointer into account for the calculation of the range of the 8042 // partial struct. 8043 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 8044 /*ReturnDevicePointer=*/false, C->isImplicit()); 8045 DeferredInfo[nullptr].emplace_back(IE, VD); 8046 } else { 8047 llvm::Value *Ptr = 8048 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8049 BasePointers.emplace_back(Ptr, VD); 8050 Pointers.push_back(Ptr); 8051 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8052 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8053 } 8054 } 8055 } 8056 8057 for (const auto &M : Info) { 8058 // We need to know when we generate information for the first component 8059 // associated with a capture, because the mapping flags depend on it. 8060 bool IsFirstComponentList = true; 8061 8062 // Temporary versions of arrays 8063 MapBaseValuesArrayTy CurBasePointers; 8064 MapValuesArrayTy CurPointers; 8065 MapValuesArrayTy CurSizes; 8066 MapFlagsArrayTy CurTypes; 8067 StructRangeInfoTy PartialStruct; 8068 8069 for (const MapInfo &L : M.second) { 8070 assert(!L.Components.empty() && 8071 "Not expecting declaration with no component lists."); 8072 8073 // Remember the current base pointer index. 8074 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8075 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8076 CurBasePointers, CurPointers, CurSizes, 8077 CurTypes, PartialStruct, 8078 IsFirstComponentList, L.IsImplicit); 8079 8080 // If this entry relates with a device pointer, set the relevant 8081 // declaration and add the 'return pointer' flag. 8082 if (L.ReturnDevicePointer) { 8083 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8084 "Unexpected number of mapped base pointers."); 8085 8086 const ValueDecl *RelevantVD = 8087 L.Components.back().getAssociatedDeclaration(); 8088 assert(RelevantVD && 8089 "No relevant declaration related with device pointer??"); 8090 8091 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8092 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8093 } 8094 IsFirstComponentList = false; 8095 } 8096 8097 // Append any pending zero-length pointers which are struct members and 8098 // used with use_device_ptr. 8099 auto CI = DeferredInfo.find(M.first); 8100 if (CI != DeferredInfo.end()) { 8101 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8102 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8103 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8104 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8105 CurBasePointers.emplace_back(BasePtr, L.VD); 8106 CurPointers.push_back(Ptr); 8107 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8108 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8109 // value MEMBER_OF=FFFF so that the entry is later updated with the 8110 // correct value of MEMBER_OF. 8111 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8112 OMP_MAP_MEMBER_OF); 8113 } 8114 } 8115 8116 // If there is an entry in PartialStruct it means we have a struct with 8117 // individual members mapped. Emit an extra combined entry. 8118 if (PartialStruct.Base.isValid()) 8119 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8120 PartialStruct); 8121 8122 // We need to append the results of this capture to what we already have. 8123 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8124 Pointers.append(CurPointers.begin(), CurPointers.end()); 8125 Sizes.append(CurSizes.begin(), CurSizes.end()); 8126 Types.append(CurTypes.begin(), CurTypes.end()); 8127 } 8128 } 8129 8130 /// Generate all the base pointers, section pointers, sizes and map types for 8131 /// the extracted map clauses of user-defined mapper. 8132 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8133 MapValuesArrayTy &Pointers, 8134 MapValuesArrayTy &Sizes, 8135 MapFlagsArrayTy &Types) const { 8136 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8137 "Expect a declare mapper directive"); 8138 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8139 // We have to process the component lists that relate with the same 8140 // declaration in a single chunk so that we can generate the map flags 8141 // correctly. Therefore, we organize all lists in a map. 8142 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8143 8144 // Helper function to fill the information map for the different supported 8145 // clauses. 8146 auto &&InfoGen = [&Info]( 8147 const ValueDecl *D, 8148 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8149 OpenMPMapClauseKind MapType, 8150 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8151 bool ReturnDevicePointer, bool IsImplicit) { 8152 const ValueDecl *VD = 8153 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8154 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8155 IsImplicit); 8156 }; 8157 8158 for (const auto *C : CurMapperDir->clauselists()) { 8159 const auto *MC = cast<OMPMapClause>(C); 8160 for (const auto L : MC->component_lists()) { 8161 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8162 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8163 } 8164 } 8165 8166 for (const auto &M : Info) { 8167 // We need to know when we generate information for the first component 8168 // associated with a capture, because the mapping flags depend on it. 8169 bool IsFirstComponentList = true; 8170 8171 // Temporary versions of arrays 8172 MapBaseValuesArrayTy CurBasePointers; 8173 MapValuesArrayTy CurPointers; 8174 MapValuesArrayTy CurSizes; 8175 MapFlagsArrayTy CurTypes; 8176 StructRangeInfoTy PartialStruct; 8177 8178 for (const MapInfo &L : M.second) { 8179 assert(!L.Components.empty() && 8180 "Not expecting declaration with no component lists."); 8181 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8182 CurBasePointers, CurPointers, CurSizes, 8183 CurTypes, PartialStruct, 8184 IsFirstComponentList, L.IsImplicit); 8185 IsFirstComponentList = false; 8186 } 8187 8188 // If there is an entry in PartialStruct it means we have a struct with 8189 // individual members mapped. Emit an extra combined entry. 8190 if (PartialStruct.Base.isValid()) 8191 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8192 PartialStruct); 8193 8194 // We need to append the results of this capture to what we already have. 8195 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8196 Pointers.append(CurPointers.begin(), CurPointers.end()); 8197 Sizes.append(CurSizes.begin(), CurSizes.end()); 8198 Types.append(CurTypes.begin(), CurTypes.end()); 8199 } 8200 } 8201 8202 /// Emit capture info for lambdas for variables captured by reference. 8203 void generateInfoForLambdaCaptures( 8204 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8205 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8206 MapFlagsArrayTy &Types, 8207 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8208 const auto *RD = VD->getType() 8209 .getCanonicalType() 8210 .getNonReferenceType() 8211 ->getAsCXXRecordDecl(); 8212 if (!RD || !RD->isLambda()) 8213 return; 8214 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8215 LValue VDLVal = CGF.MakeAddrLValue( 8216 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8217 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8218 FieldDecl *ThisCapture = nullptr; 8219 RD->getCaptureFields(Captures, ThisCapture); 8220 if (ThisCapture) { 8221 LValue ThisLVal = 8222 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8223 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8224 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8225 VDLVal.getPointer(CGF)); 8226 BasePointers.push_back(ThisLVal.getPointer(CGF)); 8227 Pointers.push_back(ThisLValVal.getPointer(CGF)); 8228 Sizes.push_back( 8229 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8230 CGF.Int64Ty, /*isSigned=*/true)); 8231 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8232 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8233 } 8234 for (const LambdaCapture &LC : RD->captures()) { 8235 if (!LC.capturesVariable()) 8236 continue; 8237 const VarDecl *VD = LC.getCapturedVar(); 8238 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8239 continue; 8240 auto It = Captures.find(VD); 8241 assert(It != Captures.end() && "Found lambda capture without field."); 8242 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8243 if (LC.getCaptureKind() == LCK_ByRef) { 8244 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8245 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8246 VDLVal.getPointer(CGF)); 8247 BasePointers.push_back(VarLVal.getPointer(CGF)); 8248 Pointers.push_back(VarLValVal.getPointer(CGF)); 8249 Sizes.push_back(CGF.Builder.CreateIntCast( 8250 CGF.getTypeSize( 8251 VD->getType().getCanonicalType().getNonReferenceType()), 8252 CGF.Int64Ty, /*isSigned=*/true)); 8253 } else { 8254 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8255 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8256 VDLVal.getPointer(CGF)); 8257 BasePointers.push_back(VarLVal.getPointer(CGF)); 8258 Pointers.push_back(VarRVal.getScalarVal()); 8259 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8260 } 8261 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8262 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8263 } 8264 } 8265 8266 /// Set correct indices for lambdas captures. 8267 void adjustMemberOfForLambdaCaptures( 8268 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8269 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8270 MapFlagsArrayTy &Types) const { 8271 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8272 // Set correct member_of idx for all implicit lambda captures. 8273 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8274 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8275 continue; 8276 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8277 assert(BasePtr && "Unable to find base lambda address."); 8278 int TgtIdx = -1; 8279 for (unsigned J = I; J > 0; --J) { 8280 unsigned Idx = J - 1; 8281 if (Pointers[Idx] != BasePtr) 8282 continue; 8283 TgtIdx = Idx; 8284 break; 8285 } 8286 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8287 // All other current entries will be MEMBER_OF the combined entry 8288 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8289 // 0xFFFF in the MEMBER_OF field). 8290 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8291 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8292 } 8293 } 8294 8295 /// Generate the base pointers, section pointers, sizes and map types 8296 /// associated to a given capture. 8297 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8298 llvm::Value *Arg, 8299 MapBaseValuesArrayTy &BasePointers, 8300 MapValuesArrayTy &Pointers, 8301 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8302 StructRangeInfoTy &PartialStruct) const { 8303 assert(!Cap->capturesVariableArrayType() && 8304 "Not expecting to generate map info for a variable array type!"); 8305 8306 // We need to know when we generating information for the first component 8307 const ValueDecl *VD = Cap->capturesThis() 8308 ? nullptr 8309 : Cap->getCapturedVar()->getCanonicalDecl(); 8310 8311 // If this declaration appears in a is_device_ptr clause we just have to 8312 // pass the pointer by value. If it is a reference to a declaration, we just 8313 // pass its value. 8314 if (DevPointersMap.count(VD)) { 8315 BasePointers.emplace_back(Arg, VD); 8316 Pointers.push_back(Arg); 8317 Sizes.push_back( 8318 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8319 CGF.Int64Ty, /*isSigned=*/true)); 8320 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8321 return; 8322 } 8323 8324 using MapData = 8325 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8326 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8327 SmallVector<MapData, 4> DeclComponentLists; 8328 assert(CurDir.is<const OMPExecutableDirective *>() && 8329 "Expect a executable directive"); 8330 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8331 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8332 for (const auto L : C->decl_component_lists(VD)) { 8333 assert(L.first == VD && 8334 "We got information for the wrong declaration??"); 8335 assert(!L.second.empty() && 8336 "Not expecting declaration with no component lists."); 8337 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8338 C->getMapTypeModifiers(), 8339 C->isImplicit()); 8340 } 8341 } 8342 8343 // Find overlapping elements (including the offset from the base element). 8344 llvm::SmallDenseMap< 8345 const MapData *, 8346 llvm::SmallVector< 8347 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8348 4> 8349 OverlappedData; 8350 size_t Count = 0; 8351 for (const MapData &L : DeclComponentLists) { 8352 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8353 OpenMPMapClauseKind MapType; 8354 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8355 bool IsImplicit; 8356 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8357 ++Count; 8358 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8359 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8360 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8361 auto CI = Components.rbegin(); 8362 auto CE = Components.rend(); 8363 auto SI = Components1.rbegin(); 8364 auto SE = Components1.rend(); 8365 for (; CI != CE && SI != SE; ++CI, ++SI) { 8366 if (CI->getAssociatedExpression()->getStmtClass() != 8367 SI->getAssociatedExpression()->getStmtClass()) 8368 break; 8369 // Are we dealing with different variables/fields? 8370 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8371 break; 8372 } 8373 // Found overlapping if, at least for one component, reached the head of 8374 // the components list. 8375 if (CI == CE || SI == SE) { 8376 assert((CI != CE || SI != SE) && 8377 "Unexpected full match of the mapping components."); 8378 const MapData &BaseData = CI == CE ? L : L1; 8379 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8380 SI == SE ? Components : Components1; 8381 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8382 OverlappedElements.getSecond().push_back(SubData); 8383 } 8384 } 8385 } 8386 // Sort the overlapped elements for each item. 8387 llvm::SmallVector<const FieldDecl *, 4> Layout; 8388 if (!OverlappedData.empty()) { 8389 if (const auto *CRD = 8390 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8391 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8392 else { 8393 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8394 Layout.append(RD->field_begin(), RD->field_end()); 8395 } 8396 } 8397 for (auto &Pair : OverlappedData) { 8398 llvm::sort( 8399 Pair.getSecond(), 8400 [&Layout]( 8401 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8402 OMPClauseMappableExprCommon::MappableExprComponentListRef 8403 Second) { 8404 auto CI = First.rbegin(); 8405 auto CE = First.rend(); 8406 auto SI = Second.rbegin(); 8407 auto SE = Second.rend(); 8408 for (; CI != CE && SI != SE; ++CI, ++SI) { 8409 if (CI->getAssociatedExpression()->getStmtClass() != 8410 SI->getAssociatedExpression()->getStmtClass()) 8411 break; 8412 // Are we dealing with different variables/fields? 8413 if (CI->getAssociatedDeclaration() != 8414 SI->getAssociatedDeclaration()) 8415 break; 8416 } 8417 8418 // Lists contain the same elements. 8419 if (CI == CE && SI == SE) 8420 return false; 8421 8422 // List with less elements is less than list with more elements. 8423 if (CI == CE || SI == SE) 8424 return CI == CE; 8425 8426 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8427 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8428 if (FD1->getParent() == FD2->getParent()) 8429 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8430 const auto It = 8431 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8432 return FD == FD1 || FD == FD2; 8433 }); 8434 return *It == FD1; 8435 }); 8436 } 8437 8438 // Associated with a capture, because the mapping flags depend on it. 8439 // Go through all of the elements with the overlapped elements. 8440 for (const auto &Pair : OverlappedData) { 8441 const MapData &L = *Pair.getFirst(); 8442 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8443 OpenMPMapClauseKind MapType; 8444 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8445 bool IsImplicit; 8446 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8447 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8448 OverlappedComponents = Pair.getSecond(); 8449 bool IsFirstComponentList = true; 8450 generateInfoForComponentList(MapType, MapModifiers, Components, 8451 BasePointers, Pointers, Sizes, Types, 8452 PartialStruct, IsFirstComponentList, 8453 IsImplicit, OverlappedComponents); 8454 } 8455 // Go through other elements without overlapped elements. 8456 bool IsFirstComponentList = OverlappedData.empty(); 8457 for (const MapData &L : DeclComponentLists) { 8458 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8459 OpenMPMapClauseKind MapType; 8460 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8461 bool IsImplicit; 8462 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8463 auto It = OverlappedData.find(&L); 8464 if (It == OverlappedData.end()) 8465 generateInfoForComponentList(MapType, MapModifiers, Components, 8466 BasePointers, Pointers, Sizes, Types, 8467 PartialStruct, IsFirstComponentList, 8468 IsImplicit); 8469 IsFirstComponentList = false; 8470 } 8471 } 8472 8473 /// Generate the base pointers, section pointers, sizes and map types 8474 /// associated with the declare target link variables. 8475 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8476 MapValuesArrayTy &Pointers, 8477 MapValuesArrayTy &Sizes, 8478 MapFlagsArrayTy &Types) const { 8479 assert(CurDir.is<const OMPExecutableDirective *>() && 8480 "Expect a executable directive"); 8481 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8482 // Map other list items in the map clause which are not captured variables 8483 // but "declare target link" global variables. 8484 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8485 for (const auto L : C->component_lists()) { 8486 if (!L.first) 8487 continue; 8488 const auto *VD = dyn_cast<VarDecl>(L.first); 8489 if (!VD) 8490 continue; 8491 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8492 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8493 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8494 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8495 continue; 8496 StructRangeInfoTy PartialStruct; 8497 generateInfoForComponentList( 8498 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8499 Pointers, Sizes, Types, PartialStruct, 8500 /*IsFirstComponentList=*/true, C->isImplicit()); 8501 assert(!PartialStruct.Base.isValid() && 8502 "No partial structs for declare target link expected."); 8503 } 8504 } 8505 } 8506 8507 /// Generate the default map information for a given capture \a CI, 8508 /// record field declaration \a RI and captured value \a CV. 8509 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8510 const FieldDecl &RI, llvm::Value *CV, 8511 MapBaseValuesArrayTy &CurBasePointers, 8512 MapValuesArrayTy &CurPointers, 8513 MapValuesArrayTy &CurSizes, 8514 MapFlagsArrayTy &CurMapTypes) const { 8515 bool IsImplicit = true; 8516 // Do the default mapping. 8517 if (CI.capturesThis()) { 8518 CurBasePointers.push_back(CV); 8519 CurPointers.push_back(CV); 8520 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8521 CurSizes.push_back( 8522 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8523 CGF.Int64Ty, /*isSigned=*/true)); 8524 // Default map type. 8525 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8526 } else if (CI.capturesVariableByCopy()) { 8527 CurBasePointers.push_back(CV); 8528 CurPointers.push_back(CV); 8529 if (!RI.getType()->isAnyPointerType()) { 8530 // We have to signal to the runtime captures passed by value that are 8531 // not pointers. 8532 CurMapTypes.push_back(OMP_MAP_LITERAL); 8533 CurSizes.push_back(CGF.Builder.CreateIntCast( 8534 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8535 } else { 8536 // Pointers are implicitly mapped with a zero size and no flags 8537 // (other than first map that is added for all implicit maps). 8538 CurMapTypes.push_back(OMP_MAP_NONE); 8539 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8540 } 8541 const VarDecl *VD = CI.getCapturedVar(); 8542 auto I = FirstPrivateDecls.find(VD); 8543 if (I != FirstPrivateDecls.end()) 8544 IsImplicit = I->getSecond(); 8545 } else { 8546 assert(CI.capturesVariable() && "Expected captured reference."); 8547 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8548 QualType ElementType = PtrTy->getPointeeType(); 8549 CurSizes.push_back(CGF.Builder.CreateIntCast( 8550 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8551 // The default map type for a scalar/complex type is 'to' because by 8552 // default the value doesn't have to be retrieved. For an aggregate 8553 // type, the default is 'tofrom'. 8554 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8555 const VarDecl *VD = CI.getCapturedVar(); 8556 auto I = FirstPrivateDecls.find(VD); 8557 if (I != FirstPrivateDecls.end() && 8558 VD->getType().isConstant(CGF.getContext())) { 8559 llvm::Constant *Addr = 8560 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8561 // Copy the value of the original variable to the new global copy. 8562 CGF.Builder.CreateMemCpy( 8563 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 8564 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8565 CurSizes.back(), /*IsVolatile=*/false); 8566 // Use new global variable as the base pointers. 8567 CurBasePointers.push_back(Addr); 8568 CurPointers.push_back(Addr); 8569 } else { 8570 CurBasePointers.push_back(CV); 8571 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8572 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8573 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8574 AlignmentSource::Decl)); 8575 CurPointers.push_back(PtrAddr.getPointer()); 8576 } else { 8577 CurPointers.push_back(CV); 8578 } 8579 } 8580 if (I != FirstPrivateDecls.end()) 8581 IsImplicit = I->getSecond(); 8582 } 8583 // Every default map produces a single argument which is a target parameter. 8584 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8585 8586 // Add flag stating this is an implicit map. 8587 if (IsImplicit) 8588 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8589 } 8590 }; 8591 } // anonymous namespace 8592 8593 /// Emit the arrays used to pass the captures and map information to the 8594 /// offloading runtime library. If there is no map or capture information, 8595 /// return nullptr by reference. 8596 static void 8597 emitOffloadingArrays(CodeGenFunction &CGF, 8598 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8599 MappableExprsHandler::MapValuesArrayTy &Pointers, 8600 MappableExprsHandler::MapValuesArrayTy &Sizes, 8601 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8602 CGOpenMPRuntime::TargetDataInfo &Info) { 8603 CodeGenModule &CGM = CGF.CGM; 8604 ASTContext &Ctx = CGF.getContext(); 8605 8606 // Reset the array information. 8607 Info.clearArrayInfo(); 8608 Info.NumberOfPtrs = BasePointers.size(); 8609 8610 if (Info.NumberOfPtrs) { 8611 // Detect if we have any capture size requiring runtime evaluation of the 8612 // size so that a constant array could be eventually used. 8613 bool hasRuntimeEvaluationCaptureSize = false; 8614 for (llvm::Value *S : Sizes) 8615 if (!isa<llvm::Constant>(S)) { 8616 hasRuntimeEvaluationCaptureSize = true; 8617 break; 8618 } 8619 8620 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8621 QualType PointerArrayType = Ctx.getConstantArrayType( 8622 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8623 /*IndexTypeQuals=*/0); 8624 8625 Info.BasePointersArray = 8626 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8627 Info.PointersArray = 8628 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8629 8630 // If we don't have any VLA types or other types that require runtime 8631 // evaluation, we can use a constant array for the map sizes, otherwise we 8632 // need to fill up the arrays as we do for the pointers. 8633 QualType Int64Ty = 8634 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8635 if (hasRuntimeEvaluationCaptureSize) { 8636 QualType SizeArrayType = Ctx.getConstantArrayType( 8637 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8638 /*IndexTypeQuals=*/0); 8639 Info.SizesArray = 8640 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8641 } else { 8642 // We expect all the sizes to be constant, so we collect them to create 8643 // a constant array. 8644 SmallVector<llvm::Constant *, 16> ConstSizes; 8645 for (llvm::Value *S : Sizes) 8646 ConstSizes.push_back(cast<llvm::Constant>(S)); 8647 8648 auto *SizesArrayInit = llvm::ConstantArray::get( 8649 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8650 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8651 auto *SizesArrayGbl = new llvm::GlobalVariable( 8652 CGM.getModule(), SizesArrayInit->getType(), 8653 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8654 SizesArrayInit, Name); 8655 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8656 Info.SizesArray = SizesArrayGbl; 8657 } 8658 8659 // The map types are always constant so we don't need to generate code to 8660 // fill arrays. Instead, we create an array constant. 8661 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8662 llvm::copy(MapTypes, Mapping.begin()); 8663 llvm::Constant *MapTypesArrayInit = 8664 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8665 std::string MaptypesName = 8666 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8667 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8668 CGM.getModule(), MapTypesArrayInit->getType(), 8669 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8670 MapTypesArrayInit, MaptypesName); 8671 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8672 Info.MapTypesArray = MapTypesArrayGbl; 8673 8674 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8675 llvm::Value *BPVal = *BasePointers[I]; 8676 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8677 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8678 Info.BasePointersArray, 0, I); 8679 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8680 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8681 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8682 CGF.Builder.CreateStore(BPVal, BPAddr); 8683 8684 if (Info.requiresDevicePointerInfo()) 8685 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8686 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8687 8688 llvm::Value *PVal = Pointers[I]; 8689 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8690 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8691 Info.PointersArray, 0, I); 8692 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8693 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8694 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8695 CGF.Builder.CreateStore(PVal, PAddr); 8696 8697 if (hasRuntimeEvaluationCaptureSize) { 8698 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8699 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8700 Info.SizesArray, 8701 /*Idx0=*/0, 8702 /*Idx1=*/I); 8703 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8704 CGF.Builder.CreateStore( 8705 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8706 SAddr); 8707 } 8708 } 8709 } 8710 } 8711 8712 /// Emit the arguments to be passed to the runtime library based on the 8713 /// arrays of pointers, sizes and map types. 8714 static void emitOffloadingArraysArgument( 8715 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8716 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8717 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8718 CodeGenModule &CGM = CGF.CGM; 8719 if (Info.NumberOfPtrs) { 8720 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8721 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8722 Info.BasePointersArray, 8723 /*Idx0=*/0, /*Idx1=*/0); 8724 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8725 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8726 Info.PointersArray, 8727 /*Idx0=*/0, 8728 /*Idx1=*/0); 8729 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8730 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8731 /*Idx0=*/0, /*Idx1=*/0); 8732 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8733 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8734 Info.MapTypesArray, 8735 /*Idx0=*/0, 8736 /*Idx1=*/0); 8737 } else { 8738 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8739 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8740 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8741 MapTypesArrayArg = 8742 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8743 } 8744 } 8745 8746 /// Check for inner distribute directive. 8747 static const OMPExecutableDirective * 8748 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8749 const auto *CS = D.getInnermostCapturedStmt(); 8750 const auto *Body = 8751 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8752 const Stmt *ChildStmt = 8753 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8754 8755 if (const auto *NestedDir = 8756 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8757 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8758 switch (D.getDirectiveKind()) { 8759 case OMPD_target: 8760 if (isOpenMPDistributeDirective(DKind)) 8761 return NestedDir; 8762 if (DKind == OMPD_teams) { 8763 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8764 /*IgnoreCaptured=*/true); 8765 if (!Body) 8766 return nullptr; 8767 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8768 if (const auto *NND = 8769 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8770 DKind = NND->getDirectiveKind(); 8771 if (isOpenMPDistributeDirective(DKind)) 8772 return NND; 8773 } 8774 } 8775 return nullptr; 8776 case OMPD_target_teams: 8777 if (isOpenMPDistributeDirective(DKind)) 8778 return NestedDir; 8779 return nullptr; 8780 case OMPD_target_parallel: 8781 case OMPD_target_simd: 8782 case OMPD_target_parallel_for: 8783 case OMPD_target_parallel_for_simd: 8784 return nullptr; 8785 case OMPD_target_teams_distribute: 8786 case OMPD_target_teams_distribute_simd: 8787 case OMPD_target_teams_distribute_parallel_for: 8788 case OMPD_target_teams_distribute_parallel_for_simd: 8789 case OMPD_parallel: 8790 case OMPD_for: 8791 case OMPD_parallel_for: 8792 case OMPD_parallel_master: 8793 case OMPD_parallel_sections: 8794 case OMPD_for_simd: 8795 case OMPD_parallel_for_simd: 8796 case OMPD_cancel: 8797 case OMPD_cancellation_point: 8798 case OMPD_ordered: 8799 case OMPD_threadprivate: 8800 case OMPD_allocate: 8801 case OMPD_task: 8802 case OMPD_simd: 8803 case OMPD_sections: 8804 case OMPD_section: 8805 case OMPD_single: 8806 case OMPD_master: 8807 case OMPD_critical: 8808 case OMPD_taskyield: 8809 case OMPD_barrier: 8810 case OMPD_taskwait: 8811 case OMPD_taskgroup: 8812 case OMPD_atomic: 8813 case OMPD_flush: 8814 case OMPD_teams: 8815 case OMPD_target_data: 8816 case OMPD_target_exit_data: 8817 case OMPD_target_enter_data: 8818 case OMPD_distribute: 8819 case OMPD_distribute_simd: 8820 case OMPD_distribute_parallel_for: 8821 case OMPD_distribute_parallel_for_simd: 8822 case OMPD_teams_distribute: 8823 case OMPD_teams_distribute_simd: 8824 case OMPD_teams_distribute_parallel_for: 8825 case OMPD_teams_distribute_parallel_for_simd: 8826 case OMPD_target_update: 8827 case OMPD_declare_simd: 8828 case OMPD_declare_variant: 8829 case OMPD_declare_target: 8830 case OMPD_end_declare_target: 8831 case OMPD_declare_reduction: 8832 case OMPD_declare_mapper: 8833 case OMPD_taskloop: 8834 case OMPD_taskloop_simd: 8835 case OMPD_master_taskloop: 8836 case OMPD_master_taskloop_simd: 8837 case OMPD_parallel_master_taskloop: 8838 case OMPD_parallel_master_taskloop_simd: 8839 case OMPD_requires: 8840 case OMPD_unknown: 8841 llvm_unreachable("Unexpected directive."); 8842 } 8843 } 8844 8845 return nullptr; 8846 } 8847 8848 /// Emit the user-defined mapper function. The code generation follows the 8849 /// pattern in the example below. 8850 /// \code 8851 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8852 /// void *base, void *begin, 8853 /// int64_t size, int64_t type) { 8854 /// // Allocate space for an array section first. 8855 /// if (size > 1 && !maptype.IsDelete) 8856 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8857 /// size*sizeof(Ty), clearToFrom(type)); 8858 /// // Map members. 8859 /// for (unsigned i = 0; i < size; i++) { 8860 /// // For each component specified by this mapper: 8861 /// for (auto c : all_components) { 8862 /// if (c.hasMapper()) 8863 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8864 /// c.arg_type); 8865 /// else 8866 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8867 /// c.arg_begin, c.arg_size, c.arg_type); 8868 /// } 8869 /// } 8870 /// // Delete the array section. 8871 /// if (size > 1 && maptype.IsDelete) 8872 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8873 /// size*sizeof(Ty), clearToFrom(type)); 8874 /// } 8875 /// \endcode 8876 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8877 CodeGenFunction *CGF) { 8878 if (UDMMap.count(D) > 0) 8879 return; 8880 ASTContext &C = CGM.getContext(); 8881 QualType Ty = D->getType(); 8882 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8883 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8884 auto *MapperVarDecl = 8885 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8886 SourceLocation Loc = D->getLocation(); 8887 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8888 8889 // Prepare mapper function arguments and attributes. 8890 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8891 C.VoidPtrTy, ImplicitParamDecl::Other); 8892 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8893 ImplicitParamDecl::Other); 8894 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8895 C.VoidPtrTy, ImplicitParamDecl::Other); 8896 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8897 ImplicitParamDecl::Other); 8898 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8899 ImplicitParamDecl::Other); 8900 FunctionArgList Args; 8901 Args.push_back(&HandleArg); 8902 Args.push_back(&BaseArg); 8903 Args.push_back(&BeginArg); 8904 Args.push_back(&SizeArg); 8905 Args.push_back(&TypeArg); 8906 const CGFunctionInfo &FnInfo = 8907 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8908 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8909 SmallString<64> TyStr; 8910 llvm::raw_svector_ostream Out(TyStr); 8911 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 8912 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 8913 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 8914 Name, &CGM.getModule()); 8915 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 8916 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 8917 // Start the mapper function code generation. 8918 CodeGenFunction MapperCGF(CGM); 8919 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 8920 // Compute the starting and end addreses of array elements. 8921 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 8922 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 8923 C.getPointerType(Int64Ty), Loc); 8924 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 8925 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 8926 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 8927 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 8928 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 8929 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 8930 C.getPointerType(Int64Ty), Loc); 8931 // Prepare common arguments for array initiation and deletion. 8932 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 8933 MapperCGF.GetAddrOfLocalVar(&HandleArg), 8934 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8935 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 8936 MapperCGF.GetAddrOfLocalVar(&BaseArg), 8937 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8938 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 8939 MapperCGF.GetAddrOfLocalVar(&BeginArg), 8940 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8941 8942 // Emit array initiation if this is an array section and \p MapType indicates 8943 // that memory allocation is required. 8944 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 8945 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8946 ElementSize, HeadBB, /*IsInit=*/true); 8947 8948 // Emit a for loop to iterate through SizeArg of elements and map all of them. 8949 8950 // Emit the loop header block. 8951 MapperCGF.EmitBlock(HeadBB); 8952 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 8953 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 8954 // Evaluate whether the initial condition is satisfied. 8955 llvm::Value *IsEmpty = 8956 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 8957 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 8958 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 8959 8960 // Emit the loop body block. 8961 MapperCGF.EmitBlock(BodyBB); 8962 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 8963 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 8964 PtrPHI->addIncoming(PtrBegin, EntryBB); 8965 Address PtrCurrent = 8966 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 8967 .getAlignment() 8968 .alignmentOfArrayElement(ElementSize)); 8969 // Privatize the declared variable of mapper to be the current array element. 8970 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 8971 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 8972 return MapperCGF 8973 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 8974 .getAddress(MapperCGF); 8975 }); 8976 (void)Scope.Privatize(); 8977 8978 // Get map clause information. Fill up the arrays with all mapped variables. 8979 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 8980 MappableExprsHandler::MapValuesArrayTy Pointers; 8981 MappableExprsHandler::MapValuesArrayTy Sizes; 8982 MappableExprsHandler::MapFlagsArrayTy MapTypes; 8983 MappableExprsHandler MEHandler(*D, MapperCGF); 8984 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 8985 8986 // Call the runtime API __tgt_mapper_num_components to get the number of 8987 // pre-existing components. 8988 llvm::Value *OffloadingArgs[] = {Handle}; 8989 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 8990 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 8991 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 8992 PreviousSize, 8993 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 8994 8995 // Fill up the runtime mapper handle for all components. 8996 for (unsigned I = 0; I < BasePointers.size(); ++I) { 8997 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 8998 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8999 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 9000 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 9001 llvm::Value *CurSizeArg = Sizes[I]; 9002 9003 // Extract the MEMBER_OF field from the map type. 9004 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 9005 MapperCGF.EmitBlock(MemberBB); 9006 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 9007 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 9008 OriMapType, 9009 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 9010 llvm::BasicBlock *MemberCombineBB = 9011 MapperCGF.createBasicBlock("omp.member.combine"); 9012 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 9013 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 9014 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 9015 // Add the number of pre-existing components to the MEMBER_OF field if it 9016 // is valid. 9017 MapperCGF.EmitBlock(MemberCombineBB); 9018 llvm::Value *CombinedMember = 9019 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 9020 // Do nothing if it is not a member of previous components. 9021 MapperCGF.EmitBlock(TypeBB); 9022 llvm::PHINode *MemberMapType = 9023 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 9024 MemberMapType->addIncoming(OriMapType, MemberBB); 9025 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 9026 9027 // Combine the map type inherited from user-defined mapper with that 9028 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 9029 // bits of the \a MapType, which is the input argument of the mapper 9030 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 9031 // bits of MemberMapType. 9032 // [OpenMP 5.0], 1.2.6. map-type decay. 9033 // | alloc | to | from | tofrom | release | delete 9034 // ---------------------------------------------------------- 9035 // alloc | alloc | alloc | alloc | alloc | release | delete 9036 // to | alloc | to | alloc | to | release | delete 9037 // from | alloc | alloc | from | from | release | delete 9038 // tofrom | alloc | to | from | tofrom | release | delete 9039 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9040 MapType, 9041 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9042 MappableExprsHandler::OMP_MAP_FROM)); 9043 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9044 llvm::BasicBlock *AllocElseBB = 9045 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9046 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9047 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9048 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9049 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9050 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9051 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9052 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9053 MapperCGF.EmitBlock(AllocBB); 9054 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9055 MemberMapType, 9056 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9057 MappableExprsHandler::OMP_MAP_FROM))); 9058 MapperCGF.Builder.CreateBr(EndBB); 9059 MapperCGF.EmitBlock(AllocElseBB); 9060 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9061 LeftToFrom, 9062 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9063 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9064 // In case of to, clear OMP_MAP_FROM. 9065 MapperCGF.EmitBlock(ToBB); 9066 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9067 MemberMapType, 9068 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9069 MapperCGF.Builder.CreateBr(EndBB); 9070 MapperCGF.EmitBlock(ToElseBB); 9071 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9072 LeftToFrom, 9073 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9074 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9075 // In case of from, clear OMP_MAP_TO. 9076 MapperCGF.EmitBlock(FromBB); 9077 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9078 MemberMapType, 9079 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9080 // In case of tofrom, do nothing. 9081 MapperCGF.EmitBlock(EndBB); 9082 llvm::PHINode *CurMapType = 9083 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9084 CurMapType->addIncoming(AllocMapType, AllocBB); 9085 CurMapType->addIncoming(ToMapType, ToBB); 9086 CurMapType->addIncoming(FromMapType, FromBB); 9087 CurMapType->addIncoming(MemberMapType, ToElseBB); 9088 9089 // TODO: call the corresponding mapper function if a user-defined mapper is 9090 // associated with this map clause. 9091 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9092 // data structure. 9093 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9094 CurSizeArg, CurMapType}; 9095 MapperCGF.EmitRuntimeCall( 9096 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9097 OffloadingArgs); 9098 } 9099 9100 // Update the pointer to point to the next element that needs to be mapped, 9101 // and check whether we have mapped all elements. 9102 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9103 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9104 PtrPHI->addIncoming(PtrNext, BodyBB); 9105 llvm::Value *IsDone = 9106 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9107 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9108 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9109 9110 MapperCGF.EmitBlock(ExitBB); 9111 // Emit array deletion if this is an array section and \p MapType indicates 9112 // that deletion is required. 9113 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9114 ElementSize, DoneBB, /*IsInit=*/false); 9115 9116 // Emit the function exit block. 9117 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9118 MapperCGF.FinishFunction(); 9119 UDMMap.try_emplace(D, Fn); 9120 if (CGF) { 9121 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9122 Decls.second.push_back(D); 9123 } 9124 } 9125 9126 /// Emit the array initialization or deletion portion for user-defined mapper 9127 /// code generation. First, it evaluates whether an array section is mapped and 9128 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9129 /// true, and \a MapType indicates to not delete this array, array 9130 /// initialization code is generated. If \a IsInit is false, and \a MapType 9131 /// indicates to not this array, array deletion code is generated. 9132 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9133 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9134 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9135 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9136 StringRef Prefix = IsInit ? ".init" : ".del"; 9137 9138 // Evaluate if this is an array section. 9139 llvm::BasicBlock *IsDeleteBB = 9140 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete"); 9141 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix); 9142 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9143 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9144 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9145 9146 // Evaluate if we are going to delete this section. 9147 MapperCGF.EmitBlock(IsDeleteBB); 9148 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9149 MapType, 9150 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9151 llvm::Value *DeleteCond; 9152 if (IsInit) { 9153 DeleteCond = MapperCGF.Builder.CreateIsNull( 9154 DeleteBit, "omp.array" + Prefix + ".delete"); 9155 } else { 9156 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9157 DeleteBit, "omp.array" + Prefix + ".delete"); 9158 } 9159 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9160 9161 MapperCGF.EmitBlock(BodyBB); 9162 // Get the array size by multiplying element size and element number (i.e., \p 9163 // Size). 9164 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9165 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9166 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9167 // memory allocation/deletion purpose only. 9168 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9169 MapType, 9170 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9171 MappableExprsHandler::OMP_MAP_FROM))); 9172 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9173 // data structure. 9174 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9175 MapperCGF.EmitRuntimeCall( 9176 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9177 } 9178 9179 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9180 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9181 llvm::Value *DeviceID, 9182 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9183 const OMPLoopDirective &D)> 9184 SizeEmitter) { 9185 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9186 const OMPExecutableDirective *TD = &D; 9187 // Get nested teams distribute kind directive, if any. 9188 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9189 TD = getNestedDistributeDirective(CGM.getContext(), D); 9190 if (!TD) 9191 return; 9192 const auto *LD = cast<OMPLoopDirective>(TD); 9193 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9194 PrePostActionTy &) { 9195 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9196 llvm::Value *Args[] = {DeviceID, NumIterations}; 9197 CGF.EmitRuntimeCall( 9198 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9199 } 9200 }; 9201 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9202 } 9203 9204 void CGOpenMPRuntime::emitTargetCall( 9205 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9206 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9207 const Expr *Device, 9208 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9209 const OMPLoopDirective &D)> 9210 SizeEmitter) { 9211 if (!CGF.HaveInsertPoint()) 9212 return; 9213 9214 assert(OutlinedFn && "Invalid outlined function!"); 9215 9216 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9217 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9218 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9219 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9220 PrePostActionTy &) { 9221 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9222 }; 9223 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9224 9225 CodeGenFunction::OMPTargetDataInfo InputInfo; 9226 llvm::Value *MapTypesArray = nullptr; 9227 // Fill up the pointer arrays and transfer execution to the device. 9228 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9229 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9230 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9231 // On top of the arrays that were filled up, the target offloading call 9232 // takes as arguments the device id as well as the host pointer. The host 9233 // pointer is used by the runtime library to identify the current target 9234 // region, so it only has to be unique and not necessarily point to 9235 // anything. It could be the pointer to the outlined function that 9236 // implements the target region, but we aren't using that so that the 9237 // compiler doesn't need to keep that, and could therefore inline the host 9238 // function if proven worthwhile during optimization. 9239 9240 // From this point on, we need to have an ID of the target region defined. 9241 assert(OutlinedFnID && "Invalid outlined function ID!"); 9242 9243 // Emit device ID if any. 9244 llvm::Value *DeviceID; 9245 if (Device) { 9246 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9247 CGF.Int64Ty, /*isSigned=*/true); 9248 } else { 9249 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9250 } 9251 9252 // Emit the number of elements in the offloading arrays. 9253 llvm::Value *PointerNum = 9254 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9255 9256 // Return value of the runtime offloading call. 9257 llvm::Value *Return; 9258 9259 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9260 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9261 9262 // Emit tripcount for the target loop-based directive. 9263 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9264 9265 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9266 // The target region is an outlined function launched by the runtime 9267 // via calls __tgt_target() or __tgt_target_teams(). 9268 // 9269 // __tgt_target() launches a target region with one team and one thread, 9270 // executing a serial region. This master thread may in turn launch 9271 // more threads within its team upon encountering a parallel region, 9272 // however, no additional teams can be launched on the device. 9273 // 9274 // __tgt_target_teams() launches a target region with one or more teams, 9275 // each with one or more threads. This call is required for target 9276 // constructs such as: 9277 // 'target teams' 9278 // 'target' / 'teams' 9279 // 'target teams distribute parallel for' 9280 // 'target parallel' 9281 // and so on. 9282 // 9283 // Note that on the host and CPU targets, the runtime implementation of 9284 // these calls simply call the outlined function without forking threads. 9285 // The outlined functions themselves have runtime calls to 9286 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9287 // the compiler in emitTeamsCall() and emitParallelCall(). 9288 // 9289 // In contrast, on the NVPTX target, the implementation of 9290 // __tgt_target_teams() launches a GPU kernel with the requested number 9291 // of teams and threads so no additional calls to the runtime are required. 9292 if (NumTeams) { 9293 // If we have NumTeams defined this means that we have an enclosed teams 9294 // region. Therefore we also expect to have NumThreads defined. These two 9295 // values should be defined in the presence of a teams directive, 9296 // regardless of having any clauses associated. If the user is using teams 9297 // but no clauses, these two values will be the default that should be 9298 // passed to the runtime library - a 32-bit integer with the value zero. 9299 assert(NumThreads && "Thread limit expression should be available along " 9300 "with number of teams."); 9301 llvm::Value *OffloadingArgs[] = {DeviceID, 9302 OutlinedFnID, 9303 PointerNum, 9304 InputInfo.BasePointersArray.getPointer(), 9305 InputInfo.PointersArray.getPointer(), 9306 InputInfo.SizesArray.getPointer(), 9307 MapTypesArray, 9308 NumTeams, 9309 NumThreads}; 9310 Return = CGF.EmitRuntimeCall( 9311 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9312 : OMPRTL__tgt_target_teams), 9313 OffloadingArgs); 9314 } else { 9315 llvm::Value *OffloadingArgs[] = {DeviceID, 9316 OutlinedFnID, 9317 PointerNum, 9318 InputInfo.BasePointersArray.getPointer(), 9319 InputInfo.PointersArray.getPointer(), 9320 InputInfo.SizesArray.getPointer(), 9321 MapTypesArray}; 9322 Return = CGF.EmitRuntimeCall( 9323 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9324 : OMPRTL__tgt_target), 9325 OffloadingArgs); 9326 } 9327 9328 // Check the error code and execute the host version if required. 9329 llvm::BasicBlock *OffloadFailedBlock = 9330 CGF.createBasicBlock("omp_offload.failed"); 9331 llvm::BasicBlock *OffloadContBlock = 9332 CGF.createBasicBlock("omp_offload.cont"); 9333 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9334 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9335 9336 CGF.EmitBlock(OffloadFailedBlock); 9337 if (RequiresOuterTask) { 9338 CapturedVars.clear(); 9339 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9340 } 9341 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9342 CGF.EmitBranch(OffloadContBlock); 9343 9344 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9345 }; 9346 9347 // Notify that the host version must be executed. 9348 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9349 RequiresOuterTask](CodeGenFunction &CGF, 9350 PrePostActionTy &) { 9351 if (RequiresOuterTask) { 9352 CapturedVars.clear(); 9353 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9354 } 9355 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9356 }; 9357 9358 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9359 &CapturedVars, RequiresOuterTask, 9360 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9361 // Fill up the arrays with all the captured variables. 9362 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9363 MappableExprsHandler::MapValuesArrayTy Pointers; 9364 MappableExprsHandler::MapValuesArrayTy Sizes; 9365 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9366 9367 // Get mappable expression information. 9368 MappableExprsHandler MEHandler(D, CGF); 9369 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9370 9371 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9372 auto CV = CapturedVars.begin(); 9373 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9374 CE = CS.capture_end(); 9375 CI != CE; ++CI, ++RI, ++CV) { 9376 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9377 MappableExprsHandler::MapValuesArrayTy CurPointers; 9378 MappableExprsHandler::MapValuesArrayTy CurSizes; 9379 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9380 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9381 9382 // VLA sizes are passed to the outlined region by copy and do not have map 9383 // information associated. 9384 if (CI->capturesVariableArrayType()) { 9385 CurBasePointers.push_back(*CV); 9386 CurPointers.push_back(*CV); 9387 CurSizes.push_back(CGF.Builder.CreateIntCast( 9388 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9389 // Copy to the device as an argument. No need to retrieve it. 9390 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9391 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9392 MappableExprsHandler::OMP_MAP_IMPLICIT); 9393 } else { 9394 // If we have any information in the map clause, we use it, otherwise we 9395 // just do a default mapping. 9396 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9397 CurSizes, CurMapTypes, PartialStruct); 9398 if (CurBasePointers.empty()) 9399 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9400 CurPointers, CurSizes, CurMapTypes); 9401 // Generate correct mapping for variables captured by reference in 9402 // lambdas. 9403 if (CI->capturesVariable()) 9404 MEHandler.generateInfoForLambdaCaptures( 9405 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9406 CurMapTypes, LambdaPointers); 9407 } 9408 // We expect to have at least an element of information for this capture. 9409 assert(!CurBasePointers.empty() && 9410 "Non-existing map pointer for capture!"); 9411 assert(CurBasePointers.size() == CurPointers.size() && 9412 CurBasePointers.size() == CurSizes.size() && 9413 CurBasePointers.size() == CurMapTypes.size() && 9414 "Inconsistent map information sizes!"); 9415 9416 // If there is an entry in PartialStruct it means we have a struct with 9417 // individual members mapped. Emit an extra combined entry. 9418 if (PartialStruct.Base.isValid()) 9419 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9420 CurMapTypes, PartialStruct); 9421 9422 // We need to append the results of this capture to what we already have. 9423 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9424 Pointers.append(CurPointers.begin(), CurPointers.end()); 9425 Sizes.append(CurSizes.begin(), CurSizes.end()); 9426 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9427 } 9428 // Adjust MEMBER_OF flags for the lambdas captures. 9429 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9430 Pointers, MapTypes); 9431 // Map other list items in the map clause which are not captured variables 9432 // but "declare target link" global variables. 9433 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9434 MapTypes); 9435 9436 TargetDataInfo Info; 9437 // Fill up the arrays and create the arguments. 9438 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9439 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9440 Info.PointersArray, Info.SizesArray, 9441 Info.MapTypesArray, Info); 9442 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9443 InputInfo.BasePointersArray = 9444 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9445 InputInfo.PointersArray = 9446 Address(Info.PointersArray, CGM.getPointerAlign()); 9447 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9448 MapTypesArray = Info.MapTypesArray; 9449 if (RequiresOuterTask) 9450 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9451 else 9452 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9453 }; 9454 9455 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9456 CodeGenFunction &CGF, PrePostActionTy &) { 9457 if (RequiresOuterTask) { 9458 CodeGenFunction::OMPTargetDataInfo InputInfo; 9459 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9460 } else { 9461 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9462 } 9463 }; 9464 9465 // If we have a target function ID it means that we need to support 9466 // offloading, otherwise, just execute on the host. We need to execute on host 9467 // regardless of the conditional in the if clause if, e.g., the user do not 9468 // specify target triples. 9469 if (OutlinedFnID) { 9470 if (IfCond) { 9471 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9472 } else { 9473 RegionCodeGenTy ThenRCG(TargetThenGen); 9474 ThenRCG(CGF); 9475 } 9476 } else { 9477 RegionCodeGenTy ElseRCG(TargetElseGen); 9478 ElseRCG(CGF); 9479 } 9480 } 9481 9482 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9483 StringRef ParentName) { 9484 if (!S) 9485 return; 9486 9487 // Codegen OMP target directives that offload compute to the device. 9488 bool RequiresDeviceCodegen = 9489 isa<OMPExecutableDirective>(S) && 9490 isOpenMPTargetExecutionDirective( 9491 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9492 9493 if (RequiresDeviceCodegen) { 9494 const auto &E = *cast<OMPExecutableDirective>(S); 9495 unsigned DeviceID; 9496 unsigned FileID; 9497 unsigned Line; 9498 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9499 FileID, Line); 9500 9501 // Is this a target region that should not be emitted as an entry point? If 9502 // so just signal we are done with this target region. 9503 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9504 ParentName, Line)) 9505 return; 9506 9507 switch (E.getDirectiveKind()) { 9508 case OMPD_target: 9509 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9510 cast<OMPTargetDirective>(E)); 9511 break; 9512 case OMPD_target_parallel: 9513 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9514 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9515 break; 9516 case OMPD_target_teams: 9517 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9518 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9519 break; 9520 case OMPD_target_teams_distribute: 9521 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9522 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9523 break; 9524 case OMPD_target_teams_distribute_simd: 9525 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9526 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9527 break; 9528 case OMPD_target_parallel_for: 9529 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9530 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9531 break; 9532 case OMPD_target_parallel_for_simd: 9533 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9534 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9535 break; 9536 case OMPD_target_simd: 9537 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9538 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9539 break; 9540 case OMPD_target_teams_distribute_parallel_for: 9541 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9542 CGM, ParentName, 9543 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9544 break; 9545 case OMPD_target_teams_distribute_parallel_for_simd: 9546 CodeGenFunction:: 9547 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9548 CGM, ParentName, 9549 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9550 break; 9551 case OMPD_parallel: 9552 case OMPD_for: 9553 case OMPD_parallel_for: 9554 case OMPD_parallel_master: 9555 case OMPD_parallel_sections: 9556 case OMPD_for_simd: 9557 case OMPD_parallel_for_simd: 9558 case OMPD_cancel: 9559 case OMPD_cancellation_point: 9560 case OMPD_ordered: 9561 case OMPD_threadprivate: 9562 case OMPD_allocate: 9563 case OMPD_task: 9564 case OMPD_simd: 9565 case OMPD_sections: 9566 case OMPD_section: 9567 case OMPD_single: 9568 case OMPD_master: 9569 case OMPD_critical: 9570 case OMPD_taskyield: 9571 case OMPD_barrier: 9572 case OMPD_taskwait: 9573 case OMPD_taskgroup: 9574 case OMPD_atomic: 9575 case OMPD_flush: 9576 case OMPD_teams: 9577 case OMPD_target_data: 9578 case OMPD_target_exit_data: 9579 case OMPD_target_enter_data: 9580 case OMPD_distribute: 9581 case OMPD_distribute_simd: 9582 case OMPD_distribute_parallel_for: 9583 case OMPD_distribute_parallel_for_simd: 9584 case OMPD_teams_distribute: 9585 case OMPD_teams_distribute_simd: 9586 case OMPD_teams_distribute_parallel_for: 9587 case OMPD_teams_distribute_parallel_for_simd: 9588 case OMPD_target_update: 9589 case OMPD_declare_simd: 9590 case OMPD_declare_variant: 9591 case OMPD_declare_target: 9592 case OMPD_end_declare_target: 9593 case OMPD_declare_reduction: 9594 case OMPD_declare_mapper: 9595 case OMPD_taskloop: 9596 case OMPD_taskloop_simd: 9597 case OMPD_master_taskloop: 9598 case OMPD_master_taskloop_simd: 9599 case OMPD_parallel_master_taskloop: 9600 case OMPD_parallel_master_taskloop_simd: 9601 case OMPD_requires: 9602 case OMPD_unknown: 9603 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9604 } 9605 return; 9606 } 9607 9608 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9609 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9610 return; 9611 9612 scanForTargetRegionsFunctions( 9613 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9614 return; 9615 } 9616 9617 // If this is a lambda function, look into its body. 9618 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9619 S = L->getBody(); 9620 9621 // Keep looking for target regions recursively. 9622 for (const Stmt *II : S->children()) 9623 scanForTargetRegionsFunctions(II, ParentName); 9624 } 9625 9626 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9627 // If emitting code for the host, we do not process FD here. Instead we do 9628 // the normal code generation. 9629 if (!CGM.getLangOpts().OpenMPIsDevice) { 9630 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9631 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9632 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9633 // Do not emit device_type(nohost) functions for the host. 9634 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9635 return true; 9636 } 9637 return false; 9638 } 9639 9640 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9641 StringRef Name = CGM.getMangledName(GD); 9642 // Try to detect target regions in the function. 9643 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9644 scanForTargetRegionsFunctions(FD->getBody(), Name); 9645 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9646 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9647 // Do not emit device_type(nohost) functions for the host. 9648 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9649 return true; 9650 } 9651 9652 // Do not to emit function if it is not marked as declare target. 9653 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9654 AlreadyEmittedTargetFunctions.count(Name) == 0; 9655 } 9656 9657 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9658 if (!CGM.getLangOpts().OpenMPIsDevice) 9659 return false; 9660 9661 // Check if there are Ctors/Dtors in this declaration and look for target 9662 // regions in it. We use the complete variant to produce the kernel name 9663 // mangling. 9664 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9665 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9666 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9667 StringRef ParentName = 9668 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9669 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9670 } 9671 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9672 StringRef ParentName = 9673 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9674 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9675 } 9676 } 9677 9678 // Do not to emit variable if it is not marked as declare target. 9679 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9680 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9681 cast<VarDecl>(GD.getDecl())); 9682 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9683 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9684 HasRequiresUnifiedSharedMemory)) { 9685 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9686 return true; 9687 } 9688 return false; 9689 } 9690 9691 llvm::Constant * 9692 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9693 const VarDecl *VD) { 9694 assert(VD->getType().isConstant(CGM.getContext()) && 9695 "Expected constant variable."); 9696 StringRef VarName; 9697 llvm::Constant *Addr; 9698 llvm::GlobalValue::LinkageTypes Linkage; 9699 QualType Ty = VD->getType(); 9700 SmallString<128> Buffer; 9701 { 9702 unsigned DeviceID; 9703 unsigned FileID; 9704 unsigned Line; 9705 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9706 FileID, Line); 9707 llvm::raw_svector_ostream OS(Buffer); 9708 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9709 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9710 VarName = OS.str(); 9711 } 9712 Linkage = llvm::GlobalValue::InternalLinkage; 9713 Addr = 9714 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9715 getDefaultFirstprivateAddressSpace()); 9716 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9717 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9718 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9719 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9720 VarName, Addr, VarSize, 9721 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9722 return Addr; 9723 } 9724 9725 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9726 llvm::Constant *Addr) { 9727 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9728 !CGM.getLangOpts().OpenMPIsDevice) 9729 return; 9730 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9731 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9732 if (!Res) { 9733 if (CGM.getLangOpts().OpenMPIsDevice) { 9734 // Register non-target variables being emitted in device code (debug info 9735 // may cause this). 9736 StringRef VarName = CGM.getMangledName(VD); 9737 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9738 } 9739 return; 9740 } 9741 // Register declare target variables. 9742 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9743 StringRef VarName; 9744 CharUnits VarSize; 9745 llvm::GlobalValue::LinkageTypes Linkage; 9746 9747 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9748 !HasRequiresUnifiedSharedMemory) { 9749 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9750 VarName = CGM.getMangledName(VD); 9751 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9752 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9753 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9754 } else { 9755 VarSize = CharUnits::Zero(); 9756 } 9757 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9758 // Temp solution to prevent optimizations of the internal variables. 9759 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9760 std::string RefName = getName({VarName, "ref"}); 9761 if (!CGM.GetGlobalValue(RefName)) { 9762 llvm::Constant *AddrRef = 9763 getOrCreateInternalVariable(Addr->getType(), RefName); 9764 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9765 GVAddrRef->setConstant(/*Val=*/true); 9766 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9767 GVAddrRef->setInitializer(Addr); 9768 CGM.addCompilerUsedGlobal(GVAddrRef); 9769 } 9770 } 9771 } else { 9772 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9773 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9774 HasRequiresUnifiedSharedMemory)) && 9775 "Declare target attribute must link or to with unified memory."); 9776 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9777 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9778 else 9779 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9780 9781 if (CGM.getLangOpts().OpenMPIsDevice) { 9782 VarName = Addr->getName(); 9783 Addr = nullptr; 9784 } else { 9785 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9786 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9787 } 9788 VarSize = CGM.getPointerSize(); 9789 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9790 } 9791 9792 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9793 VarName, Addr, VarSize, Flags, Linkage); 9794 } 9795 9796 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9797 if (isa<FunctionDecl>(GD.getDecl()) || 9798 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9799 return emitTargetFunctions(GD); 9800 9801 return emitTargetGlobalVariable(GD); 9802 } 9803 9804 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9805 for (const VarDecl *VD : DeferredGlobalVariables) { 9806 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9807 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9808 if (!Res) 9809 continue; 9810 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9811 !HasRequiresUnifiedSharedMemory) { 9812 CGM.EmitGlobal(VD); 9813 } else { 9814 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9815 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9816 HasRequiresUnifiedSharedMemory)) && 9817 "Expected link clause or to clause with unified memory."); 9818 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9819 } 9820 } 9821 } 9822 9823 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9824 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9825 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9826 " Expected target-based directive."); 9827 } 9828 9829 void CGOpenMPRuntime::checkArchForUnifiedAddressing( 9830 const OMPRequiresDecl *D) { 9831 for (const OMPClause *Clause : D->clauselists()) { 9832 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9833 HasRequiresUnifiedSharedMemory = true; 9834 break; 9835 } 9836 } 9837 } 9838 9839 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9840 LangAS &AS) { 9841 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9842 return false; 9843 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9844 switch(A->getAllocatorType()) { 9845 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9846 // Not supported, fallback to the default mem space. 9847 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9848 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9849 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9850 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9851 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9852 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9853 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9854 AS = LangAS::Default; 9855 return true; 9856 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9857 llvm_unreachable("Expected predefined allocator for the variables with the " 9858 "static storage."); 9859 } 9860 return false; 9861 } 9862 9863 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9864 return HasRequiresUnifiedSharedMemory; 9865 } 9866 9867 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9868 CodeGenModule &CGM) 9869 : CGM(CGM) { 9870 if (CGM.getLangOpts().OpenMPIsDevice) { 9871 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9872 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9873 } 9874 } 9875 9876 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9877 if (CGM.getLangOpts().OpenMPIsDevice) 9878 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9879 } 9880 9881 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9882 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9883 return true; 9884 9885 StringRef Name = CGM.getMangledName(GD); 9886 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9887 // Do not to emit function if it is marked as declare target as it was already 9888 // emitted. 9889 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9890 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) { 9891 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name))) 9892 return !F->isDeclaration(); 9893 return false; 9894 } 9895 return true; 9896 } 9897 9898 return !AlreadyEmittedTargetFunctions.insert(Name).second; 9899 } 9900 9901 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9902 // If we don't have entries or if we are emitting code for the device, we 9903 // don't need to do anything. 9904 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9905 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9906 (OffloadEntriesInfoManager.empty() && 9907 !HasEmittedDeclareTargetRegion && 9908 !HasEmittedTargetRegion)) 9909 return nullptr; 9910 9911 // Create and register the function that handles the requires directives. 9912 ASTContext &C = CGM.getContext(); 9913 9914 llvm::Function *RequiresRegFn; 9915 { 9916 CodeGenFunction CGF(CGM); 9917 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9918 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9919 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9920 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9921 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9922 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9923 // TODO: check for other requires clauses. 9924 // The requires directive takes effect only when a target region is 9925 // present in the compilation unit. Otherwise it is ignored and not 9926 // passed to the runtime. This avoids the runtime from throwing an error 9927 // for mismatching requires clauses across compilation units that don't 9928 // contain at least 1 target region. 9929 assert((HasEmittedTargetRegion || 9930 HasEmittedDeclareTargetRegion || 9931 !OffloadEntriesInfoManager.empty()) && 9932 "Target or declare target region expected."); 9933 if (HasRequiresUnifiedSharedMemory) 9934 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9935 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 9936 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9937 CGF.FinishFunction(); 9938 } 9939 return RequiresRegFn; 9940 } 9941 9942 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9943 const OMPExecutableDirective &D, 9944 SourceLocation Loc, 9945 llvm::Function *OutlinedFn, 9946 ArrayRef<llvm::Value *> CapturedVars) { 9947 if (!CGF.HaveInsertPoint()) 9948 return; 9949 9950 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9951 CodeGenFunction::RunCleanupsScope Scope(CGF); 9952 9953 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9954 llvm::Value *Args[] = { 9955 RTLoc, 9956 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9957 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9958 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9959 RealArgs.append(std::begin(Args), std::end(Args)); 9960 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9961 9962 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 9963 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9964 } 9965 9966 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9967 const Expr *NumTeams, 9968 const Expr *ThreadLimit, 9969 SourceLocation Loc) { 9970 if (!CGF.HaveInsertPoint()) 9971 return; 9972 9973 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9974 9975 llvm::Value *NumTeamsVal = 9976 NumTeams 9977 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9978 CGF.CGM.Int32Ty, /* isSigned = */ true) 9979 : CGF.Builder.getInt32(0); 9980 9981 llvm::Value *ThreadLimitVal = 9982 ThreadLimit 9983 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 9984 CGF.CGM.Int32Ty, /* isSigned = */ true) 9985 : CGF.Builder.getInt32(0); 9986 9987 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 9988 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 9989 ThreadLimitVal}; 9990 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 9991 PushNumTeamsArgs); 9992 } 9993 9994 void CGOpenMPRuntime::emitTargetDataCalls( 9995 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 9996 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 9997 if (!CGF.HaveInsertPoint()) 9998 return; 9999 10000 // Action used to replace the default codegen action and turn privatization 10001 // off. 10002 PrePostActionTy NoPrivAction; 10003 10004 // Generate the code for the opening of the data environment. Capture all the 10005 // arguments of the runtime call by reference because they are used in the 10006 // closing of the region. 10007 auto &&BeginThenGen = [this, &D, Device, &Info, 10008 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 10009 // Fill up the arrays with all the mapped variables. 10010 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10011 MappableExprsHandler::MapValuesArrayTy Pointers; 10012 MappableExprsHandler::MapValuesArrayTy Sizes; 10013 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10014 10015 // Get map clause information. 10016 MappableExprsHandler MCHandler(D, CGF); 10017 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10018 10019 // Fill up the arrays and create the arguments. 10020 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10021 10022 llvm::Value *BasePointersArrayArg = nullptr; 10023 llvm::Value *PointersArrayArg = nullptr; 10024 llvm::Value *SizesArrayArg = nullptr; 10025 llvm::Value *MapTypesArrayArg = nullptr; 10026 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10027 SizesArrayArg, MapTypesArrayArg, Info); 10028 10029 // Emit device ID if any. 10030 llvm::Value *DeviceID = nullptr; 10031 if (Device) { 10032 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10033 CGF.Int64Ty, /*isSigned=*/true); 10034 } else { 10035 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10036 } 10037 10038 // Emit the number of elements in the offloading arrays. 10039 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10040 10041 llvm::Value *OffloadingArgs[] = { 10042 DeviceID, PointerNum, BasePointersArrayArg, 10043 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10044 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 10045 OffloadingArgs); 10046 10047 // If device pointer privatization is required, emit the body of the region 10048 // here. It will have to be duplicated: with and without privatization. 10049 if (!Info.CaptureDeviceAddrMap.empty()) 10050 CodeGen(CGF); 10051 }; 10052 10053 // Generate code for the closing of the data region. 10054 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10055 PrePostActionTy &) { 10056 assert(Info.isValid() && "Invalid data environment closing arguments."); 10057 10058 llvm::Value *BasePointersArrayArg = nullptr; 10059 llvm::Value *PointersArrayArg = nullptr; 10060 llvm::Value *SizesArrayArg = nullptr; 10061 llvm::Value *MapTypesArrayArg = nullptr; 10062 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10063 SizesArrayArg, MapTypesArrayArg, Info); 10064 10065 // Emit device ID if any. 10066 llvm::Value *DeviceID = nullptr; 10067 if (Device) { 10068 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10069 CGF.Int64Ty, /*isSigned=*/true); 10070 } else { 10071 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10072 } 10073 10074 // Emit the number of elements in the offloading arrays. 10075 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10076 10077 llvm::Value *OffloadingArgs[] = { 10078 DeviceID, PointerNum, BasePointersArrayArg, 10079 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10080 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10081 OffloadingArgs); 10082 }; 10083 10084 // If we need device pointer privatization, we need to emit the body of the 10085 // region with no privatization in the 'else' branch of the conditional. 10086 // Otherwise, we don't have to do anything. 10087 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10088 PrePostActionTy &) { 10089 if (!Info.CaptureDeviceAddrMap.empty()) { 10090 CodeGen.setAction(NoPrivAction); 10091 CodeGen(CGF); 10092 } 10093 }; 10094 10095 // We don't have to do anything to close the region if the if clause evaluates 10096 // to false. 10097 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10098 10099 if (IfCond) { 10100 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10101 } else { 10102 RegionCodeGenTy RCG(BeginThenGen); 10103 RCG(CGF); 10104 } 10105 10106 // If we don't require privatization of device pointers, we emit the body in 10107 // between the runtime calls. This avoids duplicating the body code. 10108 if (Info.CaptureDeviceAddrMap.empty()) { 10109 CodeGen.setAction(NoPrivAction); 10110 CodeGen(CGF); 10111 } 10112 10113 if (IfCond) { 10114 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10115 } else { 10116 RegionCodeGenTy RCG(EndThenGen); 10117 RCG(CGF); 10118 } 10119 } 10120 10121 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10122 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10123 const Expr *Device) { 10124 if (!CGF.HaveInsertPoint()) 10125 return; 10126 10127 assert((isa<OMPTargetEnterDataDirective>(D) || 10128 isa<OMPTargetExitDataDirective>(D) || 10129 isa<OMPTargetUpdateDirective>(D)) && 10130 "Expecting either target enter, exit data, or update directives."); 10131 10132 CodeGenFunction::OMPTargetDataInfo InputInfo; 10133 llvm::Value *MapTypesArray = nullptr; 10134 // Generate the code for the opening of the data environment. 10135 auto &&ThenGen = [this, &D, Device, &InputInfo, 10136 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10137 // Emit device ID if any. 10138 llvm::Value *DeviceID = nullptr; 10139 if (Device) { 10140 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10141 CGF.Int64Ty, /*isSigned=*/true); 10142 } else { 10143 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10144 } 10145 10146 // Emit the number of elements in the offloading arrays. 10147 llvm::Constant *PointerNum = 10148 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10149 10150 llvm::Value *OffloadingArgs[] = {DeviceID, 10151 PointerNum, 10152 InputInfo.BasePointersArray.getPointer(), 10153 InputInfo.PointersArray.getPointer(), 10154 InputInfo.SizesArray.getPointer(), 10155 MapTypesArray}; 10156 10157 // Select the right runtime function call for each expected standalone 10158 // directive. 10159 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10160 OpenMPRTLFunction RTLFn; 10161 switch (D.getDirectiveKind()) { 10162 case OMPD_target_enter_data: 10163 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10164 : OMPRTL__tgt_target_data_begin; 10165 break; 10166 case OMPD_target_exit_data: 10167 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10168 : OMPRTL__tgt_target_data_end; 10169 break; 10170 case OMPD_target_update: 10171 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10172 : OMPRTL__tgt_target_data_update; 10173 break; 10174 case OMPD_parallel: 10175 case OMPD_for: 10176 case OMPD_parallel_for: 10177 case OMPD_parallel_master: 10178 case OMPD_parallel_sections: 10179 case OMPD_for_simd: 10180 case OMPD_parallel_for_simd: 10181 case OMPD_cancel: 10182 case OMPD_cancellation_point: 10183 case OMPD_ordered: 10184 case OMPD_threadprivate: 10185 case OMPD_allocate: 10186 case OMPD_task: 10187 case OMPD_simd: 10188 case OMPD_sections: 10189 case OMPD_section: 10190 case OMPD_single: 10191 case OMPD_master: 10192 case OMPD_critical: 10193 case OMPD_taskyield: 10194 case OMPD_barrier: 10195 case OMPD_taskwait: 10196 case OMPD_taskgroup: 10197 case OMPD_atomic: 10198 case OMPD_flush: 10199 case OMPD_teams: 10200 case OMPD_target_data: 10201 case OMPD_distribute: 10202 case OMPD_distribute_simd: 10203 case OMPD_distribute_parallel_for: 10204 case OMPD_distribute_parallel_for_simd: 10205 case OMPD_teams_distribute: 10206 case OMPD_teams_distribute_simd: 10207 case OMPD_teams_distribute_parallel_for: 10208 case OMPD_teams_distribute_parallel_for_simd: 10209 case OMPD_declare_simd: 10210 case OMPD_declare_variant: 10211 case OMPD_declare_target: 10212 case OMPD_end_declare_target: 10213 case OMPD_declare_reduction: 10214 case OMPD_declare_mapper: 10215 case OMPD_taskloop: 10216 case OMPD_taskloop_simd: 10217 case OMPD_master_taskloop: 10218 case OMPD_master_taskloop_simd: 10219 case OMPD_parallel_master_taskloop: 10220 case OMPD_parallel_master_taskloop_simd: 10221 case OMPD_target: 10222 case OMPD_target_simd: 10223 case OMPD_target_teams_distribute: 10224 case OMPD_target_teams_distribute_simd: 10225 case OMPD_target_teams_distribute_parallel_for: 10226 case OMPD_target_teams_distribute_parallel_for_simd: 10227 case OMPD_target_teams: 10228 case OMPD_target_parallel: 10229 case OMPD_target_parallel_for: 10230 case OMPD_target_parallel_for_simd: 10231 case OMPD_requires: 10232 case OMPD_unknown: 10233 llvm_unreachable("Unexpected standalone target data directive."); 10234 break; 10235 } 10236 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10237 }; 10238 10239 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10240 CodeGenFunction &CGF, PrePostActionTy &) { 10241 // Fill up the arrays with all the mapped variables. 10242 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10243 MappableExprsHandler::MapValuesArrayTy Pointers; 10244 MappableExprsHandler::MapValuesArrayTy Sizes; 10245 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10246 10247 // Get map clause information. 10248 MappableExprsHandler MEHandler(D, CGF); 10249 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10250 10251 TargetDataInfo Info; 10252 // Fill up the arrays and create the arguments. 10253 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10254 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10255 Info.PointersArray, Info.SizesArray, 10256 Info.MapTypesArray, Info); 10257 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10258 InputInfo.BasePointersArray = 10259 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10260 InputInfo.PointersArray = 10261 Address(Info.PointersArray, CGM.getPointerAlign()); 10262 InputInfo.SizesArray = 10263 Address(Info.SizesArray, CGM.getPointerAlign()); 10264 MapTypesArray = Info.MapTypesArray; 10265 if (D.hasClausesOfKind<OMPDependClause>()) 10266 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10267 else 10268 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10269 }; 10270 10271 if (IfCond) { 10272 emitIfClause(CGF, IfCond, TargetThenGen, 10273 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10274 } else { 10275 RegionCodeGenTy ThenRCG(TargetThenGen); 10276 ThenRCG(CGF); 10277 } 10278 } 10279 10280 namespace { 10281 /// Kind of parameter in a function with 'declare simd' directive. 10282 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10283 /// Attribute set of the parameter. 10284 struct ParamAttrTy { 10285 ParamKindTy Kind = Vector; 10286 llvm::APSInt StrideOrArg; 10287 llvm::APSInt Alignment; 10288 }; 10289 } // namespace 10290 10291 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10292 ArrayRef<ParamAttrTy> ParamAttrs) { 10293 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10294 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10295 // of that clause. The VLEN value must be power of 2. 10296 // In other case the notion of the function`s "characteristic data type" (CDT) 10297 // is used to compute the vector length. 10298 // CDT is defined in the following order: 10299 // a) For non-void function, the CDT is the return type. 10300 // b) If the function has any non-uniform, non-linear parameters, then the 10301 // CDT is the type of the first such parameter. 10302 // c) If the CDT determined by a) or b) above is struct, union, or class 10303 // type which is pass-by-value (except for the type that maps to the 10304 // built-in complex data type), the characteristic data type is int. 10305 // d) If none of the above three cases is applicable, the CDT is int. 10306 // The VLEN is then determined based on the CDT and the size of vector 10307 // register of that ISA for which current vector version is generated. The 10308 // VLEN is computed using the formula below: 10309 // VLEN = sizeof(vector_register) / sizeof(CDT), 10310 // where vector register size specified in section 3.2.1 Registers and the 10311 // Stack Frame of original AMD64 ABI document. 10312 QualType RetType = FD->getReturnType(); 10313 if (RetType.isNull()) 10314 return 0; 10315 ASTContext &C = FD->getASTContext(); 10316 QualType CDT; 10317 if (!RetType.isNull() && !RetType->isVoidType()) { 10318 CDT = RetType; 10319 } else { 10320 unsigned Offset = 0; 10321 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10322 if (ParamAttrs[Offset].Kind == Vector) 10323 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10324 ++Offset; 10325 } 10326 if (CDT.isNull()) { 10327 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10328 if (ParamAttrs[I + Offset].Kind == Vector) { 10329 CDT = FD->getParamDecl(I)->getType(); 10330 break; 10331 } 10332 } 10333 } 10334 } 10335 if (CDT.isNull()) 10336 CDT = C.IntTy; 10337 CDT = CDT->getCanonicalTypeUnqualified(); 10338 if (CDT->isRecordType() || CDT->isUnionType()) 10339 CDT = C.IntTy; 10340 return C.getTypeSize(CDT); 10341 } 10342 10343 static void 10344 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10345 const llvm::APSInt &VLENVal, 10346 ArrayRef<ParamAttrTy> ParamAttrs, 10347 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10348 struct ISADataTy { 10349 char ISA; 10350 unsigned VecRegSize; 10351 }; 10352 ISADataTy ISAData[] = { 10353 { 10354 'b', 128 10355 }, // SSE 10356 { 10357 'c', 256 10358 }, // AVX 10359 { 10360 'd', 256 10361 }, // AVX2 10362 { 10363 'e', 512 10364 }, // AVX512 10365 }; 10366 llvm::SmallVector<char, 2> Masked; 10367 switch (State) { 10368 case OMPDeclareSimdDeclAttr::BS_Undefined: 10369 Masked.push_back('N'); 10370 Masked.push_back('M'); 10371 break; 10372 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10373 Masked.push_back('N'); 10374 break; 10375 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10376 Masked.push_back('M'); 10377 break; 10378 } 10379 for (char Mask : Masked) { 10380 for (const ISADataTy &Data : ISAData) { 10381 SmallString<256> Buffer; 10382 llvm::raw_svector_ostream Out(Buffer); 10383 Out << "_ZGV" << Data.ISA << Mask; 10384 if (!VLENVal) { 10385 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10386 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10387 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10388 } else { 10389 Out << VLENVal; 10390 } 10391 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10392 switch (ParamAttr.Kind){ 10393 case LinearWithVarStride: 10394 Out << 's' << ParamAttr.StrideOrArg; 10395 break; 10396 case Linear: 10397 Out << 'l'; 10398 if (!!ParamAttr.StrideOrArg) 10399 Out << ParamAttr.StrideOrArg; 10400 break; 10401 case Uniform: 10402 Out << 'u'; 10403 break; 10404 case Vector: 10405 Out << 'v'; 10406 break; 10407 } 10408 if (!!ParamAttr.Alignment) 10409 Out << 'a' << ParamAttr.Alignment; 10410 } 10411 Out << '_' << Fn->getName(); 10412 Fn->addFnAttr(Out.str()); 10413 } 10414 } 10415 } 10416 10417 // This are the Functions that are needed to mangle the name of the 10418 // vector functions generated by the compiler, according to the rules 10419 // defined in the "Vector Function ABI specifications for AArch64", 10420 // available at 10421 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10422 10423 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10424 /// 10425 /// TODO: Need to implement the behavior for reference marked with a 10426 /// var or no linear modifiers (1.b in the section). For this, we 10427 /// need to extend ParamKindTy to support the linear modifiers. 10428 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10429 QT = QT.getCanonicalType(); 10430 10431 if (QT->isVoidType()) 10432 return false; 10433 10434 if (Kind == ParamKindTy::Uniform) 10435 return false; 10436 10437 if (Kind == ParamKindTy::Linear) 10438 return false; 10439 10440 // TODO: Handle linear references with modifiers 10441 10442 if (Kind == ParamKindTy::LinearWithVarStride) 10443 return false; 10444 10445 return true; 10446 } 10447 10448 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10449 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10450 QT = QT.getCanonicalType(); 10451 unsigned Size = C.getTypeSize(QT); 10452 10453 // Only scalars and complex within 16 bytes wide set PVB to true. 10454 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10455 return false; 10456 10457 if (QT->isFloatingType()) 10458 return true; 10459 10460 if (QT->isIntegerType()) 10461 return true; 10462 10463 if (QT->isPointerType()) 10464 return true; 10465 10466 // TODO: Add support for complex types (section 3.1.2, item 2). 10467 10468 return false; 10469 } 10470 10471 /// Computes the lane size (LS) of a return type or of an input parameter, 10472 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10473 /// TODO: Add support for references, section 3.2.1, item 1. 10474 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10475 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10476 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10477 if (getAArch64PBV(PTy, C)) 10478 return C.getTypeSize(PTy); 10479 } 10480 if (getAArch64PBV(QT, C)) 10481 return C.getTypeSize(QT); 10482 10483 return C.getTypeSize(C.getUIntPtrType()); 10484 } 10485 10486 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10487 // signature of the scalar function, as defined in 3.2.2 of the 10488 // AAVFABI. 10489 static std::tuple<unsigned, unsigned, bool> 10490 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10491 QualType RetType = FD->getReturnType().getCanonicalType(); 10492 10493 ASTContext &C = FD->getASTContext(); 10494 10495 bool OutputBecomesInput = false; 10496 10497 llvm::SmallVector<unsigned, 8> Sizes; 10498 if (!RetType->isVoidType()) { 10499 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10500 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10501 OutputBecomesInput = true; 10502 } 10503 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10504 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10505 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10506 } 10507 10508 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10509 // The LS of a function parameter / return value can only be a power 10510 // of 2, starting from 8 bits, up to 128. 10511 assert(std::all_of(Sizes.begin(), Sizes.end(), 10512 [](unsigned Size) { 10513 return Size == 8 || Size == 16 || Size == 32 || 10514 Size == 64 || Size == 128; 10515 }) && 10516 "Invalid size"); 10517 10518 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10519 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10520 OutputBecomesInput); 10521 } 10522 10523 /// Mangle the parameter part of the vector function name according to 10524 /// their OpenMP classification. The mangling function is defined in 10525 /// section 3.5 of the AAVFABI. 10526 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10527 SmallString<256> Buffer; 10528 llvm::raw_svector_ostream Out(Buffer); 10529 for (const auto &ParamAttr : ParamAttrs) { 10530 switch (ParamAttr.Kind) { 10531 case LinearWithVarStride: 10532 Out << "ls" << ParamAttr.StrideOrArg; 10533 break; 10534 case Linear: 10535 Out << 'l'; 10536 // Don't print the step value if it is not present or if it is 10537 // equal to 1. 10538 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10539 Out << ParamAttr.StrideOrArg; 10540 break; 10541 case Uniform: 10542 Out << 'u'; 10543 break; 10544 case Vector: 10545 Out << 'v'; 10546 break; 10547 } 10548 10549 if (!!ParamAttr.Alignment) 10550 Out << 'a' << ParamAttr.Alignment; 10551 } 10552 10553 return Out.str(); 10554 } 10555 10556 // Function used to add the attribute. The parameter `VLEN` is 10557 // templated to allow the use of "x" when targeting scalable functions 10558 // for SVE. 10559 template <typename T> 10560 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10561 char ISA, StringRef ParSeq, 10562 StringRef MangledName, bool OutputBecomesInput, 10563 llvm::Function *Fn) { 10564 SmallString<256> Buffer; 10565 llvm::raw_svector_ostream Out(Buffer); 10566 Out << Prefix << ISA << LMask << VLEN; 10567 if (OutputBecomesInput) 10568 Out << "v"; 10569 Out << ParSeq << "_" << MangledName; 10570 Fn->addFnAttr(Out.str()); 10571 } 10572 10573 // Helper function to generate the Advanced SIMD names depending on 10574 // the value of the NDS when simdlen is not present. 10575 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10576 StringRef Prefix, char ISA, 10577 StringRef ParSeq, StringRef MangledName, 10578 bool OutputBecomesInput, 10579 llvm::Function *Fn) { 10580 switch (NDS) { 10581 case 8: 10582 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10583 OutputBecomesInput, Fn); 10584 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10585 OutputBecomesInput, Fn); 10586 break; 10587 case 16: 10588 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10589 OutputBecomesInput, Fn); 10590 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10591 OutputBecomesInput, Fn); 10592 break; 10593 case 32: 10594 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10595 OutputBecomesInput, Fn); 10596 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10597 OutputBecomesInput, Fn); 10598 break; 10599 case 64: 10600 case 128: 10601 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10602 OutputBecomesInput, Fn); 10603 break; 10604 default: 10605 llvm_unreachable("Scalar type is too wide."); 10606 } 10607 } 10608 10609 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10610 static void emitAArch64DeclareSimdFunction( 10611 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10612 ArrayRef<ParamAttrTy> ParamAttrs, 10613 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10614 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10615 10616 // Get basic data for building the vector signature. 10617 const auto Data = getNDSWDS(FD, ParamAttrs); 10618 const unsigned NDS = std::get<0>(Data); 10619 const unsigned WDS = std::get<1>(Data); 10620 const bool OutputBecomesInput = std::get<2>(Data); 10621 10622 // Check the values provided via `simdlen` by the user. 10623 // 1. A `simdlen(1)` doesn't produce vector signatures, 10624 if (UserVLEN == 1) { 10625 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10626 DiagnosticsEngine::Warning, 10627 "The clause simdlen(1) has no effect when targeting aarch64."); 10628 CGM.getDiags().Report(SLoc, DiagID); 10629 return; 10630 } 10631 10632 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10633 // Advanced SIMD output. 10634 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10635 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10636 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10637 "power of 2 when targeting Advanced SIMD."); 10638 CGM.getDiags().Report(SLoc, DiagID); 10639 return; 10640 } 10641 10642 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10643 // limits. 10644 if (ISA == 's' && UserVLEN != 0) { 10645 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10646 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10647 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10648 "lanes in the architectural constraints " 10649 "for SVE (min is 128-bit, max is " 10650 "2048-bit, by steps of 128-bit)"); 10651 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10652 return; 10653 } 10654 } 10655 10656 // Sort out parameter sequence. 10657 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10658 StringRef Prefix = "_ZGV"; 10659 // Generate simdlen from user input (if any). 10660 if (UserVLEN) { 10661 if (ISA == 's') { 10662 // SVE generates only a masked function. 10663 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10664 OutputBecomesInput, Fn); 10665 } else { 10666 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10667 // Advanced SIMD generates one or two functions, depending on 10668 // the `[not]inbranch` clause. 10669 switch (State) { 10670 case OMPDeclareSimdDeclAttr::BS_Undefined: 10671 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10672 OutputBecomesInput, Fn); 10673 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10674 OutputBecomesInput, Fn); 10675 break; 10676 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10677 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10678 OutputBecomesInput, Fn); 10679 break; 10680 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10681 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10682 OutputBecomesInput, Fn); 10683 break; 10684 } 10685 } 10686 } else { 10687 // If no user simdlen is provided, follow the AAVFABI rules for 10688 // generating the vector length. 10689 if (ISA == 's') { 10690 // SVE, section 3.4.1, item 1. 10691 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10692 OutputBecomesInput, Fn); 10693 } else { 10694 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10695 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10696 // two vector names depending on the use of the clause 10697 // `[not]inbranch`. 10698 switch (State) { 10699 case OMPDeclareSimdDeclAttr::BS_Undefined: 10700 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10701 OutputBecomesInput, Fn); 10702 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10703 OutputBecomesInput, Fn); 10704 break; 10705 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10706 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10707 OutputBecomesInput, Fn); 10708 break; 10709 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10710 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10711 OutputBecomesInput, Fn); 10712 break; 10713 } 10714 } 10715 } 10716 } 10717 10718 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10719 llvm::Function *Fn) { 10720 ASTContext &C = CGM.getContext(); 10721 FD = FD->getMostRecentDecl(); 10722 // Map params to their positions in function decl. 10723 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10724 if (isa<CXXMethodDecl>(FD)) 10725 ParamPositions.try_emplace(FD, 0); 10726 unsigned ParamPos = ParamPositions.size(); 10727 for (const ParmVarDecl *P : FD->parameters()) { 10728 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10729 ++ParamPos; 10730 } 10731 while (FD) { 10732 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10733 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10734 // Mark uniform parameters. 10735 for (const Expr *E : Attr->uniforms()) { 10736 E = E->IgnoreParenImpCasts(); 10737 unsigned Pos; 10738 if (isa<CXXThisExpr>(E)) { 10739 Pos = ParamPositions[FD]; 10740 } else { 10741 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10742 ->getCanonicalDecl(); 10743 Pos = ParamPositions[PVD]; 10744 } 10745 ParamAttrs[Pos].Kind = Uniform; 10746 } 10747 // Get alignment info. 10748 auto NI = Attr->alignments_begin(); 10749 for (const Expr *E : Attr->aligneds()) { 10750 E = E->IgnoreParenImpCasts(); 10751 unsigned Pos; 10752 QualType ParmTy; 10753 if (isa<CXXThisExpr>(E)) { 10754 Pos = ParamPositions[FD]; 10755 ParmTy = E->getType(); 10756 } else { 10757 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10758 ->getCanonicalDecl(); 10759 Pos = ParamPositions[PVD]; 10760 ParmTy = PVD->getType(); 10761 } 10762 ParamAttrs[Pos].Alignment = 10763 (*NI) 10764 ? (*NI)->EvaluateKnownConstInt(C) 10765 : llvm::APSInt::getUnsigned( 10766 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10767 .getQuantity()); 10768 ++NI; 10769 } 10770 // Mark linear parameters. 10771 auto SI = Attr->steps_begin(); 10772 auto MI = Attr->modifiers_begin(); 10773 for (const Expr *E : Attr->linears()) { 10774 E = E->IgnoreParenImpCasts(); 10775 unsigned Pos; 10776 if (isa<CXXThisExpr>(E)) { 10777 Pos = ParamPositions[FD]; 10778 } else { 10779 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10780 ->getCanonicalDecl(); 10781 Pos = ParamPositions[PVD]; 10782 } 10783 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10784 ParamAttr.Kind = Linear; 10785 if (*SI) { 10786 Expr::EvalResult Result; 10787 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10788 if (const auto *DRE = 10789 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10790 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10791 ParamAttr.Kind = LinearWithVarStride; 10792 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10793 ParamPositions[StridePVD->getCanonicalDecl()]); 10794 } 10795 } 10796 } else { 10797 ParamAttr.StrideOrArg = Result.Val.getInt(); 10798 } 10799 } 10800 ++SI; 10801 ++MI; 10802 } 10803 llvm::APSInt VLENVal; 10804 SourceLocation ExprLoc; 10805 const Expr *VLENExpr = Attr->getSimdlen(); 10806 if (VLENExpr) { 10807 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10808 ExprLoc = VLENExpr->getExprLoc(); 10809 } 10810 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10811 if (CGM.getTriple().getArch() == llvm::Triple::x86 || 10812 CGM.getTriple().getArch() == llvm::Triple::x86_64) { 10813 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10814 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10815 unsigned VLEN = VLENVal.getExtValue(); 10816 StringRef MangledName = Fn->getName(); 10817 if (CGM.getTarget().hasFeature("sve")) 10818 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10819 MangledName, 's', 128, Fn, ExprLoc); 10820 if (CGM.getTarget().hasFeature("neon")) 10821 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10822 MangledName, 'n', 128, Fn, ExprLoc); 10823 } 10824 } 10825 FD = FD->getPreviousDecl(); 10826 } 10827 } 10828 10829 namespace { 10830 /// Cleanup action for doacross support. 10831 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10832 public: 10833 static const int DoacrossFinArgs = 2; 10834 10835 private: 10836 llvm::FunctionCallee RTLFn; 10837 llvm::Value *Args[DoacrossFinArgs]; 10838 10839 public: 10840 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10841 ArrayRef<llvm::Value *> CallArgs) 10842 : RTLFn(RTLFn) { 10843 assert(CallArgs.size() == DoacrossFinArgs); 10844 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10845 } 10846 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10847 if (!CGF.HaveInsertPoint()) 10848 return; 10849 CGF.EmitRuntimeCall(RTLFn, Args); 10850 } 10851 }; 10852 } // namespace 10853 10854 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10855 const OMPLoopDirective &D, 10856 ArrayRef<Expr *> NumIterations) { 10857 if (!CGF.HaveInsertPoint()) 10858 return; 10859 10860 ASTContext &C = CGM.getContext(); 10861 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10862 RecordDecl *RD; 10863 if (KmpDimTy.isNull()) { 10864 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10865 // kmp_int64 lo; // lower 10866 // kmp_int64 up; // upper 10867 // kmp_int64 st; // stride 10868 // }; 10869 RD = C.buildImplicitRecord("kmp_dim"); 10870 RD->startDefinition(); 10871 addFieldToRecordDecl(C, RD, Int64Ty); 10872 addFieldToRecordDecl(C, RD, Int64Ty); 10873 addFieldToRecordDecl(C, RD, Int64Ty); 10874 RD->completeDefinition(); 10875 KmpDimTy = C.getRecordType(RD); 10876 } else { 10877 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10878 } 10879 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10880 QualType ArrayTy = 10881 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 10882 10883 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10884 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10885 enum { LowerFD = 0, UpperFD, StrideFD }; 10886 // Fill dims with data. 10887 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10888 LValue DimsLVal = CGF.MakeAddrLValue( 10889 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10890 // dims.upper = num_iterations; 10891 LValue UpperLVal = CGF.EmitLValueForField( 10892 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10893 llvm::Value *NumIterVal = 10894 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10895 D.getNumIterations()->getType(), Int64Ty, 10896 D.getNumIterations()->getExprLoc()); 10897 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10898 // dims.stride = 1; 10899 LValue StrideLVal = CGF.EmitLValueForField( 10900 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10901 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10902 StrideLVal); 10903 } 10904 10905 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10906 // kmp_int32 num_dims, struct kmp_dim * dims); 10907 llvm::Value *Args[] = { 10908 emitUpdateLocation(CGF, D.getBeginLoc()), 10909 getThreadID(CGF, D.getBeginLoc()), 10910 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10911 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10912 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10913 CGM.VoidPtrTy)}; 10914 10915 llvm::FunctionCallee RTLFn = 10916 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 10917 CGF.EmitRuntimeCall(RTLFn, Args); 10918 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10919 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10920 llvm::FunctionCallee FiniRTLFn = 10921 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 10922 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10923 llvm::makeArrayRef(FiniArgs)); 10924 } 10925 10926 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10927 const OMPDependClause *C) { 10928 QualType Int64Ty = 10929 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10930 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10931 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10932 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 10933 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10934 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10935 const Expr *CounterVal = C->getLoopData(I); 10936 assert(CounterVal); 10937 llvm::Value *CntVal = CGF.EmitScalarConversion( 10938 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10939 CounterVal->getExprLoc()); 10940 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10941 /*Volatile=*/false, Int64Ty); 10942 } 10943 llvm::Value *Args[] = { 10944 emitUpdateLocation(CGF, C->getBeginLoc()), 10945 getThreadID(CGF, C->getBeginLoc()), 10946 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10947 llvm::FunctionCallee RTLFn; 10948 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10949 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 10950 } else { 10951 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10952 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 10953 } 10954 CGF.EmitRuntimeCall(RTLFn, Args); 10955 } 10956 10957 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10958 llvm::FunctionCallee Callee, 10959 ArrayRef<llvm::Value *> Args) const { 10960 assert(Loc.isValid() && "Outlined function call location must be valid."); 10961 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10962 10963 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10964 if (Fn->doesNotThrow()) { 10965 CGF.EmitNounwindRuntimeCall(Fn, Args); 10966 return; 10967 } 10968 } 10969 CGF.EmitRuntimeCall(Callee, Args); 10970 } 10971 10972 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10973 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10974 ArrayRef<llvm::Value *> Args) const { 10975 emitCall(CGF, Loc, OutlinedFn, Args); 10976 } 10977 10978 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10979 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 10980 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 10981 HasEmittedDeclareTargetRegion = true; 10982 } 10983 10984 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 10985 const VarDecl *NativeParam, 10986 const VarDecl *TargetParam) const { 10987 return CGF.GetAddrOfLocalVar(NativeParam); 10988 } 10989 10990 namespace { 10991 /// Cleanup action for allocate support. 10992 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 10993 public: 10994 static const int CleanupArgs = 3; 10995 10996 private: 10997 llvm::FunctionCallee RTLFn; 10998 llvm::Value *Args[CleanupArgs]; 10999 11000 public: 11001 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 11002 ArrayRef<llvm::Value *> CallArgs) 11003 : RTLFn(RTLFn) { 11004 assert(CallArgs.size() == CleanupArgs && 11005 "Size of arguments does not match."); 11006 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 11007 } 11008 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 11009 if (!CGF.HaveInsertPoint()) 11010 return; 11011 CGF.EmitRuntimeCall(RTLFn, Args); 11012 } 11013 }; 11014 } // namespace 11015 11016 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 11017 const VarDecl *VD) { 11018 if (!VD) 11019 return Address::invalid(); 11020 const VarDecl *CVD = VD->getCanonicalDecl(); 11021 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 11022 return Address::invalid(); 11023 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 11024 // Use the default allocation. 11025 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 11026 !AA->getAllocator()) 11027 return Address::invalid(); 11028 llvm::Value *Size; 11029 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 11030 if (CVD->getType()->isVariablyModifiedType()) { 11031 Size = CGF.getTypeSize(CVD->getType()); 11032 // Align the size: ((size + align - 1) / align) * align 11033 Size = CGF.Builder.CreateNUWAdd( 11034 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 11035 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 11036 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 11037 } else { 11038 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 11039 Size = CGM.getSize(Sz.alignTo(Align)); 11040 } 11041 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11042 assert(AA->getAllocator() && 11043 "Expected allocator expression for non-default allocator."); 11044 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11045 // According to the standard, the original allocator type is a enum (integer). 11046 // Convert to pointer type, if required. 11047 if (Allocator->getType()->isIntegerTy()) 11048 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11049 else if (Allocator->getType()->isPointerTy()) 11050 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11051 CGM.VoidPtrTy); 11052 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11053 11054 llvm::Value *Addr = 11055 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11056 CVD->getName() + ".void.addr"); 11057 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11058 Allocator}; 11059 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11060 11061 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11062 llvm::makeArrayRef(FiniArgs)); 11063 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11064 Addr, 11065 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11066 CVD->getName() + ".addr"); 11067 return Address(Addr, Align); 11068 } 11069 11070 namespace { 11071 using OMPContextSelectorData = 11072 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>; 11073 using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>; 11074 } // anonymous namespace 11075 11076 /// Checks current context and returns true if it matches the context selector. 11077 template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx, 11078 typename... Arguments> 11079 static bool checkContext(const OMPContextSelectorData &Data, 11080 Arguments... Params) { 11081 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown && 11082 "Unknown context selector or context selector set."); 11083 return false; 11084 } 11085 11086 /// Checks for implementation={vendor(<vendor>)} context selector. 11087 /// \returns true iff <vendor>="llvm", false otherwise. 11088 template <> 11089 bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>( 11090 const OMPContextSelectorData &Data) { 11091 return llvm::all_of(Data.Names, 11092 [](StringRef S) { return !S.compare_lower("llvm"); }); 11093 } 11094 11095 /// Checks for device={kind(<kind>)} context selector. 11096 /// \returns true if <kind>="host" and compilation is for host. 11097 /// true if <kind>="nohost" and compilation is for device. 11098 /// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU. 11099 /// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN. 11100 /// false otherwise. 11101 template <> 11102 bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>( 11103 const OMPContextSelectorData &Data, CodeGenModule &CGM) { 11104 for (StringRef Name : Data.Names) { 11105 if (!Name.compare_lower("host")) { 11106 if (CGM.getLangOpts().OpenMPIsDevice) 11107 return false; 11108 continue; 11109 } 11110 if (!Name.compare_lower("nohost")) { 11111 if (!CGM.getLangOpts().OpenMPIsDevice) 11112 return false; 11113 continue; 11114 } 11115 switch (CGM.getTriple().getArch()) { 11116 case llvm::Triple::arm: 11117 case llvm::Triple::armeb: 11118 case llvm::Triple::aarch64: 11119 case llvm::Triple::aarch64_be: 11120 case llvm::Triple::aarch64_32: 11121 case llvm::Triple::ppc: 11122 case llvm::Triple::ppc64: 11123 case llvm::Triple::ppc64le: 11124 case llvm::Triple::x86: 11125 case llvm::Triple::x86_64: 11126 if (Name.compare_lower("cpu")) 11127 return false; 11128 break; 11129 case llvm::Triple::amdgcn: 11130 case llvm::Triple::nvptx: 11131 case llvm::Triple::nvptx64: 11132 if (Name.compare_lower("gpu")) 11133 return false; 11134 break; 11135 case llvm::Triple::UnknownArch: 11136 case llvm::Triple::arc: 11137 case llvm::Triple::avr: 11138 case llvm::Triple::bpfel: 11139 case llvm::Triple::bpfeb: 11140 case llvm::Triple::hexagon: 11141 case llvm::Triple::mips: 11142 case llvm::Triple::mipsel: 11143 case llvm::Triple::mips64: 11144 case llvm::Triple::mips64el: 11145 case llvm::Triple::msp430: 11146 case llvm::Triple::r600: 11147 case llvm::Triple::riscv32: 11148 case llvm::Triple::riscv64: 11149 case llvm::Triple::sparc: 11150 case llvm::Triple::sparcv9: 11151 case llvm::Triple::sparcel: 11152 case llvm::Triple::systemz: 11153 case llvm::Triple::tce: 11154 case llvm::Triple::tcele: 11155 case llvm::Triple::thumb: 11156 case llvm::Triple::thumbeb: 11157 case llvm::Triple::xcore: 11158 case llvm::Triple::le32: 11159 case llvm::Triple::le64: 11160 case llvm::Triple::amdil: 11161 case llvm::Triple::amdil64: 11162 case llvm::Triple::hsail: 11163 case llvm::Triple::hsail64: 11164 case llvm::Triple::spir: 11165 case llvm::Triple::spir64: 11166 case llvm::Triple::kalimba: 11167 case llvm::Triple::shave: 11168 case llvm::Triple::lanai: 11169 case llvm::Triple::wasm32: 11170 case llvm::Triple::wasm64: 11171 case llvm::Triple::renderscript32: 11172 case llvm::Triple::renderscript64: 11173 return false; 11174 } 11175 } 11176 return true; 11177 } 11178 11179 bool matchesContext(CodeGenModule &CGM, 11180 const CompleteOMPContextSelectorData &ContextData) { 11181 for (const OMPContextSelectorData &Data : ContextData) { 11182 switch (Data.Ctx) { 11183 case OMP_CTX_vendor: 11184 assert(Data.CtxSet == OMP_CTX_SET_implementation && 11185 "Expected implementation context selector set."); 11186 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data)) 11187 return false; 11188 break; 11189 case OMP_CTX_kind: 11190 assert(Data.CtxSet == OMP_CTX_SET_device && 11191 "Expected device context selector set."); 11192 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data, 11193 CGM)) 11194 return false; 11195 break; 11196 case OMP_CTX_unknown: 11197 llvm_unreachable("Unknown context selector kind."); 11198 } 11199 } 11200 return true; 11201 } 11202 11203 static CompleteOMPContextSelectorData 11204 translateAttrToContextSelectorData(ASTContext &C, 11205 const OMPDeclareVariantAttr *A) { 11206 CompleteOMPContextSelectorData Data; 11207 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) { 11208 Data.emplace_back(); 11209 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( 11210 *std::next(A->ctxSelectorSets_begin(), I)); 11211 auto Ctx = static_cast<OpenMPContextSelectorKind>( 11212 *std::next(A->ctxSelectors_begin(), I)); 11213 Data.back().CtxSet = CtxSet; 11214 Data.back().Ctx = Ctx; 11215 const Expr *Score = *std::next(A->scores_begin(), I); 11216 Data.back().Score = Score->EvaluateKnownConstInt(C); 11217 switch (Ctx) { 11218 case OMP_CTX_vendor: 11219 assert(CtxSet == OMP_CTX_SET_implementation && 11220 "Expected implementation context selector set."); 11221 Data.back().Names = 11222 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end()); 11223 break; 11224 case OMP_CTX_kind: 11225 assert(CtxSet == OMP_CTX_SET_device && 11226 "Expected device context selector set."); 11227 Data.back().Names = 11228 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end()); 11229 break; 11230 case OMP_CTX_unknown: 11231 llvm_unreachable("Unknown context selector kind."); 11232 } 11233 } 11234 return Data; 11235 } 11236 11237 static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS, 11238 const CompleteOMPContextSelectorData &RHS) { 11239 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData; 11240 for (const OMPContextSelectorData &D : RHS) { 11241 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx)); 11242 Pair.getSecond().insert(D.Names.begin(), D.Names.end()); 11243 } 11244 bool AllSetsAreEqual = true; 11245 for (const OMPContextSelectorData &D : LHS) { 11246 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx)); 11247 if (It == RHSData.end()) 11248 return false; 11249 if (D.Names.size() > It->getSecond().size()) 11250 return false; 11251 if (llvm::set_union(It->getSecond(), D.Names)) 11252 return false; 11253 AllSetsAreEqual = 11254 AllSetsAreEqual && (D.Names.size() == It->getSecond().size()); 11255 } 11256 11257 return LHS.size() != RHS.size() || !AllSetsAreEqual; 11258 } 11259 11260 static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS, 11261 const CompleteOMPContextSelectorData &RHS) { 11262 // Score is calculated as sum of all scores + 1. 11263 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11264 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS); 11265 if (RHSIsSubsetOfLHS) { 11266 LHSScore = llvm::APSInt::get(0); 11267 } else { 11268 for (const OMPContextSelectorData &Data : LHS) { 11269 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) { 11270 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11271 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) { 11272 LHSScore += Data.Score.extend(LHSScore.getBitWidth()); 11273 } else { 11274 LHSScore += Data.Score; 11275 } 11276 } 11277 } 11278 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11279 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) { 11280 RHSScore = llvm::APSInt::get(0); 11281 } else { 11282 for (const OMPContextSelectorData &Data : RHS) { 11283 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) { 11284 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11285 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) { 11286 RHSScore += Data.Score.extend(RHSScore.getBitWidth()); 11287 } else { 11288 RHSScore += Data.Score; 11289 } 11290 } 11291 } 11292 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0; 11293 } 11294 11295 /// Finds the variant function that matches current context with its context 11296 /// selector. 11297 static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, 11298 const FunctionDecl *FD) { 11299 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11300 return FD; 11301 // Iterate through all DeclareVariant attributes and check context selectors. 11302 const OMPDeclareVariantAttr *TopMostAttr = nullptr; 11303 CompleteOMPContextSelectorData TopMostData; 11304 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11305 CompleteOMPContextSelectorData Data = 11306 translateAttrToContextSelectorData(CGM.getContext(), A); 11307 if (!matchesContext(CGM, Data)) 11308 continue; 11309 // If the attribute matches the context, find the attribute with the highest 11310 // score. 11311 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) { 11312 TopMostAttr = A; 11313 TopMostData.swap(Data); 11314 } 11315 } 11316 if (!TopMostAttr) 11317 return FD; 11318 return cast<FunctionDecl>( 11319 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) 11320 ->getDecl()); 11321 } 11322 11323 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11324 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11325 // If the original function is defined already, use its definition. 11326 StringRef MangledName = CGM.getMangledName(GD); 11327 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11328 if (Orig && !Orig->isDeclaration()) 11329 return false; 11330 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D); 11331 // Emit original function if it does not have declare variant attribute or the 11332 // context does not match. 11333 if (NewFD == D) 11334 return false; 11335 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11336 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) { 11337 DeferredVariantFunction.erase(D); 11338 return true; 11339 } 11340 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11341 return true; 11342 } 11343 11344 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11345 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11346 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11347 llvm_unreachable("Not supported in SIMD-only mode"); 11348 } 11349 11350 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11351 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11352 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11353 llvm_unreachable("Not supported in SIMD-only mode"); 11354 } 11355 11356 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11357 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11358 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11359 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11360 bool Tied, unsigned &NumberOfParts) { 11361 llvm_unreachable("Not supported in SIMD-only mode"); 11362 } 11363 11364 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11365 SourceLocation Loc, 11366 llvm::Function *OutlinedFn, 11367 ArrayRef<llvm::Value *> CapturedVars, 11368 const Expr *IfCond) { 11369 llvm_unreachable("Not supported in SIMD-only mode"); 11370 } 11371 11372 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11373 CodeGenFunction &CGF, StringRef CriticalName, 11374 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11375 const Expr *Hint) { 11376 llvm_unreachable("Not supported in SIMD-only mode"); 11377 } 11378 11379 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11380 const RegionCodeGenTy &MasterOpGen, 11381 SourceLocation Loc) { 11382 llvm_unreachable("Not supported in SIMD-only mode"); 11383 } 11384 11385 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11386 SourceLocation Loc) { 11387 llvm_unreachable("Not supported in SIMD-only mode"); 11388 } 11389 11390 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11391 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11392 SourceLocation Loc) { 11393 llvm_unreachable("Not supported in SIMD-only mode"); 11394 } 11395 11396 void CGOpenMPSIMDRuntime::emitSingleRegion( 11397 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11398 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11399 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11400 ArrayRef<const Expr *> AssignmentOps) { 11401 llvm_unreachable("Not supported in SIMD-only mode"); 11402 } 11403 11404 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11405 const RegionCodeGenTy &OrderedOpGen, 11406 SourceLocation Loc, 11407 bool IsThreads) { 11408 llvm_unreachable("Not supported in SIMD-only mode"); 11409 } 11410 11411 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11412 SourceLocation Loc, 11413 OpenMPDirectiveKind Kind, 11414 bool EmitChecks, 11415 bool ForceSimpleCall) { 11416 llvm_unreachable("Not supported in SIMD-only mode"); 11417 } 11418 11419 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11420 CodeGenFunction &CGF, SourceLocation Loc, 11421 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11422 bool Ordered, const DispatchRTInput &DispatchValues) { 11423 llvm_unreachable("Not supported in SIMD-only mode"); 11424 } 11425 11426 void CGOpenMPSIMDRuntime::emitForStaticInit( 11427 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11428 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11429 llvm_unreachable("Not supported in SIMD-only mode"); 11430 } 11431 11432 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11433 CodeGenFunction &CGF, SourceLocation Loc, 11434 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11435 llvm_unreachable("Not supported in SIMD-only mode"); 11436 } 11437 11438 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11439 SourceLocation Loc, 11440 unsigned IVSize, 11441 bool IVSigned) { 11442 llvm_unreachable("Not supported in SIMD-only mode"); 11443 } 11444 11445 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11446 SourceLocation Loc, 11447 OpenMPDirectiveKind DKind) { 11448 llvm_unreachable("Not supported in SIMD-only mode"); 11449 } 11450 11451 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11452 SourceLocation Loc, 11453 unsigned IVSize, bool IVSigned, 11454 Address IL, Address LB, 11455 Address UB, Address ST) { 11456 llvm_unreachable("Not supported in SIMD-only mode"); 11457 } 11458 11459 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11460 llvm::Value *NumThreads, 11461 SourceLocation Loc) { 11462 llvm_unreachable("Not supported in SIMD-only mode"); 11463 } 11464 11465 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11466 OpenMPProcBindClauseKind ProcBind, 11467 SourceLocation Loc) { 11468 llvm_unreachable("Not supported in SIMD-only mode"); 11469 } 11470 11471 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11472 const VarDecl *VD, 11473 Address VDAddr, 11474 SourceLocation Loc) { 11475 llvm_unreachable("Not supported in SIMD-only mode"); 11476 } 11477 11478 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11479 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11480 CodeGenFunction *CGF) { 11481 llvm_unreachable("Not supported in SIMD-only mode"); 11482 } 11483 11484 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11485 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11486 llvm_unreachable("Not supported in SIMD-only mode"); 11487 } 11488 11489 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11490 ArrayRef<const Expr *> Vars, 11491 SourceLocation Loc) { 11492 llvm_unreachable("Not supported in SIMD-only mode"); 11493 } 11494 11495 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11496 const OMPExecutableDirective &D, 11497 llvm::Function *TaskFunction, 11498 QualType SharedsTy, Address Shareds, 11499 const Expr *IfCond, 11500 const OMPTaskDataTy &Data) { 11501 llvm_unreachable("Not supported in SIMD-only mode"); 11502 } 11503 11504 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11505 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11506 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11507 const Expr *IfCond, const OMPTaskDataTy &Data) { 11508 llvm_unreachable("Not supported in SIMD-only mode"); 11509 } 11510 11511 void CGOpenMPSIMDRuntime::emitReduction( 11512 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11513 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11514 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11515 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11516 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 11517 ReductionOps, Options); 11518 } 11519 11520 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 11521 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 11522 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 11523 llvm_unreachable("Not supported in SIMD-only mode"); 11524 } 11525 11526 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 11527 SourceLocation Loc, 11528 ReductionCodeGen &RCG, 11529 unsigned N) { 11530 llvm_unreachable("Not supported in SIMD-only mode"); 11531 } 11532 11533 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 11534 SourceLocation Loc, 11535 llvm::Value *ReductionsPtr, 11536 LValue SharedLVal) { 11537 llvm_unreachable("Not supported in SIMD-only mode"); 11538 } 11539 11540 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 11541 SourceLocation Loc) { 11542 llvm_unreachable("Not supported in SIMD-only mode"); 11543 } 11544 11545 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 11546 CodeGenFunction &CGF, SourceLocation Loc, 11547 OpenMPDirectiveKind CancelRegion) { 11548 llvm_unreachable("Not supported in SIMD-only mode"); 11549 } 11550 11551 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 11552 SourceLocation Loc, const Expr *IfCond, 11553 OpenMPDirectiveKind CancelRegion) { 11554 llvm_unreachable("Not supported in SIMD-only mode"); 11555 } 11556 11557 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 11558 const OMPExecutableDirective &D, StringRef ParentName, 11559 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 11560 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 11561 llvm_unreachable("Not supported in SIMD-only mode"); 11562 } 11563 11564 void CGOpenMPSIMDRuntime::emitTargetCall( 11565 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11566 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 11567 const Expr *Device, 11568 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 11569 const OMPLoopDirective &D)> 11570 SizeEmitter) { 11571 llvm_unreachable("Not supported in SIMD-only mode"); 11572 } 11573 11574 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 11575 llvm_unreachable("Not supported in SIMD-only mode"); 11576 } 11577 11578 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 11579 llvm_unreachable("Not supported in SIMD-only mode"); 11580 } 11581 11582 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 11583 return false; 11584 } 11585 11586 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 11587 const OMPExecutableDirective &D, 11588 SourceLocation Loc, 11589 llvm::Function *OutlinedFn, 11590 ArrayRef<llvm::Value *> CapturedVars) { 11591 llvm_unreachable("Not supported in SIMD-only mode"); 11592 } 11593 11594 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11595 const Expr *NumTeams, 11596 const Expr *ThreadLimit, 11597 SourceLocation Loc) { 11598 llvm_unreachable("Not supported in SIMD-only mode"); 11599 } 11600 11601 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 11602 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11603 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11604 llvm_unreachable("Not supported in SIMD-only mode"); 11605 } 11606 11607 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 11608 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11609 const Expr *Device) { 11610 llvm_unreachable("Not supported in SIMD-only mode"); 11611 } 11612 11613 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11614 const OMPLoopDirective &D, 11615 ArrayRef<Expr *> NumIterations) { 11616 llvm_unreachable("Not supported in SIMD-only mode"); 11617 } 11618 11619 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11620 const OMPDependClause *C) { 11621 llvm_unreachable("Not supported in SIMD-only mode"); 11622 } 11623 11624 const VarDecl * 11625 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 11626 const VarDecl *NativeParam) const { 11627 llvm_unreachable("Not supported in SIMD-only mode"); 11628 } 11629 11630 Address 11631 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 11632 const VarDecl *NativeParam, 11633 const VarDecl *TargetParam) const { 11634 llvm_unreachable("Not supported in SIMD-only mode"); 11635 } 11636