1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides a class for OpenMP runtime code generation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGCXXABI.h" 14 #include "CGCleanup.h" 15 #include "CGOpenMPRuntime.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/CodeGen/ConstantInitBuilder.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/StmtOpenMP.h" 21 #include "clang/Basic/BitmaskEnum.h" 22 #include "llvm/ADT/ArrayRef.h" 23 #include "llvm/ADT/SetOperations.h" 24 #include "llvm/Bitcode/BitcodeReader.h" 25 #include "llvm/IR/DerivedTypes.h" 26 #include "llvm/IR/GlobalValue.h" 27 #include "llvm/IR/Value.h" 28 #include "llvm/Support/Format.h" 29 #include "llvm/Support/raw_ostream.h" 30 #include <cassert> 31 32 using namespace clang; 33 using namespace CodeGen; 34 35 namespace { 36 /// Base class for handling code generation inside OpenMP regions. 37 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 38 public: 39 /// Kinds of OpenMP regions used in codegen. 40 enum CGOpenMPRegionKind { 41 /// Region with outlined function for standalone 'parallel' 42 /// directive. 43 ParallelOutlinedRegion, 44 /// Region with outlined function for standalone 'task' directive. 45 TaskOutlinedRegion, 46 /// Region for constructs that do not require function outlining, 47 /// like 'for', 'sections', 'atomic' etc. directives. 48 InlinedRegion, 49 /// Region with outlined function for standalone 'target' directive. 50 TargetRegion, 51 }; 52 53 CGOpenMPRegionInfo(const CapturedStmt &CS, 54 const CGOpenMPRegionKind RegionKind, 55 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 56 bool HasCancel) 57 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 58 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 59 60 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 61 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 62 bool HasCancel) 63 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 64 Kind(Kind), HasCancel(HasCancel) {} 65 66 /// Get a variable or parameter for storing global thread id 67 /// inside OpenMP construct. 68 virtual const VarDecl *getThreadIDVariable() const = 0; 69 70 /// Emit the captured statement body. 71 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 72 73 /// Get an LValue for the current ThreadID variable. 74 /// \return LValue for thread id variable. This LValue always has type int32*. 75 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 76 77 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 78 79 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 80 81 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 82 83 bool hasCancel() const { return HasCancel; } 84 85 static bool classof(const CGCapturedStmtInfo *Info) { 86 return Info->getKind() == CR_OpenMP; 87 } 88 89 ~CGOpenMPRegionInfo() override = default; 90 91 protected: 92 CGOpenMPRegionKind RegionKind; 93 RegionCodeGenTy CodeGen; 94 OpenMPDirectiveKind Kind; 95 bool HasCancel; 96 }; 97 98 /// API for captured statement code generation in OpenMP constructs. 99 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 100 public: 101 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 102 const RegionCodeGenTy &CodeGen, 103 OpenMPDirectiveKind Kind, bool HasCancel, 104 StringRef HelperName) 105 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 106 HasCancel), 107 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 108 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 109 } 110 111 /// Get a variable or parameter for storing global thread id 112 /// inside OpenMP construct. 113 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 114 115 /// Get the name of the capture helper. 116 StringRef getHelperName() const override { return HelperName; } 117 118 static bool classof(const CGCapturedStmtInfo *Info) { 119 return CGOpenMPRegionInfo::classof(Info) && 120 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 121 ParallelOutlinedRegion; 122 } 123 124 private: 125 /// A variable or parameter storing global thread id for OpenMP 126 /// constructs. 127 const VarDecl *ThreadIDVar; 128 StringRef HelperName; 129 }; 130 131 /// API for captured statement code generation in OpenMP constructs. 132 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 133 public: 134 class UntiedTaskActionTy final : public PrePostActionTy { 135 bool Untied; 136 const VarDecl *PartIDVar; 137 const RegionCodeGenTy UntiedCodeGen; 138 llvm::SwitchInst *UntiedSwitch = nullptr; 139 140 public: 141 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 142 const RegionCodeGenTy &UntiedCodeGen) 143 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 144 void Enter(CodeGenFunction &CGF) override { 145 if (Untied) { 146 // Emit task switching point. 147 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 148 CGF.GetAddrOfLocalVar(PartIDVar), 149 PartIDVar->getType()->castAs<PointerType>()); 150 llvm::Value *Res = 151 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 152 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 153 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 154 CGF.EmitBlock(DoneBB); 155 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 156 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 157 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 158 CGF.Builder.GetInsertBlock()); 159 emitUntiedSwitch(CGF); 160 } 161 } 162 void emitUntiedSwitch(CodeGenFunction &CGF) const { 163 if (Untied) { 164 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 165 CGF.GetAddrOfLocalVar(PartIDVar), 166 PartIDVar->getType()->castAs<PointerType>()); 167 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 168 PartIdLVal); 169 UntiedCodeGen(CGF); 170 CodeGenFunction::JumpDest CurPoint = 171 CGF.getJumpDestInCurrentScope(".untied.next."); 172 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 173 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 174 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 175 CGF.Builder.GetInsertBlock()); 176 CGF.EmitBranchThroughCleanup(CurPoint); 177 CGF.EmitBlock(CurPoint.getBlock()); 178 } 179 } 180 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 181 }; 182 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 183 const VarDecl *ThreadIDVar, 184 const RegionCodeGenTy &CodeGen, 185 OpenMPDirectiveKind Kind, bool HasCancel, 186 const UntiedTaskActionTy &Action) 187 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 188 ThreadIDVar(ThreadIDVar), Action(Action) { 189 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 190 } 191 192 /// Get a variable or parameter for storing global thread id 193 /// inside OpenMP construct. 194 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 195 196 /// Get an LValue for the current ThreadID variable. 197 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 198 199 /// Get the name of the capture helper. 200 StringRef getHelperName() const override { return ".omp_outlined."; } 201 202 void emitUntiedSwitch(CodeGenFunction &CGF) override { 203 Action.emitUntiedSwitch(CGF); 204 } 205 206 static bool classof(const CGCapturedStmtInfo *Info) { 207 return CGOpenMPRegionInfo::classof(Info) && 208 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 209 TaskOutlinedRegion; 210 } 211 212 private: 213 /// A variable or parameter storing global thread id for OpenMP 214 /// constructs. 215 const VarDecl *ThreadIDVar; 216 /// Action for emitting code for untied tasks. 217 const UntiedTaskActionTy &Action; 218 }; 219 220 /// API for inlined captured statement code generation in OpenMP 221 /// constructs. 222 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 223 public: 224 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 225 const RegionCodeGenTy &CodeGen, 226 OpenMPDirectiveKind Kind, bool HasCancel) 227 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 228 OldCSI(OldCSI), 229 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 230 231 // Retrieve the value of the context parameter. 232 llvm::Value *getContextValue() const override { 233 if (OuterRegionInfo) 234 return OuterRegionInfo->getContextValue(); 235 llvm_unreachable("No context value for inlined OpenMP region"); 236 } 237 238 void setContextValue(llvm::Value *V) override { 239 if (OuterRegionInfo) { 240 OuterRegionInfo->setContextValue(V); 241 return; 242 } 243 llvm_unreachable("No context value for inlined OpenMP region"); 244 } 245 246 /// Lookup the captured field decl for a variable. 247 const FieldDecl *lookup(const VarDecl *VD) const override { 248 if (OuterRegionInfo) 249 return OuterRegionInfo->lookup(VD); 250 // If there is no outer outlined region,no need to lookup in a list of 251 // captured variables, we can use the original one. 252 return nullptr; 253 } 254 255 FieldDecl *getThisFieldDecl() const override { 256 if (OuterRegionInfo) 257 return OuterRegionInfo->getThisFieldDecl(); 258 return nullptr; 259 } 260 261 /// Get a variable or parameter for storing global thread id 262 /// inside OpenMP construct. 263 const VarDecl *getThreadIDVariable() const override { 264 if (OuterRegionInfo) 265 return OuterRegionInfo->getThreadIDVariable(); 266 return nullptr; 267 } 268 269 /// Get an LValue for the current ThreadID variable. 270 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 271 if (OuterRegionInfo) 272 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 273 llvm_unreachable("No LValue for inlined OpenMP construct"); 274 } 275 276 /// Get the name of the capture helper. 277 StringRef getHelperName() const override { 278 if (auto *OuterRegionInfo = getOldCSI()) 279 return OuterRegionInfo->getHelperName(); 280 llvm_unreachable("No helper name for inlined OpenMP construct"); 281 } 282 283 void emitUntiedSwitch(CodeGenFunction &CGF) override { 284 if (OuterRegionInfo) 285 OuterRegionInfo->emitUntiedSwitch(CGF); 286 } 287 288 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 289 290 static bool classof(const CGCapturedStmtInfo *Info) { 291 return CGOpenMPRegionInfo::classof(Info) && 292 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 293 } 294 295 ~CGOpenMPInlinedRegionInfo() override = default; 296 297 private: 298 /// CodeGen info about outer OpenMP region. 299 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 300 CGOpenMPRegionInfo *OuterRegionInfo; 301 }; 302 303 /// API for captured statement code generation in OpenMP target 304 /// constructs. For this captures, implicit parameters are used instead of the 305 /// captured fields. The name of the target region has to be unique in a given 306 /// application so it is provided by the client, because only the client has 307 /// the information to generate that. 308 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 309 public: 310 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 311 const RegionCodeGenTy &CodeGen, StringRef HelperName) 312 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 313 /*HasCancel=*/false), 314 HelperName(HelperName) {} 315 316 /// This is unused for target regions because each starts executing 317 /// with a single thread. 318 const VarDecl *getThreadIDVariable() const override { return nullptr; } 319 320 /// Get the name of the capture helper. 321 StringRef getHelperName() const override { return HelperName; } 322 323 static bool classof(const CGCapturedStmtInfo *Info) { 324 return CGOpenMPRegionInfo::classof(Info) && 325 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 326 } 327 328 private: 329 StringRef HelperName; 330 }; 331 332 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 333 llvm_unreachable("No codegen for expressions"); 334 } 335 /// API for generation of expressions captured in a innermost OpenMP 336 /// region. 337 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 338 public: 339 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 340 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 341 OMPD_unknown, 342 /*HasCancel=*/false), 343 PrivScope(CGF) { 344 // Make sure the globals captured in the provided statement are local by 345 // using the privatization logic. We assume the same variable is not 346 // captured more than once. 347 for (const auto &C : CS.captures()) { 348 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 349 continue; 350 351 const VarDecl *VD = C.getCapturedVar(); 352 if (VD->isLocalVarDeclOrParm()) 353 continue; 354 355 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 356 /*RefersToEnclosingVariableOrCapture=*/false, 357 VD->getType().getNonReferenceType(), VK_LValue, 358 C.getLocation()); 359 PrivScope.addPrivate( 360 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(); }); 361 } 362 (void)PrivScope.Privatize(); 363 } 364 365 /// Lookup the captured field decl for a variable. 366 const FieldDecl *lookup(const VarDecl *VD) const override { 367 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 368 return FD; 369 return nullptr; 370 } 371 372 /// Emit the captured statement body. 373 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 374 llvm_unreachable("No body for expressions"); 375 } 376 377 /// Get a variable or parameter for storing global thread id 378 /// inside OpenMP construct. 379 const VarDecl *getThreadIDVariable() const override { 380 llvm_unreachable("No thread id for expressions"); 381 } 382 383 /// Get the name of the capture helper. 384 StringRef getHelperName() const override { 385 llvm_unreachable("No helper name for expressions"); 386 } 387 388 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 389 390 private: 391 /// Private scope to capture global variables. 392 CodeGenFunction::OMPPrivateScope PrivScope; 393 }; 394 395 /// RAII for emitting code of OpenMP constructs. 396 class InlinedOpenMPRegionRAII { 397 CodeGenFunction &CGF; 398 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 399 FieldDecl *LambdaThisCaptureField = nullptr; 400 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 401 402 public: 403 /// Constructs region for combined constructs. 404 /// \param CodeGen Code generation sequence for combined directives. Includes 405 /// a list of functions used for code generation of implicitly inlined 406 /// regions. 407 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 408 OpenMPDirectiveKind Kind, bool HasCancel) 409 : CGF(CGF) { 410 // Start emission for the construct. 411 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 412 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 413 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 414 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 415 CGF.LambdaThisCaptureField = nullptr; 416 BlockInfo = CGF.BlockInfo; 417 CGF.BlockInfo = nullptr; 418 } 419 420 ~InlinedOpenMPRegionRAII() { 421 // Restore original CapturedStmtInfo only if we're done with code emission. 422 auto *OldCSI = 423 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 424 delete CGF.CapturedStmtInfo; 425 CGF.CapturedStmtInfo = OldCSI; 426 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 427 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 428 CGF.BlockInfo = BlockInfo; 429 } 430 }; 431 432 /// Values for bit flags used in the ident_t to describe the fields. 433 /// All enumeric elements are named and described in accordance with the code 434 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 435 enum OpenMPLocationFlags : unsigned { 436 /// Use trampoline for internal microtask. 437 OMP_IDENT_IMD = 0x01, 438 /// Use c-style ident structure. 439 OMP_IDENT_KMPC = 0x02, 440 /// Atomic reduction option for kmpc_reduce. 441 OMP_ATOMIC_REDUCE = 0x10, 442 /// Explicit 'barrier' directive. 443 OMP_IDENT_BARRIER_EXPL = 0x20, 444 /// Implicit barrier in code. 445 OMP_IDENT_BARRIER_IMPL = 0x40, 446 /// Implicit barrier in 'for' directive. 447 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 448 /// Implicit barrier in 'sections' directive. 449 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 450 /// Implicit barrier in 'single' directive. 451 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 452 /// Call of __kmp_for_static_init for static loop. 453 OMP_IDENT_WORK_LOOP = 0x200, 454 /// Call of __kmp_for_static_init for sections. 455 OMP_IDENT_WORK_SECTIONS = 0x400, 456 /// Call of __kmp_for_static_init for distribute. 457 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 458 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 459 }; 460 461 namespace { 462 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 463 /// Values for bit flags for marking which requires clauses have been used. 464 enum OpenMPOffloadingRequiresDirFlags : int64_t { 465 /// flag undefined. 466 OMP_REQ_UNDEFINED = 0x000, 467 /// no requires clause present. 468 OMP_REQ_NONE = 0x001, 469 /// reverse_offload clause. 470 OMP_REQ_REVERSE_OFFLOAD = 0x002, 471 /// unified_address clause. 472 OMP_REQ_UNIFIED_ADDRESS = 0x004, 473 /// unified_shared_memory clause. 474 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 475 /// dynamic_allocators clause. 476 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 477 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 478 }; 479 480 enum OpenMPOffloadingReservedDeviceIDs { 481 /// Device ID if the device was not defined, runtime should get it 482 /// from environment variables in the spec. 483 OMP_DEVICEID_UNDEF = -1, 484 }; 485 } // anonymous namespace 486 487 /// Describes ident structure that describes a source location. 488 /// All descriptions are taken from 489 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 490 /// Original structure: 491 /// typedef struct ident { 492 /// kmp_int32 reserved_1; /**< might be used in Fortran; 493 /// see above */ 494 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 495 /// KMP_IDENT_KMPC identifies this union 496 /// member */ 497 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 498 /// see above */ 499 ///#if USE_ITT_BUILD 500 /// /* but currently used for storing 501 /// region-specific ITT */ 502 /// /* contextual information. */ 503 ///#endif /* USE_ITT_BUILD */ 504 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 505 /// C++ */ 506 /// char const *psource; /**< String describing the source location. 507 /// The string is composed of semi-colon separated 508 // fields which describe the source file, 509 /// the function and a pair of line numbers that 510 /// delimit the construct. 511 /// */ 512 /// } ident_t; 513 enum IdentFieldIndex { 514 /// might be used in Fortran 515 IdentField_Reserved_1, 516 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 517 IdentField_Flags, 518 /// Not really used in Fortran any more 519 IdentField_Reserved_2, 520 /// Source[4] in Fortran, do not use for C++ 521 IdentField_Reserved_3, 522 /// String describing the source location. The string is composed of 523 /// semi-colon separated fields which describe the source file, the function 524 /// and a pair of line numbers that delimit the construct. 525 IdentField_PSource 526 }; 527 528 /// Schedule types for 'omp for' loops (these enumerators are taken from 529 /// the enum sched_type in kmp.h). 530 enum OpenMPSchedType { 531 /// Lower bound for default (unordered) versions. 532 OMP_sch_lower = 32, 533 OMP_sch_static_chunked = 33, 534 OMP_sch_static = 34, 535 OMP_sch_dynamic_chunked = 35, 536 OMP_sch_guided_chunked = 36, 537 OMP_sch_runtime = 37, 538 OMP_sch_auto = 38, 539 /// static with chunk adjustment (e.g., simd) 540 OMP_sch_static_balanced_chunked = 45, 541 /// Lower bound for 'ordered' versions. 542 OMP_ord_lower = 64, 543 OMP_ord_static_chunked = 65, 544 OMP_ord_static = 66, 545 OMP_ord_dynamic_chunked = 67, 546 OMP_ord_guided_chunked = 68, 547 OMP_ord_runtime = 69, 548 OMP_ord_auto = 70, 549 OMP_sch_default = OMP_sch_static, 550 /// dist_schedule types 551 OMP_dist_sch_static_chunked = 91, 552 OMP_dist_sch_static = 92, 553 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 554 /// Set if the monotonic schedule modifier was present. 555 OMP_sch_modifier_monotonic = (1 << 29), 556 /// Set if the nonmonotonic schedule modifier was present. 557 OMP_sch_modifier_nonmonotonic = (1 << 30), 558 }; 559 560 enum OpenMPRTLFunction { 561 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 562 /// kmpc_micro microtask, ...); 563 OMPRTL__kmpc_fork_call, 564 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 565 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 566 OMPRTL__kmpc_threadprivate_cached, 567 /// Call to void __kmpc_threadprivate_register( ident_t *, 568 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 569 OMPRTL__kmpc_threadprivate_register, 570 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 571 OMPRTL__kmpc_global_thread_num, 572 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 573 // kmp_critical_name *crit); 574 OMPRTL__kmpc_critical, 575 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 576 // global_tid, kmp_critical_name *crit, uintptr_t hint); 577 OMPRTL__kmpc_critical_with_hint, 578 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 579 // kmp_critical_name *crit); 580 OMPRTL__kmpc_end_critical, 581 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 582 // global_tid); 583 OMPRTL__kmpc_cancel_barrier, 584 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 585 OMPRTL__kmpc_barrier, 586 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 587 OMPRTL__kmpc_for_static_fini, 588 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 589 // global_tid); 590 OMPRTL__kmpc_serialized_parallel, 591 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 592 // global_tid); 593 OMPRTL__kmpc_end_serialized_parallel, 594 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 595 // kmp_int32 num_threads); 596 OMPRTL__kmpc_push_num_threads, 597 // Call to void __kmpc_flush(ident_t *loc); 598 OMPRTL__kmpc_flush, 599 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 600 OMPRTL__kmpc_master, 601 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 602 OMPRTL__kmpc_end_master, 603 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 604 // int end_part); 605 OMPRTL__kmpc_omp_taskyield, 606 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 607 OMPRTL__kmpc_single, 608 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 609 OMPRTL__kmpc_end_single, 610 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 611 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 612 // kmp_routine_entry_t *task_entry); 613 OMPRTL__kmpc_omp_task_alloc, 614 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 615 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 616 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 617 // kmp_int64 device_id); 618 OMPRTL__kmpc_omp_target_task_alloc, 619 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 620 // new_task); 621 OMPRTL__kmpc_omp_task, 622 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 623 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 624 // kmp_int32 didit); 625 OMPRTL__kmpc_copyprivate, 626 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 627 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 628 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 629 OMPRTL__kmpc_reduce, 630 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 631 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 632 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 633 // *lck); 634 OMPRTL__kmpc_reduce_nowait, 635 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 636 // kmp_critical_name *lck); 637 OMPRTL__kmpc_end_reduce, 638 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 639 // kmp_critical_name *lck); 640 OMPRTL__kmpc_end_reduce_nowait, 641 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 642 // kmp_task_t * new_task); 643 OMPRTL__kmpc_omp_task_begin_if0, 644 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 645 // kmp_task_t * new_task); 646 OMPRTL__kmpc_omp_task_complete_if0, 647 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 648 OMPRTL__kmpc_ordered, 649 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 650 OMPRTL__kmpc_end_ordered, 651 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 652 // global_tid); 653 OMPRTL__kmpc_omp_taskwait, 654 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 655 OMPRTL__kmpc_taskgroup, 656 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 657 OMPRTL__kmpc_end_taskgroup, 658 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 659 // int proc_bind); 660 OMPRTL__kmpc_push_proc_bind, 661 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 662 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 663 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 664 OMPRTL__kmpc_omp_task_with_deps, 665 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 666 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 667 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 668 OMPRTL__kmpc_omp_wait_deps, 669 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 670 // global_tid, kmp_int32 cncl_kind); 671 OMPRTL__kmpc_cancellationpoint, 672 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 673 // kmp_int32 cncl_kind); 674 OMPRTL__kmpc_cancel, 675 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 676 // kmp_int32 num_teams, kmp_int32 thread_limit); 677 OMPRTL__kmpc_push_num_teams, 678 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 679 // microtask, ...); 680 OMPRTL__kmpc_fork_teams, 681 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 682 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 683 // sched, kmp_uint64 grainsize, void *task_dup); 684 OMPRTL__kmpc_taskloop, 685 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 686 // num_dims, struct kmp_dim *dims); 687 OMPRTL__kmpc_doacross_init, 688 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 689 OMPRTL__kmpc_doacross_fini, 690 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 691 // *vec); 692 OMPRTL__kmpc_doacross_post, 693 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 694 // *vec); 695 OMPRTL__kmpc_doacross_wait, 696 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 697 // *data); 698 OMPRTL__kmpc_task_reduction_init, 699 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 700 // *d); 701 OMPRTL__kmpc_task_reduction_get_th_data, 702 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 703 OMPRTL__kmpc_alloc, 704 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 705 OMPRTL__kmpc_free, 706 707 // 708 // Offloading related calls 709 // 710 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 711 // size); 712 OMPRTL__kmpc_push_target_tripcount, 713 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 714 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 715 // *arg_types); 716 OMPRTL__tgt_target, 717 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 718 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 719 // *arg_types); 720 OMPRTL__tgt_target_nowait, 721 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 722 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 723 // *arg_types, int32_t num_teams, int32_t thread_limit); 724 OMPRTL__tgt_target_teams, 725 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 726 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 727 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 728 OMPRTL__tgt_target_teams_nowait, 729 // Call to void __tgt_register_requires(int64_t flags); 730 OMPRTL__tgt_register_requires, 731 // Call to void __tgt_register_lib(__tgt_bin_desc *desc); 732 OMPRTL__tgt_register_lib, 733 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); 734 OMPRTL__tgt_unregister_lib, 735 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 736 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 737 OMPRTL__tgt_target_data_begin, 738 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 739 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 740 // *arg_types); 741 OMPRTL__tgt_target_data_begin_nowait, 742 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 743 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 744 OMPRTL__tgt_target_data_end, 745 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 746 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 747 // *arg_types); 748 OMPRTL__tgt_target_data_end_nowait, 749 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 750 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 751 OMPRTL__tgt_target_data_update, 752 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 753 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 754 // *arg_types); 755 OMPRTL__tgt_target_data_update_nowait, 756 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 757 OMPRTL__tgt_mapper_num_components, 758 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 759 // *base, void *begin, int64_t size, int64_t type); 760 OMPRTL__tgt_push_mapper_component, 761 }; 762 763 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 764 /// region. 765 class CleanupTy final : public EHScopeStack::Cleanup { 766 PrePostActionTy *Action; 767 768 public: 769 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 770 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 771 if (!CGF.HaveInsertPoint()) 772 return; 773 Action->Exit(CGF); 774 } 775 }; 776 777 } // anonymous namespace 778 779 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 780 CodeGenFunction::RunCleanupsScope Scope(CGF); 781 if (PrePostAction) { 782 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 783 Callback(CodeGen, CGF, *PrePostAction); 784 } else { 785 PrePostActionTy Action; 786 Callback(CodeGen, CGF, Action); 787 } 788 } 789 790 /// Check if the combiner is a call to UDR combiner and if it is so return the 791 /// UDR decl used for reduction. 792 static const OMPDeclareReductionDecl * 793 getReductionInit(const Expr *ReductionOp) { 794 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 795 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 796 if (const auto *DRE = 797 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 798 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 799 return DRD; 800 return nullptr; 801 } 802 803 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 804 const OMPDeclareReductionDecl *DRD, 805 const Expr *InitOp, 806 Address Private, Address Original, 807 QualType Ty) { 808 if (DRD->getInitializer()) { 809 std::pair<llvm::Function *, llvm::Function *> Reduction = 810 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 811 const auto *CE = cast<CallExpr>(InitOp); 812 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 813 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 814 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 815 const auto *LHSDRE = 816 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 817 const auto *RHSDRE = 818 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 819 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 820 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 821 [=]() { return Private; }); 822 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 823 [=]() { return Original; }); 824 (void)PrivateScope.Privatize(); 825 RValue Func = RValue::get(Reduction.second); 826 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 827 CGF.EmitIgnoredExpr(InitOp); 828 } else { 829 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 830 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 831 auto *GV = new llvm::GlobalVariable( 832 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 833 llvm::GlobalValue::PrivateLinkage, Init, Name); 834 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 835 RValue InitRVal; 836 switch (CGF.getEvaluationKind(Ty)) { 837 case TEK_Scalar: 838 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 839 break; 840 case TEK_Complex: 841 InitRVal = 842 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 843 break; 844 case TEK_Aggregate: 845 InitRVal = RValue::getAggregate(LV.getAddress()); 846 break; 847 } 848 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 849 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 850 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 851 /*IsInitializer=*/false); 852 } 853 } 854 855 /// Emit initialization of arrays of complex types. 856 /// \param DestAddr Address of the array. 857 /// \param Type Type of array. 858 /// \param Init Initial expression of array. 859 /// \param SrcAddr Address of the original array. 860 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 861 QualType Type, bool EmitDeclareReductionInit, 862 const Expr *Init, 863 const OMPDeclareReductionDecl *DRD, 864 Address SrcAddr = Address::invalid()) { 865 // Perform element-by-element initialization. 866 QualType ElementTy; 867 868 // Drill down to the base element type on both arrays. 869 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 870 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 871 DestAddr = 872 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 873 if (DRD) 874 SrcAddr = 875 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 876 877 llvm::Value *SrcBegin = nullptr; 878 if (DRD) 879 SrcBegin = SrcAddr.getPointer(); 880 llvm::Value *DestBegin = DestAddr.getPointer(); 881 // Cast from pointer to array type to pointer to single element. 882 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 883 // The basic structure here is a while-do loop. 884 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 885 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 886 llvm::Value *IsEmpty = 887 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 888 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 889 890 // Enter the loop body, making that address the current address. 891 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 892 CGF.EmitBlock(BodyBB); 893 894 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 895 896 llvm::PHINode *SrcElementPHI = nullptr; 897 Address SrcElementCurrent = Address::invalid(); 898 if (DRD) { 899 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 900 "omp.arraycpy.srcElementPast"); 901 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 902 SrcElementCurrent = 903 Address(SrcElementPHI, 904 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 905 } 906 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 907 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 908 DestElementPHI->addIncoming(DestBegin, EntryBB); 909 Address DestElementCurrent = 910 Address(DestElementPHI, 911 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 912 913 // Emit copy. 914 { 915 CodeGenFunction::RunCleanupsScope InitScope(CGF); 916 if (EmitDeclareReductionInit) { 917 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 918 SrcElementCurrent, ElementTy); 919 } else 920 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 921 /*IsInitializer=*/false); 922 } 923 924 if (DRD) { 925 // Shift the address forward by one element. 926 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 927 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 928 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 929 } 930 931 // Shift the address forward by one element. 932 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 933 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 934 // Check whether we've reached the end. 935 llvm::Value *Done = 936 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 937 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 938 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 939 940 // Done. 941 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 942 } 943 944 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 945 return CGF.EmitOMPSharedLValue(E); 946 } 947 948 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 949 const Expr *E) { 950 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 951 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 952 return LValue(); 953 } 954 955 void ReductionCodeGen::emitAggregateInitialization( 956 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 957 const OMPDeclareReductionDecl *DRD) { 958 // Emit VarDecl with copy init for arrays. 959 // Get the address of the original variable captured in current 960 // captured region. 961 const auto *PrivateVD = 962 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 963 bool EmitDeclareReductionInit = 964 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 965 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 966 EmitDeclareReductionInit, 967 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 968 : PrivateVD->getInit(), 969 DRD, SharedLVal.getAddress()); 970 } 971 972 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 973 ArrayRef<const Expr *> Privates, 974 ArrayRef<const Expr *> ReductionOps) { 975 ClausesData.reserve(Shareds.size()); 976 SharedAddresses.reserve(Shareds.size()); 977 Sizes.reserve(Shareds.size()); 978 BaseDecls.reserve(Shareds.size()); 979 auto IPriv = Privates.begin(); 980 auto IRed = ReductionOps.begin(); 981 for (const Expr *Ref : Shareds) { 982 ClausesData.emplace_back(Ref, *IPriv, *IRed); 983 std::advance(IPriv, 1); 984 std::advance(IRed, 1); 985 } 986 } 987 988 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 989 assert(SharedAddresses.size() == N && 990 "Number of generated lvalues must be exactly N."); 991 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 992 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 993 SharedAddresses.emplace_back(First, Second); 994 } 995 996 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 997 const auto *PrivateVD = 998 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 999 QualType PrivateType = PrivateVD->getType(); 1000 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1001 if (!PrivateType->isVariablyModifiedType()) { 1002 Sizes.emplace_back( 1003 CGF.getTypeSize( 1004 SharedAddresses[N].first.getType().getNonReferenceType()), 1005 nullptr); 1006 return; 1007 } 1008 llvm::Value *Size; 1009 llvm::Value *SizeInChars; 1010 auto *ElemType = 1011 cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType()) 1012 ->getElementType(); 1013 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1014 if (AsArraySection) { 1015 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(), 1016 SharedAddresses[N].first.getPointer()); 1017 Size = CGF.Builder.CreateNUWAdd( 1018 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1019 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1020 } else { 1021 SizeInChars = CGF.getTypeSize( 1022 SharedAddresses[N].first.getType().getNonReferenceType()); 1023 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1024 } 1025 Sizes.emplace_back(SizeInChars, Size); 1026 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1027 CGF, 1028 cast<OpaqueValueExpr>( 1029 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1030 RValue::get(Size)); 1031 CGF.EmitVariablyModifiedType(PrivateType); 1032 } 1033 1034 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1035 llvm::Value *Size) { 1036 const auto *PrivateVD = 1037 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1038 QualType PrivateType = PrivateVD->getType(); 1039 if (!PrivateType->isVariablyModifiedType()) { 1040 assert(!Size && !Sizes[N].second && 1041 "Size should be nullptr for non-variably modified reduction " 1042 "items."); 1043 return; 1044 } 1045 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1046 CGF, 1047 cast<OpaqueValueExpr>( 1048 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1049 RValue::get(Size)); 1050 CGF.EmitVariablyModifiedType(PrivateType); 1051 } 1052 1053 void ReductionCodeGen::emitInitialization( 1054 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1055 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1056 assert(SharedAddresses.size() > N && "No variable was generated"); 1057 const auto *PrivateVD = 1058 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1059 const OMPDeclareReductionDecl *DRD = 1060 getReductionInit(ClausesData[N].ReductionOp); 1061 QualType PrivateType = PrivateVD->getType(); 1062 PrivateAddr = CGF.Builder.CreateElementBitCast( 1063 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1064 QualType SharedType = SharedAddresses[N].first.getType(); 1065 SharedLVal = CGF.MakeAddrLValue( 1066 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(), 1067 CGF.ConvertTypeForMem(SharedType)), 1068 SharedType, SharedAddresses[N].first.getBaseInfo(), 1069 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1070 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1071 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1072 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1073 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1074 PrivateAddr, SharedLVal.getAddress(), 1075 SharedLVal.getType()); 1076 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1077 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1078 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1079 PrivateVD->getType().getQualifiers(), 1080 /*IsInitializer=*/false); 1081 } 1082 } 1083 1084 bool ReductionCodeGen::needCleanups(unsigned N) { 1085 const auto *PrivateVD = 1086 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1087 QualType PrivateType = PrivateVD->getType(); 1088 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1089 return DTorKind != QualType::DK_none; 1090 } 1091 1092 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1093 Address PrivateAddr) { 1094 const auto *PrivateVD = 1095 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1096 QualType PrivateType = PrivateVD->getType(); 1097 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1098 if (needCleanups(N)) { 1099 PrivateAddr = CGF.Builder.CreateElementBitCast( 1100 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1101 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1102 } 1103 } 1104 1105 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1106 LValue BaseLV) { 1107 BaseTy = BaseTy.getNonReferenceType(); 1108 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1109 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1110 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1111 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy); 1112 } else { 1113 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy); 1114 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1115 } 1116 BaseTy = BaseTy->getPointeeType(); 1117 } 1118 return CGF.MakeAddrLValue( 1119 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(), 1120 CGF.ConvertTypeForMem(ElTy)), 1121 BaseLV.getType(), BaseLV.getBaseInfo(), 1122 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1123 } 1124 1125 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1126 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1127 llvm::Value *Addr) { 1128 Address Tmp = Address::invalid(); 1129 Address TopTmp = Address::invalid(); 1130 Address MostTopTmp = Address::invalid(); 1131 BaseTy = BaseTy.getNonReferenceType(); 1132 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1133 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1134 Tmp = CGF.CreateMemTemp(BaseTy); 1135 if (TopTmp.isValid()) 1136 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1137 else 1138 MostTopTmp = Tmp; 1139 TopTmp = Tmp; 1140 BaseTy = BaseTy->getPointeeType(); 1141 } 1142 llvm::Type *Ty = BaseLVType; 1143 if (Tmp.isValid()) 1144 Ty = Tmp.getElementType(); 1145 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1146 if (Tmp.isValid()) { 1147 CGF.Builder.CreateStore(Addr, Tmp); 1148 return MostTopTmp; 1149 } 1150 return Address(Addr, BaseLVAlignment); 1151 } 1152 1153 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1154 const VarDecl *OrigVD = nullptr; 1155 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1156 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1157 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1158 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1159 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1160 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1161 DE = cast<DeclRefExpr>(Base); 1162 OrigVD = cast<VarDecl>(DE->getDecl()); 1163 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1164 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1165 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1166 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1167 DE = cast<DeclRefExpr>(Base); 1168 OrigVD = cast<VarDecl>(DE->getDecl()); 1169 } 1170 return OrigVD; 1171 } 1172 1173 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1174 Address PrivateAddr) { 1175 const DeclRefExpr *DE; 1176 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1177 BaseDecls.emplace_back(OrigVD); 1178 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1179 LValue BaseLValue = 1180 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1181 OriginalBaseLValue); 1182 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1183 BaseLValue.getPointer(), SharedAddresses[N].first.getPointer()); 1184 llvm::Value *PrivatePointer = 1185 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1186 PrivateAddr.getPointer(), 1187 SharedAddresses[N].first.getAddress().getType()); 1188 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1189 return castToBase(CGF, OrigVD->getType(), 1190 SharedAddresses[N].first.getType(), 1191 OriginalBaseLValue.getAddress().getType(), 1192 OriginalBaseLValue.getAlignment(), Ptr); 1193 } 1194 BaseDecls.emplace_back( 1195 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1196 return PrivateAddr; 1197 } 1198 1199 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1200 const OMPDeclareReductionDecl *DRD = 1201 getReductionInit(ClausesData[N].ReductionOp); 1202 return DRD && DRD->getInitializer(); 1203 } 1204 1205 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1206 return CGF.EmitLoadOfPointerLValue( 1207 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1208 getThreadIDVariable()->getType()->castAs<PointerType>()); 1209 } 1210 1211 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1212 if (!CGF.HaveInsertPoint()) 1213 return; 1214 // 1.2.2 OpenMP Language Terminology 1215 // Structured block - An executable statement with a single entry at the 1216 // top and a single exit at the bottom. 1217 // The point of exit cannot be a branch out of the structured block. 1218 // longjmp() and throw() must not violate the entry/exit criteria. 1219 CGF.EHStack.pushTerminate(); 1220 CodeGen(CGF); 1221 CGF.EHStack.popTerminate(); 1222 } 1223 1224 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1225 CodeGenFunction &CGF) { 1226 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1227 getThreadIDVariable()->getType(), 1228 AlignmentSource::Decl); 1229 } 1230 1231 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1232 QualType FieldTy) { 1233 auto *Field = FieldDecl::Create( 1234 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1235 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1236 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1237 Field->setAccess(AS_public); 1238 DC->addDecl(Field); 1239 return Field; 1240 } 1241 1242 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1243 StringRef Separator) 1244 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1245 OffloadEntriesInfoManager(CGM) { 1246 ASTContext &C = CGM.getContext(); 1247 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1248 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1249 RD->startDefinition(); 1250 // reserved_1 1251 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1252 // flags 1253 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1254 // reserved_2 1255 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1256 // reserved_3 1257 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1258 // psource 1259 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1260 RD->completeDefinition(); 1261 IdentQTy = C.getRecordType(RD); 1262 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1263 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1264 1265 loadOffloadInfoMetadata(); 1266 } 1267 1268 bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD, 1269 const GlobalDecl &OldGD, 1270 llvm::GlobalValue *OrigAddr, 1271 bool IsForDefinition) { 1272 // Emit at least a definition for the aliasee if the the address of the 1273 // original function is requested. 1274 if (IsForDefinition || OrigAddr) 1275 (void)CGM.GetAddrOfGlobal(NewGD); 1276 StringRef NewMangledName = CGM.getMangledName(NewGD); 1277 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1278 if (Addr && !Addr->isDeclaration()) { 1279 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1280 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(OldGD); 1281 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1282 1283 // Create a reference to the named value. This ensures that it is emitted 1284 // if a deferred decl. 1285 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1286 1287 // Create the new alias itself, but don't set a name yet. 1288 auto *GA = 1289 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1290 1291 if (OrigAddr) { 1292 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1293 1294 GA->takeName(OrigAddr); 1295 OrigAddr->replaceAllUsesWith( 1296 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1297 OrigAddr->eraseFromParent(); 1298 } else { 1299 GA->setName(CGM.getMangledName(OldGD)); 1300 } 1301 1302 // Set attributes which are particular to an alias; this is a 1303 // specialization of the attributes which may be set on a global function. 1304 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1305 D->isWeakImported()) 1306 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1307 1308 CGM.SetCommonAttributes(OldGD, GA); 1309 return true; 1310 } 1311 return false; 1312 } 1313 1314 void CGOpenMPRuntime::clear() { 1315 InternalVars.clear(); 1316 // Clean non-target variable declarations possibly used only in debug info. 1317 for (const auto &Data : EmittedNonTargetVariables) { 1318 if (!Data.getValue().pointsToAliveValue()) 1319 continue; 1320 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1321 if (!GV) 1322 continue; 1323 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1324 continue; 1325 GV->eraseFromParent(); 1326 } 1327 // Emit aliases for the deferred aliasees. 1328 for (const auto &Pair : DeferredVariantFunction) { 1329 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1330 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1331 // If not able to emit alias, just emit original declaration. 1332 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr, 1333 /*IsForDefinition=*/false); 1334 } 1335 } 1336 1337 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1338 SmallString<128> Buffer; 1339 llvm::raw_svector_ostream OS(Buffer); 1340 StringRef Sep = FirstSeparator; 1341 for (StringRef Part : Parts) { 1342 OS << Sep << Part; 1343 Sep = Separator; 1344 } 1345 return OS.str(); 1346 } 1347 1348 static llvm::Function * 1349 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1350 const Expr *CombinerInitializer, const VarDecl *In, 1351 const VarDecl *Out, bool IsCombiner) { 1352 // void .omp_combiner.(Ty *in, Ty *out); 1353 ASTContext &C = CGM.getContext(); 1354 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1355 FunctionArgList Args; 1356 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1357 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1358 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1359 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1360 Args.push_back(&OmpOutParm); 1361 Args.push_back(&OmpInParm); 1362 const CGFunctionInfo &FnInfo = 1363 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1364 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1365 std::string Name = CGM.getOpenMPRuntime().getName( 1366 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1367 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1368 Name, &CGM.getModule()); 1369 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1370 if (CGM.getLangOpts().Optimize) { 1371 Fn->removeFnAttr(llvm::Attribute::NoInline); 1372 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1373 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1374 } 1375 CodeGenFunction CGF(CGM); 1376 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1377 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1378 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1379 Out->getLocation()); 1380 CodeGenFunction::OMPPrivateScope Scope(CGF); 1381 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1382 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1383 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1384 .getAddress(); 1385 }); 1386 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1387 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1388 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1389 .getAddress(); 1390 }); 1391 (void)Scope.Privatize(); 1392 if (!IsCombiner && Out->hasInit() && 1393 !CGF.isTrivialInitializer(Out->getInit())) { 1394 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1395 Out->getType().getQualifiers(), 1396 /*IsInitializer=*/true); 1397 } 1398 if (CombinerInitializer) 1399 CGF.EmitIgnoredExpr(CombinerInitializer); 1400 Scope.ForceCleanup(); 1401 CGF.FinishFunction(); 1402 return Fn; 1403 } 1404 1405 void CGOpenMPRuntime::emitUserDefinedReduction( 1406 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1407 if (UDRMap.count(D) > 0) 1408 return; 1409 llvm::Function *Combiner = emitCombinerOrInitializer( 1410 CGM, D->getType(), D->getCombiner(), 1411 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1412 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1413 /*IsCombiner=*/true); 1414 llvm::Function *Initializer = nullptr; 1415 if (const Expr *Init = D->getInitializer()) { 1416 Initializer = emitCombinerOrInitializer( 1417 CGM, D->getType(), 1418 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1419 : nullptr, 1420 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1421 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1422 /*IsCombiner=*/false); 1423 } 1424 UDRMap.try_emplace(D, Combiner, Initializer); 1425 if (CGF) { 1426 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1427 Decls.second.push_back(D); 1428 } 1429 } 1430 1431 std::pair<llvm::Function *, llvm::Function *> 1432 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1433 auto I = UDRMap.find(D); 1434 if (I != UDRMap.end()) 1435 return I->second; 1436 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1437 return UDRMap.lookup(D); 1438 } 1439 1440 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1441 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1442 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1443 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1444 assert(ThreadIDVar->getType()->isPointerType() && 1445 "thread id variable must be of type kmp_int32 *"); 1446 CodeGenFunction CGF(CGM, true); 1447 bool HasCancel = false; 1448 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1449 HasCancel = OPD->hasCancel(); 1450 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1451 HasCancel = OPSD->hasCancel(); 1452 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1453 HasCancel = OPFD->hasCancel(); 1454 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1455 HasCancel = OPFD->hasCancel(); 1456 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1457 HasCancel = OPFD->hasCancel(); 1458 else if (const auto *OPFD = 1459 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1460 HasCancel = OPFD->hasCancel(); 1461 else if (const auto *OPFD = 1462 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1463 HasCancel = OPFD->hasCancel(); 1464 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1465 HasCancel, OutlinedHelperName); 1466 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1467 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 1468 } 1469 1470 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1471 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1472 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1473 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1474 return emitParallelOrTeamsOutlinedFunction( 1475 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1476 } 1477 1478 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1479 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1480 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1481 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1482 return emitParallelOrTeamsOutlinedFunction( 1483 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1484 } 1485 1486 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1487 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1488 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1489 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1490 bool Tied, unsigned &NumberOfParts) { 1491 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1492 PrePostActionTy &) { 1493 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1494 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1495 llvm::Value *TaskArgs[] = { 1496 UpLoc, ThreadID, 1497 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1498 TaskTVar->getType()->castAs<PointerType>()) 1499 .getPointer()}; 1500 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1501 }; 1502 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1503 UntiedCodeGen); 1504 CodeGen.setAction(Action); 1505 assert(!ThreadIDVar->getType()->isPointerType() && 1506 "thread id variable must be of type kmp_int32 for tasks"); 1507 const OpenMPDirectiveKind Region = 1508 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1509 : OMPD_task; 1510 const CapturedStmt *CS = D.getCapturedStmt(Region); 1511 const auto *TD = dyn_cast<OMPTaskDirective>(&D); 1512 CodeGenFunction CGF(CGM, true); 1513 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1514 InnermostKind, 1515 TD ? TD->hasCancel() : false, Action); 1516 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1517 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1518 if (!Tied) 1519 NumberOfParts = Action.getNumberOfParts(); 1520 return Res; 1521 } 1522 1523 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1524 const RecordDecl *RD, const CGRecordLayout &RL, 1525 ArrayRef<llvm::Constant *> Data) { 1526 llvm::StructType *StructTy = RL.getLLVMType(); 1527 unsigned PrevIdx = 0; 1528 ConstantInitBuilder CIBuilder(CGM); 1529 auto DI = Data.begin(); 1530 for (const FieldDecl *FD : RD->fields()) { 1531 unsigned Idx = RL.getLLVMFieldNo(FD); 1532 // Fill the alignment. 1533 for (unsigned I = PrevIdx; I < Idx; ++I) 1534 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1535 PrevIdx = Idx + 1; 1536 Fields.add(*DI); 1537 ++DI; 1538 } 1539 } 1540 1541 template <class... As> 1542 static llvm::GlobalVariable * 1543 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1544 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1545 As &&... Args) { 1546 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1547 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1548 ConstantInitBuilder CIBuilder(CGM); 1549 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1550 buildStructValue(Fields, CGM, RD, RL, Data); 1551 return Fields.finishAndCreateGlobal( 1552 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1553 std::forward<As>(Args)...); 1554 } 1555 1556 template <typename T> 1557 static void 1558 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1559 ArrayRef<llvm::Constant *> Data, 1560 T &Parent) { 1561 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1562 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1563 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1564 buildStructValue(Fields, CGM, RD, RL, Data); 1565 Fields.finishAndAddTo(Parent); 1566 } 1567 1568 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1569 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1570 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1571 FlagsTy FlagsKey(Flags, Reserved2Flags); 1572 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1573 if (!Entry) { 1574 if (!DefaultOpenMPPSource) { 1575 // Initialize default location for psource field of ident_t structure of 1576 // all ident_t objects. Format is ";file;function;line;column;;". 1577 // Taken from 1578 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1579 DefaultOpenMPPSource = 1580 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1581 DefaultOpenMPPSource = 1582 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1583 } 1584 1585 llvm::Constant *Data[] = { 1586 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1587 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1588 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1589 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1590 llvm::GlobalValue *DefaultOpenMPLocation = 1591 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1592 llvm::GlobalValue::PrivateLinkage); 1593 DefaultOpenMPLocation->setUnnamedAddr( 1594 llvm::GlobalValue::UnnamedAddr::Global); 1595 1596 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1597 } 1598 return Address(Entry, Align); 1599 } 1600 1601 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1602 bool AtCurrentPoint) { 1603 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1604 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1605 1606 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1607 if (AtCurrentPoint) { 1608 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1609 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1610 } else { 1611 Elem.second.ServiceInsertPt = 1612 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1613 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1614 } 1615 } 1616 1617 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1618 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1619 if (Elem.second.ServiceInsertPt) { 1620 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1621 Elem.second.ServiceInsertPt = nullptr; 1622 Ptr->eraseFromParent(); 1623 } 1624 } 1625 1626 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1627 SourceLocation Loc, 1628 unsigned Flags) { 1629 Flags |= OMP_IDENT_KMPC; 1630 // If no debug info is generated - return global default location. 1631 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1632 Loc.isInvalid()) 1633 return getOrCreateDefaultLocation(Flags).getPointer(); 1634 1635 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1636 1637 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1638 Address LocValue = Address::invalid(); 1639 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1640 if (I != OpenMPLocThreadIDMap.end()) 1641 LocValue = Address(I->second.DebugLoc, Align); 1642 1643 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1644 // GetOpenMPThreadID was called before this routine. 1645 if (!LocValue.isValid()) { 1646 // Generate "ident_t .kmpc_loc.addr;" 1647 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1648 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1649 Elem.second.DebugLoc = AI.getPointer(); 1650 LocValue = AI; 1651 1652 if (!Elem.second.ServiceInsertPt) 1653 setLocThreadIdInsertPt(CGF); 1654 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1655 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1656 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1657 CGF.getTypeSize(IdentQTy)); 1658 } 1659 1660 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1661 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1662 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1663 LValue PSource = 1664 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1665 1666 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1667 if (OMPDebugLoc == nullptr) { 1668 SmallString<128> Buffer2; 1669 llvm::raw_svector_ostream OS2(Buffer2); 1670 // Build debug location 1671 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1672 OS2 << ";" << PLoc.getFilename() << ";"; 1673 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1674 OS2 << FD->getQualifiedNameAsString(); 1675 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1676 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1677 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1678 } 1679 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1680 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1681 1682 // Our callers always pass this to a runtime function, so for 1683 // convenience, go ahead and return a naked pointer. 1684 return LocValue.getPointer(); 1685 } 1686 1687 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1688 SourceLocation Loc) { 1689 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1690 1691 llvm::Value *ThreadID = nullptr; 1692 // Check whether we've already cached a load of the thread id in this 1693 // function. 1694 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1695 if (I != OpenMPLocThreadIDMap.end()) { 1696 ThreadID = I->second.ThreadID; 1697 if (ThreadID != nullptr) 1698 return ThreadID; 1699 } 1700 // If exceptions are enabled, do not use parameter to avoid possible crash. 1701 if (auto *OMPRegionInfo = 1702 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1703 if (OMPRegionInfo->getThreadIDVariable()) { 1704 // Check if this an outlined function with thread id passed as argument. 1705 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1706 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1707 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1708 !CGF.getLangOpts().CXXExceptions || 1709 CGF.Builder.GetInsertBlock() == TopBlock || 1710 !isa<llvm::Instruction>(LVal.getPointer()) || 1711 cast<llvm::Instruction>(LVal.getPointer())->getParent() == TopBlock || 1712 cast<llvm::Instruction>(LVal.getPointer())->getParent() == 1713 CGF.Builder.GetInsertBlock()) { 1714 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1715 // If value loaded in entry block, cache it and use it everywhere in 1716 // function. 1717 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1718 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1719 Elem.second.ThreadID = ThreadID; 1720 } 1721 return ThreadID; 1722 } 1723 } 1724 } 1725 1726 // This is not an outlined function region - need to call __kmpc_int32 1727 // kmpc_global_thread_num(ident_t *loc). 1728 // Generate thread id value and cache this value for use across the 1729 // function. 1730 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1731 if (!Elem.second.ServiceInsertPt) 1732 setLocThreadIdInsertPt(CGF); 1733 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1734 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1735 llvm::CallInst *Call = CGF.Builder.CreateCall( 1736 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1737 emitUpdateLocation(CGF, Loc)); 1738 Call->setCallingConv(CGF.getRuntimeCC()); 1739 Elem.second.ThreadID = Call; 1740 return Call; 1741 } 1742 1743 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1744 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1745 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1746 clearLocThreadIdInsertPt(CGF); 1747 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1748 } 1749 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1750 for(auto *D : FunctionUDRMap[CGF.CurFn]) 1751 UDRMap.erase(D); 1752 FunctionUDRMap.erase(CGF.CurFn); 1753 } 1754 auto I = FunctionUDMMap.find(CGF.CurFn); 1755 if (I != FunctionUDMMap.end()) { 1756 for(auto *D : I->second) 1757 UDMMap.erase(D); 1758 FunctionUDMMap.erase(I); 1759 } 1760 } 1761 1762 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1763 return IdentTy->getPointerTo(); 1764 } 1765 1766 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1767 if (!Kmpc_MicroTy) { 1768 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1769 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1770 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1771 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1772 } 1773 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1774 } 1775 1776 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1777 llvm::FunctionCallee RTLFn = nullptr; 1778 switch (static_cast<OpenMPRTLFunction>(Function)) { 1779 case OMPRTL__kmpc_fork_call: { 1780 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1781 // microtask, ...); 1782 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1783 getKmpc_MicroPointerTy()}; 1784 auto *FnTy = 1785 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1786 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1787 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1788 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1789 llvm::LLVMContext &Ctx = F->getContext(); 1790 llvm::MDBuilder MDB(Ctx); 1791 // Annotate the callback behavior of the __kmpc_fork_call: 1792 // - The callback callee is argument number 2 (microtask). 1793 // - The first two arguments of the callback callee are unknown (-1). 1794 // - All variadic arguments to the __kmpc_fork_call are passed to the 1795 // callback callee. 1796 F->addMetadata( 1797 llvm::LLVMContext::MD_callback, 1798 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1799 2, {-1, -1}, 1800 /* VarArgsArePassed */ true)})); 1801 } 1802 } 1803 break; 1804 } 1805 case OMPRTL__kmpc_global_thread_num: { 1806 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1807 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1808 auto *FnTy = 1809 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1810 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1811 break; 1812 } 1813 case OMPRTL__kmpc_threadprivate_cached: { 1814 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1815 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1816 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1817 CGM.VoidPtrTy, CGM.SizeTy, 1818 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1819 auto *FnTy = 1820 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1821 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1822 break; 1823 } 1824 case OMPRTL__kmpc_critical: { 1825 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1826 // kmp_critical_name *crit); 1827 llvm::Type *TypeParams[] = { 1828 getIdentTyPointerTy(), CGM.Int32Ty, 1829 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1830 auto *FnTy = 1831 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1832 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1833 break; 1834 } 1835 case OMPRTL__kmpc_critical_with_hint: { 1836 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1837 // kmp_critical_name *crit, uintptr_t hint); 1838 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1839 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1840 CGM.IntPtrTy}; 1841 auto *FnTy = 1842 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1843 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1844 break; 1845 } 1846 case OMPRTL__kmpc_threadprivate_register: { 1847 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1848 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1849 // typedef void *(*kmpc_ctor)(void *); 1850 auto *KmpcCtorTy = 1851 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1852 /*isVarArg*/ false)->getPointerTo(); 1853 // typedef void *(*kmpc_cctor)(void *, void *); 1854 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1855 auto *KmpcCopyCtorTy = 1856 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1857 /*isVarArg*/ false) 1858 ->getPointerTo(); 1859 // typedef void (*kmpc_dtor)(void *); 1860 auto *KmpcDtorTy = 1861 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1862 ->getPointerTo(); 1863 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1864 KmpcCopyCtorTy, KmpcDtorTy}; 1865 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1866 /*isVarArg*/ false); 1867 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1868 break; 1869 } 1870 case OMPRTL__kmpc_end_critical: { 1871 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1872 // kmp_critical_name *crit); 1873 llvm::Type *TypeParams[] = { 1874 getIdentTyPointerTy(), CGM.Int32Ty, 1875 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1876 auto *FnTy = 1877 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1878 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1879 break; 1880 } 1881 case OMPRTL__kmpc_cancel_barrier: { 1882 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1883 // global_tid); 1884 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1885 auto *FnTy = 1886 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1887 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1888 break; 1889 } 1890 case OMPRTL__kmpc_barrier: { 1891 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1892 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1893 auto *FnTy = 1894 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1895 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1896 break; 1897 } 1898 case OMPRTL__kmpc_for_static_fini: { 1899 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1900 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1901 auto *FnTy = 1902 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1903 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1904 break; 1905 } 1906 case OMPRTL__kmpc_push_num_threads: { 1907 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1908 // kmp_int32 num_threads) 1909 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1910 CGM.Int32Ty}; 1911 auto *FnTy = 1912 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1913 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1914 break; 1915 } 1916 case OMPRTL__kmpc_serialized_parallel: { 1917 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1918 // global_tid); 1919 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1920 auto *FnTy = 1921 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1922 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1923 break; 1924 } 1925 case OMPRTL__kmpc_end_serialized_parallel: { 1926 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1927 // global_tid); 1928 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1929 auto *FnTy = 1930 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1931 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1932 break; 1933 } 1934 case OMPRTL__kmpc_flush: { 1935 // Build void __kmpc_flush(ident_t *loc); 1936 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1937 auto *FnTy = 1938 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1939 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1940 break; 1941 } 1942 case OMPRTL__kmpc_master: { 1943 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1944 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1945 auto *FnTy = 1946 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1947 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 1948 break; 1949 } 1950 case OMPRTL__kmpc_end_master: { 1951 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 1952 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1953 auto *FnTy = 1954 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1955 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 1956 break; 1957 } 1958 case OMPRTL__kmpc_omp_taskyield: { 1959 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 1960 // int end_part); 1961 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1962 auto *FnTy = 1963 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1964 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 1965 break; 1966 } 1967 case OMPRTL__kmpc_single: { 1968 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 1969 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1970 auto *FnTy = 1971 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1972 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 1973 break; 1974 } 1975 case OMPRTL__kmpc_end_single: { 1976 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 1977 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1978 auto *FnTy = 1979 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1980 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 1981 break; 1982 } 1983 case OMPRTL__kmpc_omp_task_alloc: { 1984 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 1985 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1986 // kmp_routine_entry_t *task_entry); 1987 assert(KmpRoutineEntryPtrTy != nullptr && 1988 "Type kmp_routine_entry_t must be created."); 1989 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1990 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 1991 // Return void * and then cast to particular kmp_task_t type. 1992 auto *FnTy = 1993 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1994 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 1995 break; 1996 } 1997 case OMPRTL__kmpc_omp_target_task_alloc: { 1998 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 1999 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2000 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 2001 assert(KmpRoutineEntryPtrTy != nullptr && 2002 "Type kmp_routine_entry_t must be created."); 2003 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2004 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 2005 CGM.Int64Ty}; 2006 // Return void * and then cast to particular kmp_task_t type. 2007 auto *FnTy = 2008 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2009 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2010 break; 2011 } 2012 case OMPRTL__kmpc_omp_task: { 2013 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2014 // *new_task); 2015 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2016 CGM.VoidPtrTy}; 2017 auto *FnTy = 2018 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2019 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2020 break; 2021 } 2022 case OMPRTL__kmpc_copyprivate: { 2023 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2024 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2025 // kmp_int32 didit); 2026 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2027 auto *CpyFnTy = 2028 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2029 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2030 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2031 CGM.Int32Ty}; 2032 auto *FnTy = 2033 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2034 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2035 break; 2036 } 2037 case OMPRTL__kmpc_reduce: { 2038 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2039 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2040 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2041 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2042 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2043 /*isVarArg=*/false); 2044 llvm::Type *TypeParams[] = { 2045 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2046 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2047 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2048 auto *FnTy = 2049 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2050 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2051 break; 2052 } 2053 case OMPRTL__kmpc_reduce_nowait: { 2054 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2055 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2056 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2057 // *lck); 2058 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2059 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2060 /*isVarArg=*/false); 2061 llvm::Type *TypeParams[] = { 2062 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2063 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2064 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2065 auto *FnTy = 2066 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2067 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2068 break; 2069 } 2070 case OMPRTL__kmpc_end_reduce: { 2071 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2072 // kmp_critical_name *lck); 2073 llvm::Type *TypeParams[] = { 2074 getIdentTyPointerTy(), CGM.Int32Ty, 2075 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2076 auto *FnTy = 2077 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2078 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2079 break; 2080 } 2081 case OMPRTL__kmpc_end_reduce_nowait: { 2082 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2083 // kmp_critical_name *lck); 2084 llvm::Type *TypeParams[] = { 2085 getIdentTyPointerTy(), CGM.Int32Ty, 2086 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2087 auto *FnTy = 2088 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2089 RTLFn = 2090 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2091 break; 2092 } 2093 case OMPRTL__kmpc_omp_task_begin_if0: { 2094 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2095 // *new_task); 2096 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2097 CGM.VoidPtrTy}; 2098 auto *FnTy = 2099 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2100 RTLFn = 2101 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2102 break; 2103 } 2104 case OMPRTL__kmpc_omp_task_complete_if0: { 2105 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2106 // *new_task); 2107 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2108 CGM.VoidPtrTy}; 2109 auto *FnTy = 2110 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2111 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2112 /*Name=*/"__kmpc_omp_task_complete_if0"); 2113 break; 2114 } 2115 case OMPRTL__kmpc_ordered: { 2116 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2117 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2118 auto *FnTy = 2119 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2120 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2121 break; 2122 } 2123 case OMPRTL__kmpc_end_ordered: { 2124 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2125 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2126 auto *FnTy = 2127 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2128 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2129 break; 2130 } 2131 case OMPRTL__kmpc_omp_taskwait: { 2132 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2133 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2134 auto *FnTy = 2135 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2136 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2137 break; 2138 } 2139 case OMPRTL__kmpc_taskgroup: { 2140 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2141 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2142 auto *FnTy = 2143 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2144 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2145 break; 2146 } 2147 case OMPRTL__kmpc_end_taskgroup: { 2148 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2149 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2150 auto *FnTy = 2151 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2152 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2153 break; 2154 } 2155 case OMPRTL__kmpc_push_proc_bind: { 2156 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2157 // int proc_bind) 2158 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2159 auto *FnTy = 2160 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2161 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2162 break; 2163 } 2164 case OMPRTL__kmpc_omp_task_with_deps: { 2165 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2166 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2167 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2168 llvm::Type *TypeParams[] = { 2169 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2170 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2171 auto *FnTy = 2172 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2173 RTLFn = 2174 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2175 break; 2176 } 2177 case OMPRTL__kmpc_omp_wait_deps: { 2178 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2179 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2180 // kmp_depend_info_t *noalias_dep_list); 2181 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2182 CGM.Int32Ty, CGM.VoidPtrTy, 2183 CGM.Int32Ty, CGM.VoidPtrTy}; 2184 auto *FnTy = 2185 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2186 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2187 break; 2188 } 2189 case OMPRTL__kmpc_cancellationpoint: { 2190 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2191 // global_tid, kmp_int32 cncl_kind) 2192 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2193 auto *FnTy = 2194 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2195 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2196 break; 2197 } 2198 case OMPRTL__kmpc_cancel: { 2199 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2200 // kmp_int32 cncl_kind) 2201 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2202 auto *FnTy = 2203 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2204 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2205 break; 2206 } 2207 case OMPRTL__kmpc_push_num_teams: { 2208 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2209 // kmp_int32 num_teams, kmp_int32 num_threads) 2210 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2211 CGM.Int32Ty}; 2212 auto *FnTy = 2213 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2214 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2215 break; 2216 } 2217 case OMPRTL__kmpc_fork_teams: { 2218 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2219 // microtask, ...); 2220 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2221 getKmpc_MicroPointerTy()}; 2222 auto *FnTy = 2223 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2224 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2225 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2226 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2227 llvm::LLVMContext &Ctx = F->getContext(); 2228 llvm::MDBuilder MDB(Ctx); 2229 // Annotate the callback behavior of the __kmpc_fork_teams: 2230 // - The callback callee is argument number 2 (microtask). 2231 // - The first two arguments of the callback callee are unknown (-1). 2232 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2233 // callback callee. 2234 F->addMetadata( 2235 llvm::LLVMContext::MD_callback, 2236 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2237 2, {-1, -1}, 2238 /* VarArgsArePassed */ true)})); 2239 } 2240 } 2241 break; 2242 } 2243 case OMPRTL__kmpc_taskloop: { 2244 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2245 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2246 // sched, kmp_uint64 grainsize, void *task_dup); 2247 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2248 CGM.IntTy, 2249 CGM.VoidPtrTy, 2250 CGM.IntTy, 2251 CGM.Int64Ty->getPointerTo(), 2252 CGM.Int64Ty->getPointerTo(), 2253 CGM.Int64Ty, 2254 CGM.IntTy, 2255 CGM.IntTy, 2256 CGM.Int64Ty, 2257 CGM.VoidPtrTy}; 2258 auto *FnTy = 2259 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2260 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2261 break; 2262 } 2263 case OMPRTL__kmpc_doacross_init: { 2264 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2265 // num_dims, struct kmp_dim *dims); 2266 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2267 CGM.Int32Ty, 2268 CGM.Int32Ty, 2269 CGM.VoidPtrTy}; 2270 auto *FnTy = 2271 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2272 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2273 break; 2274 } 2275 case OMPRTL__kmpc_doacross_fini: { 2276 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2277 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2278 auto *FnTy = 2279 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2280 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2281 break; 2282 } 2283 case OMPRTL__kmpc_doacross_post: { 2284 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2285 // *vec); 2286 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2287 CGM.Int64Ty->getPointerTo()}; 2288 auto *FnTy = 2289 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2290 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2291 break; 2292 } 2293 case OMPRTL__kmpc_doacross_wait: { 2294 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2295 // *vec); 2296 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2297 CGM.Int64Ty->getPointerTo()}; 2298 auto *FnTy = 2299 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2300 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2301 break; 2302 } 2303 case OMPRTL__kmpc_task_reduction_init: { 2304 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2305 // *data); 2306 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2307 auto *FnTy = 2308 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2309 RTLFn = 2310 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2311 break; 2312 } 2313 case OMPRTL__kmpc_task_reduction_get_th_data: { 2314 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2315 // *d); 2316 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2317 auto *FnTy = 2318 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2319 RTLFn = CGM.CreateRuntimeFunction( 2320 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2321 break; 2322 } 2323 case OMPRTL__kmpc_alloc: { 2324 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2325 // al); omp_allocator_handle_t type is void *. 2326 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2327 auto *FnTy = 2328 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2329 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2330 break; 2331 } 2332 case OMPRTL__kmpc_free: { 2333 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2334 // al); omp_allocator_handle_t type is void *. 2335 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2336 auto *FnTy = 2337 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2338 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2339 break; 2340 } 2341 case OMPRTL__kmpc_push_target_tripcount: { 2342 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2343 // size); 2344 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2345 llvm::FunctionType *FnTy = 2346 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2347 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2348 break; 2349 } 2350 case OMPRTL__tgt_target: { 2351 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2352 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2353 // *arg_types); 2354 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2355 CGM.VoidPtrTy, 2356 CGM.Int32Ty, 2357 CGM.VoidPtrPtrTy, 2358 CGM.VoidPtrPtrTy, 2359 CGM.Int64Ty->getPointerTo(), 2360 CGM.Int64Ty->getPointerTo()}; 2361 auto *FnTy = 2362 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2363 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2364 break; 2365 } 2366 case OMPRTL__tgt_target_nowait: { 2367 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2368 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2369 // int64_t *arg_types); 2370 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2371 CGM.VoidPtrTy, 2372 CGM.Int32Ty, 2373 CGM.VoidPtrPtrTy, 2374 CGM.VoidPtrPtrTy, 2375 CGM.Int64Ty->getPointerTo(), 2376 CGM.Int64Ty->getPointerTo()}; 2377 auto *FnTy = 2378 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2379 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2380 break; 2381 } 2382 case OMPRTL__tgt_target_teams: { 2383 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2384 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2385 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2386 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2387 CGM.VoidPtrTy, 2388 CGM.Int32Ty, 2389 CGM.VoidPtrPtrTy, 2390 CGM.VoidPtrPtrTy, 2391 CGM.Int64Ty->getPointerTo(), 2392 CGM.Int64Ty->getPointerTo(), 2393 CGM.Int32Ty, 2394 CGM.Int32Ty}; 2395 auto *FnTy = 2396 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2397 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2398 break; 2399 } 2400 case OMPRTL__tgt_target_teams_nowait: { 2401 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2402 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2403 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2404 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2405 CGM.VoidPtrTy, 2406 CGM.Int32Ty, 2407 CGM.VoidPtrPtrTy, 2408 CGM.VoidPtrPtrTy, 2409 CGM.Int64Ty->getPointerTo(), 2410 CGM.Int64Ty->getPointerTo(), 2411 CGM.Int32Ty, 2412 CGM.Int32Ty}; 2413 auto *FnTy = 2414 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2415 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2416 break; 2417 } 2418 case OMPRTL__tgt_register_requires: { 2419 // Build void __tgt_register_requires(int64_t flags); 2420 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2421 auto *FnTy = 2422 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2423 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2424 break; 2425 } 2426 case OMPRTL__tgt_register_lib: { 2427 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 2428 QualType ParamTy = 2429 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2430 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2431 auto *FnTy = 2432 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2433 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 2434 break; 2435 } 2436 case OMPRTL__tgt_unregister_lib: { 2437 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 2438 QualType ParamTy = 2439 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2440 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2441 auto *FnTy = 2442 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2443 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 2444 break; 2445 } 2446 case OMPRTL__tgt_target_data_begin: { 2447 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2448 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2449 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2450 CGM.Int32Ty, 2451 CGM.VoidPtrPtrTy, 2452 CGM.VoidPtrPtrTy, 2453 CGM.Int64Ty->getPointerTo(), 2454 CGM.Int64Ty->getPointerTo()}; 2455 auto *FnTy = 2456 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2457 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2458 break; 2459 } 2460 case OMPRTL__tgt_target_data_begin_nowait: { 2461 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2462 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2463 // *arg_types); 2464 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2465 CGM.Int32Ty, 2466 CGM.VoidPtrPtrTy, 2467 CGM.VoidPtrPtrTy, 2468 CGM.Int64Ty->getPointerTo(), 2469 CGM.Int64Ty->getPointerTo()}; 2470 auto *FnTy = 2471 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2472 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2473 break; 2474 } 2475 case OMPRTL__tgt_target_data_end: { 2476 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2477 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2478 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2479 CGM.Int32Ty, 2480 CGM.VoidPtrPtrTy, 2481 CGM.VoidPtrPtrTy, 2482 CGM.Int64Ty->getPointerTo(), 2483 CGM.Int64Ty->getPointerTo()}; 2484 auto *FnTy = 2485 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2486 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2487 break; 2488 } 2489 case OMPRTL__tgt_target_data_end_nowait: { 2490 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2491 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2492 // *arg_types); 2493 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2494 CGM.Int32Ty, 2495 CGM.VoidPtrPtrTy, 2496 CGM.VoidPtrPtrTy, 2497 CGM.Int64Ty->getPointerTo(), 2498 CGM.Int64Ty->getPointerTo()}; 2499 auto *FnTy = 2500 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2501 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2502 break; 2503 } 2504 case OMPRTL__tgt_target_data_update: { 2505 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2506 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2507 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2508 CGM.Int32Ty, 2509 CGM.VoidPtrPtrTy, 2510 CGM.VoidPtrPtrTy, 2511 CGM.Int64Ty->getPointerTo(), 2512 CGM.Int64Ty->getPointerTo()}; 2513 auto *FnTy = 2514 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2515 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2516 break; 2517 } 2518 case OMPRTL__tgt_target_data_update_nowait: { 2519 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2520 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2521 // *arg_types); 2522 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2523 CGM.Int32Ty, 2524 CGM.VoidPtrPtrTy, 2525 CGM.VoidPtrPtrTy, 2526 CGM.Int64Ty->getPointerTo(), 2527 CGM.Int64Ty->getPointerTo()}; 2528 auto *FnTy = 2529 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2530 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2531 break; 2532 } 2533 case OMPRTL__tgt_mapper_num_components: { 2534 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2535 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2536 auto *FnTy = 2537 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2538 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2539 break; 2540 } 2541 case OMPRTL__tgt_push_mapper_component: { 2542 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2543 // *base, void *begin, int64_t size, int64_t type); 2544 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2545 CGM.Int64Ty, CGM.Int64Ty}; 2546 auto *FnTy = 2547 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2548 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2549 break; 2550 } 2551 } 2552 assert(RTLFn && "Unable to find OpenMP runtime function"); 2553 return RTLFn; 2554 } 2555 2556 llvm::FunctionCallee 2557 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2558 assert((IVSize == 32 || IVSize == 64) && 2559 "IV size is not compatible with the omp runtime"); 2560 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2561 : "__kmpc_for_static_init_4u") 2562 : (IVSigned ? "__kmpc_for_static_init_8" 2563 : "__kmpc_for_static_init_8u"); 2564 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2565 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2566 llvm::Type *TypeParams[] = { 2567 getIdentTyPointerTy(), // loc 2568 CGM.Int32Ty, // tid 2569 CGM.Int32Ty, // schedtype 2570 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2571 PtrTy, // p_lower 2572 PtrTy, // p_upper 2573 PtrTy, // p_stride 2574 ITy, // incr 2575 ITy // chunk 2576 }; 2577 auto *FnTy = 2578 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2579 return CGM.CreateRuntimeFunction(FnTy, Name); 2580 } 2581 2582 llvm::FunctionCallee 2583 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2584 assert((IVSize == 32 || IVSize == 64) && 2585 "IV size is not compatible with the omp runtime"); 2586 StringRef Name = 2587 IVSize == 32 2588 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2589 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2590 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2591 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2592 CGM.Int32Ty, // tid 2593 CGM.Int32Ty, // schedtype 2594 ITy, // lower 2595 ITy, // upper 2596 ITy, // stride 2597 ITy // chunk 2598 }; 2599 auto *FnTy = 2600 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2601 return CGM.CreateRuntimeFunction(FnTy, Name); 2602 } 2603 2604 llvm::FunctionCallee 2605 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2606 assert((IVSize == 32 || IVSize == 64) && 2607 "IV size is not compatible with the omp runtime"); 2608 StringRef Name = 2609 IVSize == 32 2610 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2611 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2612 llvm::Type *TypeParams[] = { 2613 getIdentTyPointerTy(), // loc 2614 CGM.Int32Ty, // tid 2615 }; 2616 auto *FnTy = 2617 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2618 return CGM.CreateRuntimeFunction(FnTy, Name); 2619 } 2620 2621 llvm::FunctionCallee 2622 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2623 assert((IVSize == 32 || IVSize == 64) && 2624 "IV size is not compatible with the omp runtime"); 2625 StringRef Name = 2626 IVSize == 32 2627 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2628 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2629 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2630 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2631 llvm::Type *TypeParams[] = { 2632 getIdentTyPointerTy(), // loc 2633 CGM.Int32Ty, // tid 2634 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2635 PtrTy, // p_lower 2636 PtrTy, // p_upper 2637 PtrTy // p_stride 2638 }; 2639 auto *FnTy = 2640 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2641 return CGM.CreateRuntimeFunction(FnTy, Name); 2642 } 2643 2644 /// Obtain information that uniquely identifies a target entry. This 2645 /// consists of the file and device IDs as well as line number associated with 2646 /// the relevant entry source location. 2647 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2648 unsigned &DeviceID, unsigned &FileID, 2649 unsigned &LineNum) { 2650 SourceManager &SM = C.getSourceManager(); 2651 2652 // The loc should be always valid and have a file ID (the user cannot use 2653 // #pragma directives in macros) 2654 2655 assert(Loc.isValid() && "Source location is expected to be always valid."); 2656 2657 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2658 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2659 2660 llvm::sys::fs::UniqueID ID; 2661 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2662 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2663 << PLoc.getFilename() << EC.message(); 2664 2665 DeviceID = ID.getDevice(); 2666 FileID = ID.getFile(); 2667 LineNum = PLoc.getLine(); 2668 } 2669 2670 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2671 if (CGM.getLangOpts().OpenMPSimd) 2672 return Address::invalid(); 2673 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2674 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2675 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2676 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2677 HasRequiresUnifiedSharedMemory))) { 2678 SmallString<64> PtrName; 2679 { 2680 llvm::raw_svector_ostream OS(PtrName); 2681 OS << CGM.getMangledName(GlobalDecl(VD)); 2682 if (!VD->isExternallyVisible()) { 2683 unsigned DeviceID, FileID, Line; 2684 getTargetEntryUniqueInfo(CGM.getContext(), 2685 VD->getCanonicalDecl()->getBeginLoc(), 2686 DeviceID, FileID, Line); 2687 OS << llvm::format("_%x", FileID); 2688 } 2689 OS << "_decl_tgt_ref_ptr"; 2690 } 2691 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2692 if (!Ptr) { 2693 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2694 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2695 PtrName); 2696 2697 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2698 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2699 2700 if (!CGM.getLangOpts().OpenMPIsDevice) 2701 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2702 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2703 } 2704 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2705 } 2706 return Address::invalid(); 2707 } 2708 2709 llvm::Constant * 2710 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2711 assert(!CGM.getLangOpts().OpenMPUseTLS || 2712 !CGM.getContext().getTargetInfo().isTLSSupported()); 2713 // Lookup the entry, lazily creating it if necessary. 2714 std::string Suffix = getName({"cache", ""}); 2715 return getOrCreateInternalVariable( 2716 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2717 } 2718 2719 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2720 const VarDecl *VD, 2721 Address VDAddr, 2722 SourceLocation Loc) { 2723 if (CGM.getLangOpts().OpenMPUseTLS && 2724 CGM.getContext().getTargetInfo().isTLSSupported()) 2725 return VDAddr; 2726 2727 llvm::Type *VarTy = VDAddr.getElementType(); 2728 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2729 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2730 CGM.Int8PtrTy), 2731 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2732 getOrCreateThreadPrivateCache(VD)}; 2733 return Address(CGF.EmitRuntimeCall( 2734 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2735 VDAddr.getAlignment()); 2736 } 2737 2738 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2739 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2740 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2741 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2742 // library. 2743 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2744 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2745 OMPLoc); 2746 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2747 // to register constructor/destructor for variable. 2748 llvm::Value *Args[] = { 2749 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2750 Ctor, CopyCtor, Dtor}; 2751 CGF.EmitRuntimeCall( 2752 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2753 } 2754 2755 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2756 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2757 bool PerformInit, CodeGenFunction *CGF) { 2758 if (CGM.getLangOpts().OpenMPUseTLS && 2759 CGM.getContext().getTargetInfo().isTLSSupported()) 2760 return nullptr; 2761 2762 VD = VD->getDefinition(CGM.getContext()); 2763 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2764 QualType ASTTy = VD->getType(); 2765 2766 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2767 const Expr *Init = VD->getAnyInitializer(); 2768 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2769 // Generate function that re-emits the declaration's initializer into the 2770 // threadprivate copy of the variable VD 2771 CodeGenFunction CtorCGF(CGM); 2772 FunctionArgList Args; 2773 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2774 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2775 ImplicitParamDecl::Other); 2776 Args.push_back(&Dst); 2777 2778 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2779 CGM.getContext().VoidPtrTy, Args); 2780 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2781 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2782 llvm::Function *Fn = 2783 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2784 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2785 Args, Loc, Loc); 2786 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2787 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2788 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2789 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2790 Arg = CtorCGF.Builder.CreateElementBitCast( 2791 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2792 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2793 /*IsInitializer=*/true); 2794 ArgVal = CtorCGF.EmitLoadOfScalar( 2795 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2796 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2797 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2798 CtorCGF.FinishFunction(); 2799 Ctor = Fn; 2800 } 2801 if (VD->getType().isDestructedType() != QualType::DK_none) { 2802 // Generate function that emits destructor call for the threadprivate copy 2803 // of the variable VD 2804 CodeGenFunction DtorCGF(CGM); 2805 FunctionArgList Args; 2806 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2807 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2808 ImplicitParamDecl::Other); 2809 Args.push_back(&Dst); 2810 2811 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2812 CGM.getContext().VoidTy, Args); 2813 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2814 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2815 llvm::Function *Fn = 2816 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2817 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2818 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2819 Loc, Loc); 2820 // Create a scope with an artificial location for the body of this function. 2821 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2822 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2823 DtorCGF.GetAddrOfLocalVar(&Dst), 2824 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2825 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2826 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2827 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2828 DtorCGF.FinishFunction(); 2829 Dtor = Fn; 2830 } 2831 // Do not emit init function if it is not required. 2832 if (!Ctor && !Dtor) 2833 return nullptr; 2834 2835 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2836 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2837 /*isVarArg=*/false) 2838 ->getPointerTo(); 2839 // Copying constructor for the threadprivate variable. 2840 // Must be NULL - reserved by runtime, but currently it requires that this 2841 // parameter is always NULL. Otherwise it fires assertion. 2842 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2843 if (Ctor == nullptr) { 2844 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2845 /*isVarArg=*/false) 2846 ->getPointerTo(); 2847 Ctor = llvm::Constant::getNullValue(CtorTy); 2848 } 2849 if (Dtor == nullptr) { 2850 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2851 /*isVarArg=*/false) 2852 ->getPointerTo(); 2853 Dtor = llvm::Constant::getNullValue(DtorTy); 2854 } 2855 if (!CGF) { 2856 auto *InitFunctionTy = 2857 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2858 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2859 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2860 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2861 CodeGenFunction InitCGF(CGM); 2862 FunctionArgList ArgList; 2863 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2864 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2865 Loc, Loc); 2866 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2867 InitCGF.FinishFunction(); 2868 return InitFunction; 2869 } 2870 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2871 } 2872 return nullptr; 2873 } 2874 2875 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2876 llvm::GlobalVariable *Addr, 2877 bool PerformInit) { 2878 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2879 !CGM.getLangOpts().OpenMPIsDevice) 2880 return false; 2881 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2882 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2883 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2884 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2885 HasRequiresUnifiedSharedMemory)) 2886 return CGM.getLangOpts().OpenMPIsDevice; 2887 VD = VD->getDefinition(CGM.getContext()); 2888 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2889 return CGM.getLangOpts().OpenMPIsDevice; 2890 2891 QualType ASTTy = VD->getType(); 2892 2893 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2894 // Produce the unique prefix to identify the new target regions. We use 2895 // the source location of the variable declaration which we know to not 2896 // conflict with any target region. 2897 unsigned DeviceID; 2898 unsigned FileID; 2899 unsigned Line; 2900 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2901 SmallString<128> Buffer, Out; 2902 { 2903 llvm::raw_svector_ostream OS(Buffer); 2904 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2905 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2906 } 2907 2908 const Expr *Init = VD->getAnyInitializer(); 2909 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2910 llvm::Constant *Ctor; 2911 llvm::Constant *ID; 2912 if (CGM.getLangOpts().OpenMPIsDevice) { 2913 // Generate function that re-emits the declaration's initializer into 2914 // the threadprivate copy of the variable VD 2915 CodeGenFunction CtorCGF(CGM); 2916 2917 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2918 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2919 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2920 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2921 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2922 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2923 FunctionArgList(), Loc, Loc); 2924 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2925 CtorCGF.EmitAnyExprToMem(Init, 2926 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2927 Init->getType().getQualifiers(), 2928 /*IsInitializer=*/true); 2929 CtorCGF.FinishFunction(); 2930 Ctor = Fn; 2931 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2932 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2933 } else { 2934 Ctor = new llvm::GlobalVariable( 2935 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2936 llvm::GlobalValue::PrivateLinkage, 2937 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2938 ID = Ctor; 2939 } 2940 2941 // Register the information for the entry associated with the constructor. 2942 Out.clear(); 2943 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2944 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2945 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2946 } 2947 if (VD->getType().isDestructedType() != QualType::DK_none) { 2948 llvm::Constant *Dtor; 2949 llvm::Constant *ID; 2950 if (CGM.getLangOpts().OpenMPIsDevice) { 2951 // Generate function that emits destructor call for the threadprivate 2952 // copy of the variable VD 2953 CodeGenFunction DtorCGF(CGM); 2954 2955 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2956 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2957 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2958 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2959 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2960 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2961 FunctionArgList(), Loc, Loc); 2962 // Create a scope with an artificial location for the body of this 2963 // function. 2964 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2965 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 2966 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2967 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2968 DtorCGF.FinishFunction(); 2969 Dtor = Fn; 2970 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2971 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 2972 } else { 2973 Dtor = new llvm::GlobalVariable( 2974 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2975 llvm::GlobalValue::PrivateLinkage, 2976 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 2977 ID = Dtor; 2978 } 2979 // Register the information for the entry associated with the destructor. 2980 Out.clear(); 2981 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2982 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2983 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2984 } 2985 return CGM.getLangOpts().OpenMPIsDevice; 2986 } 2987 2988 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2989 QualType VarType, 2990 StringRef Name) { 2991 std::string Suffix = getName({"artificial", ""}); 2992 std::string CacheSuffix = getName({"cache", ""}); 2993 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2994 llvm::Value *GAddr = 2995 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2996 llvm::Value *Args[] = { 2997 emitUpdateLocation(CGF, SourceLocation()), 2998 getThreadID(CGF, SourceLocation()), 2999 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 3000 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 3001 /*isSigned=*/false), 3002 getOrCreateInternalVariable( 3003 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 3004 return Address( 3005 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3006 CGF.EmitRuntimeCall( 3007 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3008 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3009 CGM.getPointerAlign()); 3010 } 3011 3012 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 3013 const RegionCodeGenTy &ThenGen, 3014 const RegionCodeGenTy &ElseGen) { 3015 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3016 3017 // If the condition constant folds and can be elided, try to avoid emitting 3018 // the condition and the dead arm of the if/else. 3019 bool CondConstant; 3020 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3021 if (CondConstant) 3022 ThenGen(CGF); 3023 else 3024 ElseGen(CGF); 3025 return; 3026 } 3027 3028 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3029 // emit the conditional branch. 3030 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3031 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3032 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3033 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3034 3035 // Emit the 'then' code. 3036 CGF.EmitBlock(ThenBlock); 3037 ThenGen(CGF); 3038 CGF.EmitBranch(ContBlock); 3039 // Emit the 'else' code if present. 3040 // There is no need to emit line number for unconditional branch. 3041 (void)ApplyDebugLocation::CreateEmpty(CGF); 3042 CGF.EmitBlock(ElseBlock); 3043 ElseGen(CGF); 3044 // There is no need to emit line number for unconditional branch. 3045 (void)ApplyDebugLocation::CreateEmpty(CGF); 3046 CGF.EmitBranch(ContBlock); 3047 // Emit the continuation block for code after the if. 3048 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3049 } 3050 3051 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3052 llvm::Function *OutlinedFn, 3053 ArrayRef<llvm::Value *> CapturedVars, 3054 const Expr *IfCond) { 3055 if (!CGF.HaveInsertPoint()) 3056 return; 3057 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3058 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3059 PrePostActionTy &) { 3060 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3061 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3062 llvm::Value *Args[] = { 3063 RTLoc, 3064 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3065 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3066 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3067 RealArgs.append(std::begin(Args), std::end(Args)); 3068 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3069 3070 llvm::FunctionCallee RTLFn = 3071 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3072 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3073 }; 3074 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3075 PrePostActionTy &) { 3076 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3077 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3078 // Build calls: 3079 // __kmpc_serialized_parallel(&Loc, GTid); 3080 llvm::Value *Args[] = {RTLoc, ThreadID}; 3081 CGF.EmitRuntimeCall( 3082 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3083 3084 // OutlinedFn(>id, &zero_bound, CapturedStruct); 3085 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 3086 Address ZeroAddrBound = 3087 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3088 /*Name=*/".bound.zero.addr"); 3089 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 3090 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3091 // ThreadId for serialized parallels is 0. 3092 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 3093 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 3094 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3095 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3096 3097 // __kmpc_end_serialized_parallel(&Loc, GTid); 3098 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3099 CGF.EmitRuntimeCall( 3100 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3101 EndArgs); 3102 }; 3103 if (IfCond) { 3104 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 3105 } else { 3106 RegionCodeGenTy ThenRCG(ThenGen); 3107 ThenRCG(CGF); 3108 } 3109 } 3110 3111 // If we're inside an (outlined) parallel region, use the region info's 3112 // thread-ID variable (it is passed in a first argument of the outlined function 3113 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3114 // regular serial code region, get thread ID by calling kmp_int32 3115 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3116 // return the address of that temp. 3117 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3118 SourceLocation Loc) { 3119 if (auto *OMPRegionInfo = 3120 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3121 if (OMPRegionInfo->getThreadIDVariable()) 3122 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); 3123 3124 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3125 QualType Int32Ty = 3126 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3127 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3128 CGF.EmitStoreOfScalar(ThreadID, 3129 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3130 3131 return ThreadIDTemp; 3132 } 3133 3134 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3135 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3136 SmallString<256> Buffer; 3137 llvm::raw_svector_ostream Out(Buffer); 3138 Out << Name; 3139 StringRef RuntimeName = Out.str(); 3140 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3141 if (Elem.second) { 3142 assert(Elem.second->getType()->getPointerElementType() == Ty && 3143 "OMP internal variable has different type than requested"); 3144 return &*Elem.second; 3145 } 3146 3147 return Elem.second = new llvm::GlobalVariable( 3148 CGM.getModule(), Ty, /*IsConstant*/ false, 3149 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3150 Elem.first(), /*InsertBefore=*/nullptr, 3151 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3152 } 3153 3154 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3155 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3156 std::string Name = getName({Prefix, "var"}); 3157 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3158 } 3159 3160 namespace { 3161 /// Common pre(post)-action for different OpenMP constructs. 3162 class CommonActionTy final : public PrePostActionTy { 3163 llvm::FunctionCallee EnterCallee; 3164 ArrayRef<llvm::Value *> EnterArgs; 3165 llvm::FunctionCallee ExitCallee; 3166 ArrayRef<llvm::Value *> ExitArgs; 3167 bool Conditional; 3168 llvm::BasicBlock *ContBlock = nullptr; 3169 3170 public: 3171 CommonActionTy(llvm::FunctionCallee EnterCallee, 3172 ArrayRef<llvm::Value *> EnterArgs, 3173 llvm::FunctionCallee ExitCallee, 3174 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3175 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3176 ExitArgs(ExitArgs), Conditional(Conditional) {} 3177 void Enter(CodeGenFunction &CGF) override { 3178 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3179 if (Conditional) { 3180 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3181 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3182 ContBlock = CGF.createBasicBlock("omp_if.end"); 3183 // Generate the branch (If-stmt) 3184 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3185 CGF.EmitBlock(ThenBlock); 3186 } 3187 } 3188 void Done(CodeGenFunction &CGF) { 3189 // Emit the rest of blocks/branches 3190 CGF.EmitBranch(ContBlock); 3191 CGF.EmitBlock(ContBlock, true); 3192 } 3193 void Exit(CodeGenFunction &CGF) override { 3194 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3195 } 3196 }; 3197 } // anonymous namespace 3198 3199 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3200 StringRef CriticalName, 3201 const RegionCodeGenTy &CriticalOpGen, 3202 SourceLocation Loc, const Expr *Hint) { 3203 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3204 // CriticalOpGen(); 3205 // __kmpc_end_critical(ident_t *, gtid, Lock); 3206 // Prepare arguments and build a call to __kmpc_critical 3207 if (!CGF.HaveInsertPoint()) 3208 return; 3209 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3210 getCriticalRegionLock(CriticalName)}; 3211 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3212 std::end(Args)); 3213 if (Hint) { 3214 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3215 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3216 } 3217 CommonActionTy Action( 3218 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3219 : OMPRTL__kmpc_critical), 3220 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3221 CriticalOpGen.setAction(Action); 3222 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3223 } 3224 3225 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3226 const RegionCodeGenTy &MasterOpGen, 3227 SourceLocation Loc) { 3228 if (!CGF.HaveInsertPoint()) 3229 return; 3230 // if(__kmpc_master(ident_t *, gtid)) { 3231 // MasterOpGen(); 3232 // __kmpc_end_master(ident_t *, gtid); 3233 // } 3234 // Prepare arguments and build a call to __kmpc_master 3235 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3236 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3237 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3238 /*Conditional=*/true); 3239 MasterOpGen.setAction(Action); 3240 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3241 Action.Done(CGF); 3242 } 3243 3244 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3245 SourceLocation Loc) { 3246 if (!CGF.HaveInsertPoint()) 3247 return; 3248 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3249 llvm::Value *Args[] = { 3250 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3251 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3252 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3253 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3254 Region->emitUntiedSwitch(CGF); 3255 } 3256 3257 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3258 const RegionCodeGenTy &TaskgroupOpGen, 3259 SourceLocation Loc) { 3260 if (!CGF.HaveInsertPoint()) 3261 return; 3262 // __kmpc_taskgroup(ident_t *, gtid); 3263 // TaskgroupOpGen(); 3264 // __kmpc_end_taskgroup(ident_t *, gtid); 3265 // Prepare arguments and build a call to __kmpc_taskgroup 3266 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3267 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3268 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3269 Args); 3270 TaskgroupOpGen.setAction(Action); 3271 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3272 } 3273 3274 /// Given an array of pointers to variables, project the address of a 3275 /// given variable. 3276 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3277 unsigned Index, const VarDecl *Var) { 3278 // Pull out the pointer to the variable. 3279 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3280 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3281 3282 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3283 Addr = CGF.Builder.CreateElementBitCast( 3284 Addr, CGF.ConvertTypeForMem(Var->getType())); 3285 return Addr; 3286 } 3287 3288 static llvm::Value *emitCopyprivateCopyFunction( 3289 CodeGenModule &CGM, llvm::Type *ArgsType, 3290 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3291 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3292 SourceLocation Loc) { 3293 ASTContext &C = CGM.getContext(); 3294 // void copy_func(void *LHSArg, void *RHSArg); 3295 FunctionArgList Args; 3296 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3297 ImplicitParamDecl::Other); 3298 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3299 ImplicitParamDecl::Other); 3300 Args.push_back(&LHSArg); 3301 Args.push_back(&RHSArg); 3302 const auto &CGFI = 3303 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3304 std::string Name = 3305 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3306 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3307 llvm::GlobalValue::InternalLinkage, Name, 3308 &CGM.getModule()); 3309 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3310 Fn->setDoesNotRecurse(); 3311 CodeGenFunction CGF(CGM); 3312 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3313 // Dest = (void*[n])(LHSArg); 3314 // Src = (void*[n])(RHSArg); 3315 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3316 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3317 ArgsType), CGF.getPointerAlign()); 3318 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3319 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3320 ArgsType), CGF.getPointerAlign()); 3321 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3322 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3323 // ... 3324 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3325 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3326 const auto *DestVar = 3327 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3328 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3329 3330 const auto *SrcVar = 3331 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3332 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3333 3334 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3335 QualType Type = VD->getType(); 3336 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3337 } 3338 CGF.FinishFunction(); 3339 return Fn; 3340 } 3341 3342 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3343 const RegionCodeGenTy &SingleOpGen, 3344 SourceLocation Loc, 3345 ArrayRef<const Expr *> CopyprivateVars, 3346 ArrayRef<const Expr *> SrcExprs, 3347 ArrayRef<const Expr *> DstExprs, 3348 ArrayRef<const Expr *> AssignmentOps) { 3349 if (!CGF.HaveInsertPoint()) 3350 return; 3351 assert(CopyprivateVars.size() == SrcExprs.size() && 3352 CopyprivateVars.size() == DstExprs.size() && 3353 CopyprivateVars.size() == AssignmentOps.size()); 3354 ASTContext &C = CGM.getContext(); 3355 // int32 did_it = 0; 3356 // if(__kmpc_single(ident_t *, gtid)) { 3357 // SingleOpGen(); 3358 // __kmpc_end_single(ident_t *, gtid); 3359 // did_it = 1; 3360 // } 3361 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3362 // <copy_func>, did_it); 3363 3364 Address DidIt = Address::invalid(); 3365 if (!CopyprivateVars.empty()) { 3366 // int32 did_it = 0; 3367 QualType KmpInt32Ty = 3368 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3369 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3370 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3371 } 3372 // Prepare arguments and build a call to __kmpc_single 3373 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3374 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3375 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3376 /*Conditional=*/true); 3377 SingleOpGen.setAction(Action); 3378 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3379 if (DidIt.isValid()) { 3380 // did_it = 1; 3381 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3382 } 3383 Action.Done(CGF); 3384 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3385 // <copy_func>, did_it); 3386 if (DidIt.isValid()) { 3387 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3388 QualType CopyprivateArrayTy = C.getConstantArrayType( 3389 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3390 /*IndexTypeQuals=*/0); 3391 // Create a list of all private variables for copyprivate. 3392 Address CopyprivateList = 3393 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3394 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3395 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3396 CGF.Builder.CreateStore( 3397 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3398 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy), 3399 Elem); 3400 } 3401 // Build function that copies private values from single region to all other 3402 // threads in the corresponding parallel region. 3403 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3404 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3405 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3406 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3407 Address CL = 3408 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3409 CGF.VoidPtrTy); 3410 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3411 llvm::Value *Args[] = { 3412 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3413 getThreadID(CGF, Loc), // i32 <gtid> 3414 BufSize, // size_t <buf_size> 3415 CL.getPointer(), // void *<copyprivate list> 3416 CpyFn, // void (*) (void *, void *) <copy_func> 3417 DidItVal // i32 did_it 3418 }; 3419 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3420 } 3421 } 3422 3423 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3424 const RegionCodeGenTy &OrderedOpGen, 3425 SourceLocation Loc, bool IsThreads) { 3426 if (!CGF.HaveInsertPoint()) 3427 return; 3428 // __kmpc_ordered(ident_t *, gtid); 3429 // OrderedOpGen(); 3430 // __kmpc_end_ordered(ident_t *, gtid); 3431 // Prepare arguments and build a call to __kmpc_ordered 3432 if (IsThreads) { 3433 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3434 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3435 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3436 Args); 3437 OrderedOpGen.setAction(Action); 3438 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3439 return; 3440 } 3441 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3442 } 3443 3444 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3445 unsigned Flags; 3446 if (Kind == OMPD_for) 3447 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3448 else if (Kind == OMPD_sections) 3449 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3450 else if (Kind == OMPD_single) 3451 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3452 else if (Kind == OMPD_barrier) 3453 Flags = OMP_IDENT_BARRIER_EXPL; 3454 else 3455 Flags = OMP_IDENT_BARRIER_IMPL; 3456 return Flags; 3457 } 3458 3459 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3460 CodeGenFunction &CGF, const OMPLoopDirective &S, 3461 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3462 // Check if the loop directive is actually a doacross loop directive. In this 3463 // case choose static, 1 schedule. 3464 if (llvm::any_of( 3465 S.getClausesOfKind<OMPOrderedClause>(), 3466 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3467 ScheduleKind = OMPC_SCHEDULE_static; 3468 // Chunk size is 1 in this case. 3469 llvm::APInt ChunkSize(32, 1); 3470 ChunkExpr = IntegerLiteral::Create( 3471 CGF.getContext(), ChunkSize, 3472 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3473 SourceLocation()); 3474 } 3475 } 3476 3477 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3478 OpenMPDirectiveKind Kind, bool EmitChecks, 3479 bool ForceSimpleCall) { 3480 if (!CGF.HaveInsertPoint()) 3481 return; 3482 // Build call __kmpc_cancel_barrier(loc, thread_id); 3483 // Build call __kmpc_barrier(loc, thread_id); 3484 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3485 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3486 // thread_id); 3487 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3488 getThreadID(CGF, Loc)}; 3489 if (auto *OMPRegionInfo = 3490 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 3491 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3492 llvm::Value *Result = CGF.EmitRuntimeCall( 3493 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3494 if (EmitChecks) { 3495 // if (__kmpc_cancel_barrier()) { 3496 // exit from construct; 3497 // } 3498 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3499 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3500 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3501 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3502 CGF.EmitBlock(ExitBB); 3503 // exit from construct; 3504 CodeGenFunction::JumpDest CancelDestination = 3505 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3506 CGF.EmitBranchThroughCleanup(CancelDestination); 3507 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3508 } 3509 return; 3510 } 3511 } 3512 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3513 } 3514 3515 /// Map the OpenMP loop schedule to the runtime enumeration. 3516 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3517 bool Chunked, bool Ordered) { 3518 switch (ScheduleKind) { 3519 case OMPC_SCHEDULE_static: 3520 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3521 : (Ordered ? OMP_ord_static : OMP_sch_static); 3522 case OMPC_SCHEDULE_dynamic: 3523 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3524 case OMPC_SCHEDULE_guided: 3525 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3526 case OMPC_SCHEDULE_runtime: 3527 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3528 case OMPC_SCHEDULE_auto: 3529 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3530 case OMPC_SCHEDULE_unknown: 3531 assert(!Chunked && "chunk was specified but schedule kind not known"); 3532 return Ordered ? OMP_ord_static : OMP_sch_static; 3533 } 3534 llvm_unreachable("Unexpected runtime schedule"); 3535 } 3536 3537 /// Map the OpenMP distribute schedule to the runtime enumeration. 3538 static OpenMPSchedType 3539 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3540 // only static is allowed for dist_schedule 3541 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3542 } 3543 3544 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3545 bool Chunked) const { 3546 OpenMPSchedType Schedule = 3547 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3548 return Schedule == OMP_sch_static; 3549 } 3550 3551 bool CGOpenMPRuntime::isStaticNonchunked( 3552 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3553 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3554 return Schedule == OMP_dist_sch_static; 3555 } 3556 3557 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3558 bool Chunked) const { 3559 OpenMPSchedType Schedule = 3560 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3561 return Schedule == OMP_sch_static_chunked; 3562 } 3563 3564 bool CGOpenMPRuntime::isStaticChunked( 3565 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3566 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3567 return Schedule == OMP_dist_sch_static_chunked; 3568 } 3569 3570 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3571 OpenMPSchedType Schedule = 3572 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3573 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3574 return Schedule != OMP_sch_static; 3575 } 3576 3577 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3578 OpenMPScheduleClauseModifier M1, 3579 OpenMPScheduleClauseModifier M2) { 3580 int Modifier = 0; 3581 switch (M1) { 3582 case OMPC_SCHEDULE_MODIFIER_monotonic: 3583 Modifier = OMP_sch_modifier_monotonic; 3584 break; 3585 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3586 Modifier = OMP_sch_modifier_nonmonotonic; 3587 break; 3588 case OMPC_SCHEDULE_MODIFIER_simd: 3589 if (Schedule == OMP_sch_static_chunked) 3590 Schedule = OMP_sch_static_balanced_chunked; 3591 break; 3592 case OMPC_SCHEDULE_MODIFIER_last: 3593 case OMPC_SCHEDULE_MODIFIER_unknown: 3594 break; 3595 } 3596 switch (M2) { 3597 case OMPC_SCHEDULE_MODIFIER_monotonic: 3598 Modifier = OMP_sch_modifier_monotonic; 3599 break; 3600 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3601 Modifier = OMP_sch_modifier_nonmonotonic; 3602 break; 3603 case OMPC_SCHEDULE_MODIFIER_simd: 3604 if (Schedule == OMP_sch_static_chunked) 3605 Schedule = OMP_sch_static_balanced_chunked; 3606 break; 3607 case OMPC_SCHEDULE_MODIFIER_last: 3608 case OMPC_SCHEDULE_MODIFIER_unknown: 3609 break; 3610 } 3611 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3612 // If the static schedule kind is specified or if the ordered clause is 3613 // specified, and if the nonmonotonic modifier is not specified, the effect is 3614 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3615 // modifier is specified, the effect is as if the nonmonotonic modifier is 3616 // specified. 3617 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3618 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3619 Schedule == OMP_sch_static_balanced_chunked || 3620 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 3621 Schedule == OMP_dist_sch_static_chunked || 3622 Schedule == OMP_dist_sch_static)) 3623 Modifier = OMP_sch_modifier_nonmonotonic; 3624 } 3625 return Schedule | Modifier; 3626 } 3627 3628 void CGOpenMPRuntime::emitForDispatchInit( 3629 CodeGenFunction &CGF, SourceLocation Loc, 3630 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3631 bool Ordered, const DispatchRTInput &DispatchValues) { 3632 if (!CGF.HaveInsertPoint()) 3633 return; 3634 OpenMPSchedType Schedule = getRuntimeSchedule( 3635 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3636 assert(Ordered || 3637 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3638 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3639 Schedule != OMP_sch_static_balanced_chunked)); 3640 // Call __kmpc_dispatch_init( 3641 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3642 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3643 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3644 3645 // If the Chunk was not specified in the clause - use default value 1. 3646 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3647 : CGF.Builder.getIntN(IVSize, 1); 3648 llvm::Value *Args[] = { 3649 emitUpdateLocation(CGF, Loc), 3650 getThreadID(CGF, Loc), 3651 CGF.Builder.getInt32(addMonoNonMonoModifier( 3652 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3653 DispatchValues.LB, // Lower 3654 DispatchValues.UB, // Upper 3655 CGF.Builder.getIntN(IVSize, 1), // Stride 3656 Chunk // Chunk 3657 }; 3658 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3659 } 3660 3661 static void emitForStaticInitCall( 3662 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3663 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3664 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3665 const CGOpenMPRuntime::StaticRTInput &Values) { 3666 if (!CGF.HaveInsertPoint()) 3667 return; 3668 3669 assert(!Values.Ordered); 3670 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3671 Schedule == OMP_sch_static_balanced_chunked || 3672 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3673 Schedule == OMP_dist_sch_static || 3674 Schedule == OMP_dist_sch_static_chunked); 3675 3676 // Call __kmpc_for_static_init( 3677 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3678 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3679 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3680 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3681 llvm::Value *Chunk = Values.Chunk; 3682 if (Chunk == nullptr) { 3683 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3684 Schedule == OMP_dist_sch_static) && 3685 "expected static non-chunked schedule"); 3686 // If the Chunk was not specified in the clause - use default value 1. 3687 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3688 } else { 3689 assert((Schedule == OMP_sch_static_chunked || 3690 Schedule == OMP_sch_static_balanced_chunked || 3691 Schedule == OMP_ord_static_chunked || 3692 Schedule == OMP_dist_sch_static_chunked) && 3693 "expected static chunked schedule"); 3694 } 3695 llvm::Value *Args[] = { 3696 UpdateLocation, 3697 ThreadId, 3698 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3699 M2)), // Schedule type 3700 Values.IL.getPointer(), // &isLastIter 3701 Values.LB.getPointer(), // &LB 3702 Values.UB.getPointer(), // &UB 3703 Values.ST.getPointer(), // &Stride 3704 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3705 Chunk // Chunk 3706 }; 3707 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3708 } 3709 3710 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3711 SourceLocation Loc, 3712 OpenMPDirectiveKind DKind, 3713 const OpenMPScheduleTy &ScheduleKind, 3714 const StaticRTInput &Values) { 3715 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3716 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3717 assert(isOpenMPWorksharingDirective(DKind) && 3718 "Expected loop-based or sections-based directive."); 3719 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3720 isOpenMPLoopDirective(DKind) 3721 ? OMP_IDENT_WORK_LOOP 3722 : OMP_IDENT_WORK_SECTIONS); 3723 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3724 llvm::FunctionCallee StaticInitFunction = 3725 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3726 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3727 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3728 } 3729 3730 void CGOpenMPRuntime::emitDistributeStaticInit( 3731 CodeGenFunction &CGF, SourceLocation Loc, 3732 OpenMPDistScheduleClauseKind SchedKind, 3733 const CGOpenMPRuntime::StaticRTInput &Values) { 3734 OpenMPSchedType ScheduleNum = 3735 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3736 llvm::Value *UpdatedLocation = 3737 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3738 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3739 llvm::FunctionCallee StaticInitFunction = 3740 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3741 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3742 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3743 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3744 } 3745 3746 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3747 SourceLocation Loc, 3748 OpenMPDirectiveKind DKind) { 3749 if (!CGF.HaveInsertPoint()) 3750 return; 3751 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3752 llvm::Value *Args[] = { 3753 emitUpdateLocation(CGF, Loc, 3754 isOpenMPDistributeDirective(DKind) 3755 ? OMP_IDENT_WORK_DISTRIBUTE 3756 : isOpenMPLoopDirective(DKind) 3757 ? OMP_IDENT_WORK_LOOP 3758 : OMP_IDENT_WORK_SECTIONS), 3759 getThreadID(CGF, Loc)}; 3760 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3761 Args); 3762 } 3763 3764 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3765 SourceLocation Loc, 3766 unsigned IVSize, 3767 bool IVSigned) { 3768 if (!CGF.HaveInsertPoint()) 3769 return; 3770 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3771 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3772 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3773 } 3774 3775 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3776 SourceLocation Loc, unsigned IVSize, 3777 bool IVSigned, Address IL, 3778 Address LB, Address UB, 3779 Address ST) { 3780 // Call __kmpc_dispatch_next( 3781 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3782 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3783 // kmp_int[32|64] *p_stride); 3784 llvm::Value *Args[] = { 3785 emitUpdateLocation(CGF, Loc), 3786 getThreadID(CGF, Loc), 3787 IL.getPointer(), // &isLastIter 3788 LB.getPointer(), // &Lower 3789 UB.getPointer(), // &Upper 3790 ST.getPointer() // &Stride 3791 }; 3792 llvm::Value *Call = 3793 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3794 return CGF.EmitScalarConversion( 3795 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3796 CGF.getContext().BoolTy, Loc); 3797 } 3798 3799 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3800 llvm::Value *NumThreads, 3801 SourceLocation Loc) { 3802 if (!CGF.HaveInsertPoint()) 3803 return; 3804 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3805 llvm::Value *Args[] = { 3806 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3807 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3808 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3809 Args); 3810 } 3811 3812 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3813 OpenMPProcBindClauseKind ProcBind, 3814 SourceLocation Loc) { 3815 if (!CGF.HaveInsertPoint()) 3816 return; 3817 // Constants for proc bind value accepted by the runtime. 3818 enum ProcBindTy { 3819 ProcBindFalse = 0, 3820 ProcBindTrue, 3821 ProcBindMaster, 3822 ProcBindClose, 3823 ProcBindSpread, 3824 ProcBindIntel, 3825 ProcBindDefault 3826 } RuntimeProcBind; 3827 switch (ProcBind) { 3828 case OMPC_PROC_BIND_master: 3829 RuntimeProcBind = ProcBindMaster; 3830 break; 3831 case OMPC_PROC_BIND_close: 3832 RuntimeProcBind = ProcBindClose; 3833 break; 3834 case OMPC_PROC_BIND_spread: 3835 RuntimeProcBind = ProcBindSpread; 3836 break; 3837 case OMPC_PROC_BIND_unknown: 3838 llvm_unreachable("Unsupported proc_bind value."); 3839 } 3840 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3841 llvm::Value *Args[] = { 3842 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3843 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 3844 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3845 } 3846 3847 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3848 SourceLocation Loc) { 3849 if (!CGF.HaveInsertPoint()) 3850 return; 3851 // Build call void __kmpc_flush(ident_t *loc) 3852 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3853 emitUpdateLocation(CGF, Loc)); 3854 } 3855 3856 namespace { 3857 /// Indexes of fields for type kmp_task_t. 3858 enum KmpTaskTFields { 3859 /// List of shared variables. 3860 KmpTaskTShareds, 3861 /// Task routine. 3862 KmpTaskTRoutine, 3863 /// Partition id for the untied tasks. 3864 KmpTaskTPartId, 3865 /// Function with call of destructors for private variables. 3866 Data1, 3867 /// Task priority. 3868 Data2, 3869 /// (Taskloops only) Lower bound. 3870 KmpTaskTLowerBound, 3871 /// (Taskloops only) Upper bound. 3872 KmpTaskTUpperBound, 3873 /// (Taskloops only) Stride. 3874 KmpTaskTStride, 3875 /// (Taskloops only) Is last iteration flag. 3876 KmpTaskTLastIter, 3877 /// (Taskloops only) Reduction data. 3878 KmpTaskTReductions, 3879 }; 3880 } // anonymous namespace 3881 3882 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3883 return OffloadEntriesTargetRegion.empty() && 3884 OffloadEntriesDeviceGlobalVar.empty(); 3885 } 3886 3887 /// Initialize target region entry. 3888 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3889 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3890 StringRef ParentName, unsigned LineNum, 3891 unsigned Order) { 3892 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3893 "only required for the device " 3894 "code generation."); 3895 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3896 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3897 OMPTargetRegionEntryTargetRegion); 3898 ++OffloadingEntriesNum; 3899 } 3900 3901 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3902 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3903 StringRef ParentName, unsigned LineNum, 3904 llvm::Constant *Addr, llvm::Constant *ID, 3905 OMPTargetRegionEntryKind Flags) { 3906 // If we are emitting code for a target, the entry is already initialized, 3907 // only has to be registered. 3908 if (CGM.getLangOpts().OpenMPIsDevice) { 3909 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3910 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3911 DiagnosticsEngine::Error, 3912 "Unable to find target region on line '%0' in the device code."); 3913 CGM.getDiags().Report(DiagID) << LineNum; 3914 return; 3915 } 3916 auto &Entry = 3917 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3918 assert(Entry.isValid() && "Entry not initialized!"); 3919 Entry.setAddress(Addr); 3920 Entry.setID(ID); 3921 Entry.setFlags(Flags); 3922 } else { 3923 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3924 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3925 ++OffloadingEntriesNum; 3926 } 3927 } 3928 3929 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3930 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3931 unsigned LineNum) const { 3932 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3933 if (PerDevice == OffloadEntriesTargetRegion.end()) 3934 return false; 3935 auto PerFile = PerDevice->second.find(FileID); 3936 if (PerFile == PerDevice->second.end()) 3937 return false; 3938 auto PerParentName = PerFile->second.find(ParentName); 3939 if (PerParentName == PerFile->second.end()) 3940 return false; 3941 auto PerLine = PerParentName->second.find(LineNum); 3942 if (PerLine == PerParentName->second.end()) 3943 return false; 3944 // Fail if this entry is already registered. 3945 if (PerLine->second.getAddress() || PerLine->second.getID()) 3946 return false; 3947 return true; 3948 } 3949 3950 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3951 const OffloadTargetRegionEntryInfoActTy &Action) { 3952 // Scan all target region entries and perform the provided action. 3953 for (const auto &D : OffloadEntriesTargetRegion) 3954 for (const auto &F : D.second) 3955 for (const auto &P : F.second) 3956 for (const auto &L : P.second) 3957 Action(D.first, F.first, P.first(), L.first, L.second); 3958 } 3959 3960 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3961 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3962 OMPTargetGlobalVarEntryKind Flags, 3963 unsigned Order) { 3964 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3965 "only required for the device " 3966 "code generation."); 3967 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3968 ++OffloadingEntriesNum; 3969 } 3970 3971 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3972 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3973 CharUnits VarSize, 3974 OMPTargetGlobalVarEntryKind Flags, 3975 llvm::GlobalValue::LinkageTypes Linkage) { 3976 if (CGM.getLangOpts().OpenMPIsDevice) { 3977 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3978 assert(Entry.isValid() && Entry.getFlags() == Flags && 3979 "Entry not initialized!"); 3980 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3981 "Resetting with the new address."); 3982 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3983 if (Entry.getVarSize().isZero()) { 3984 Entry.setVarSize(VarSize); 3985 Entry.setLinkage(Linkage); 3986 } 3987 return; 3988 } 3989 Entry.setVarSize(VarSize); 3990 Entry.setLinkage(Linkage); 3991 Entry.setAddress(Addr); 3992 } else { 3993 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3994 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3995 assert(Entry.isValid() && Entry.getFlags() == Flags && 3996 "Entry not initialized!"); 3997 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3998 "Resetting with the new address."); 3999 if (Entry.getVarSize().isZero()) { 4000 Entry.setVarSize(VarSize); 4001 Entry.setLinkage(Linkage); 4002 } 4003 return; 4004 } 4005 OffloadEntriesDeviceGlobalVar.try_emplace( 4006 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 4007 ++OffloadingEntriesNum; 4008 } 4009 } 4010 4011 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4012 actOnDeviceGlobalVarEntriesInfo( 4013 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4014 // Scan all target region entries and perform the provided action. 4015 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4016 Action(E.getKey(), E.getValue()); 4017 } 4018 4019 void CGOpenMPRuntime::createOffloadEntry( 4020 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4021 llvm::GlobalValue::LinkageTypes Linkage) { 4022 StringRef Name = Addr->getName(); 4023 llvm::Module &M = CGM.getModule(); 4024 llvm::LLVMContext &C = M.getContext(); 4025 4026 // Create constant string with the name. 4027 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4028 4029 std::string StringName = getName({"omp_offloading", "entry_name"}); 4030 auto *Str = new llvm::GlobalVariable( 4031 M, StrPtrInit->getType(), /*isConstant=*/true, 4032 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4033 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4034 4035 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4036 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4037 llvm::ConstantInt::get(CGM.SizeTy, Size), 4038 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4039 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4040 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4041 llvm::GlobalVariable *Entry = createGlobalStruct( 4042 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4043 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4044 4045 // The entry has to be created in the section the linker expects it to be. 4046 Entry->setSection("omp_offloading_entries"); 4047 } 4048 4049 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4050 // Emit the offloading entries and metadata so that the device codegen side 4051 // can easily figure out what to emit. The produced metadata looks like 4052 // this: 4053 // 4054 // !omp_offload.info = !{!1, ...} 4055 // 4056 // Right now we only generate metadata for function that contain target 4057 // regions. 4058 4059 // If we are in simd mode or there are no entries, we don't need to do 4060 // anything. 4061 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4062 return; 4063 4064 llvm::Module &M = CGM.getModule(); 4065 llvm::LLVMContext &C = M.getContext(); 4066 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4067 SourceLocation, StringRef>, 4068 16> 4069 OrderedEntries(OffloadEntriesInfoManager.size()); 4070 llvm::SmallVector<StringRef, 16> ParentFunctions( 4071 OffloadEntriesInfoManager.size()); 4072 4073 // Auxiliary methods to create metadata values and strings. 4074 auto &&GetMDInt = [this](unsigned V) { 4075 return llvm::ConstantAsMetadata::get( 4076 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4077 }; 4078 4079 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4080 4081 // Create the offloading info metadata node. 4082 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4083 4084 // Create function that emits metadata for each target region entry; 4085 auto &&TargetRegionMetadataEmitter = 4086 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4087 &GetMDString]( 4088 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4089 unsigned Line, 4090 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4091 // Generate metadata for target regions. Each entry of this metadata 4092 // contains: 4093 // - Entry 0 -> Kind of this type of metadata (0). 4094 // - Entry 1 -> Device ID of the file where the entry was identified. 4095 // - Entry 2 -> File ID of the file where the entry was identified. 4096 // - Entry 3 -> Mangled name of the function where the entry was 4097 // identified. 4098 // - Entry 4 -> Line in the file where the entry was identified. 4099 // - Entry 5 -> Order the entry was created. 4100 // The first element of the metadata node is the kind. 4101 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4102 GetMDInt(FileID), GetMDString(ParentName), 4103 GetMDInt(Line), GetMDInt(E.getOrder())}; 4104 4105 SourceLocation Loc; 4106 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4107 E = CGM.getContext().getSourceManager().fileinfo_end(); 4108 I != E; ++I) { 4109 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4110 I->getFirst()->getUniqueID().getFile() == FileID) { 4111 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4112 I->getFirst(), Line, 1); 4113 break; 4114 } 4115 } 4116 // Save this entry in the right position of the ordered entries array. 4117 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4118 ParentFunctions[E.getOrder()] = ParentName; 4119 4120 // Add metadata to the named metadata node. 4121 MD->addOperand(llvm::MDNode::get(C, Ops)); 4122 }; 4123 4124 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4125 TargetRegionMetadataEmitter); 4126 4127 // Create function that emits metadata for each device global variable entry; 4128 auto &&DeviceGlobalVarMetadataEmitter = 4129 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4130 MD](StringRef MangledName, 4131 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4132 &E) { 4133 // Generate metadata for global variables. Each entry of this metadata 4134 // contains: 4135 // - Entry 0 -> Kind of this type of metadata (1). 4136 // - Entry 1 -> Mangled name of the variable. 4137 // - Entry 2 -> Declare target kind. 4138 // - Entry 3 -> Order the entry was created. 4139 // The first element of the metadata node is the kind. 4140 llvm::Metadata *Ops[] = { 4141 GetMDInt(E.getKind()), GetMDString(MangledName), 4142 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4143 4144 // Save this entry in the right position of the ordered entries array. 4145 OrderedEntries[E.getOrder()] = 4146 std::make_tuple(&E, SourceLocation(), MangledName); 4147 4148 // Add metadata to the named metadata node. 4149 MD->addOperand(llvm::MDNode::get(C, Ops)); 4150 }; 4151 4152 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4153 DeviceGlobalVarMetadataEmitter); 4154 4155 for (const auto &E : OrderedEntries) { 4156 assert(std::get<0>(E) && "All ordered entries must exist!"); 4157 if (const auto *CE = 4158 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4159 std::get<0>(E))) { 4160 if (!CE->getID() || !CE->getAddress()) { 4161 // Do not blame the entry if the parent funtion is not emitted. 4162 StringRef FnName = ParentFunctions[CE->getOrder()]; 4163 if (!CGM.GetGlobalValue(FnName)) 4164 continue; 4165 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4166 DiagnosticsEngine::Error, 4167 "Offloading entry for target region in %0 is incorrect: either the " 4168 "address or the ID is invalid."); 4169 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4170 continue; 4171 } 4172 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4173 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4174 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4175 OffloadEntryInfoDeviceGlobalVar>( 4176 std::get<0>(E))) { 4177 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4178 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4179 CE->getFlags()); 4180 switch (Flags) { 4181 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4182 if (CGM.getLangOpts().OpenMPIsDevice && 4183 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4184 continue; 4185 if (!CE->getAddress()) { 4186 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4187 DiagnosticsEngine::Error, "Offloading entry for declare target " 4188 "variable %0 is incorrect: the " 4189 "address is invalid."); 4190 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4191 continue; 4192 } 4193 // The vaiable has no definition - no need to add the entry. 4194 if (CE->getVarSize().isZero()) 4195 continue; 4196 break; 4197 } 4198 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4199 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4200 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4201 "Declaret target link address is set."); 4202 if (CGM.getLangOpts().OpenMPIsDevice) 4203 continue; 4204 if (!CE->getAddress()) { 4205 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4206 DiagnosticsEngine::Error, 4207 "Offloading entry for declare target variable is incorrect: the " 4208 "address is invalid."); 4209 CGM.getDiags().Report(DiagID); 4210 continue; 4211 } 4212 break; 4213 } 4214 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4215 CE->getVarSize().getQuantity(), Flags, 4216 CE->getLinkage()); 4217 } else { 4218 llvm_unreachable("Unsupported entry kind."); 4219 } 4220 } 4221 } 4222 4223 /// Loads all the offload entries information from the host IR 4224 /// metadata. 4225 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4226 // If we are in target mode, load the metadata from the host IR. This code has 4227 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4228 4229 if (!CGM.getLangOpts().OpenMPIsDevice) 4230 return; 4231 4232 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4233 return; 4234 4235 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4236 if (auto EC = Buf.getError()) { 4237 CGM.getDiags().Report(diag::err_cannot_open_file) 4238 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4239 return; 4240 } 4241 4242 llvm::LLVMContext C; 4243 auto ME = expectedToErrorOrAndEmitErrors( 4244 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4245 4246 if (auto EC = ME.getError()) { 4247 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4248 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4249 CGM.getDiags().Report(DiagID) 4250 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4251 return; 4252 } 4253 4254 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4255 if (!MD) 4256 return; 4257 4258 for (llvm::MDNode *MN : MD->operands()) { 4259 auto &&GetMDInt = [MN](unsigned Idx) { 4260 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4261 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4262 }; 4263 4264 auto &&GetMDString = [MN](unsigned Idx) { 4265 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4266 return V->getString(); 4267 }; 4268 4269 switch (GetMDInt(0)) { 4270 default: 4271 llvm_unreachable("Unexpected metadata!"); 4272 break; 4273 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4274 OffloadingEntryInfoTargetRegion: 4275 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4276 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4277 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4278 /*Order=*/GetMDInt(5)); 4279 break; 4280 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4281 OffloadingEntryInfoDeviceGlobalVar: 4282 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4283 /*MangledName=*/GetMDString(1), 4284 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4285 /*Flags=*/GetMDInt(2)), 4286 /*Order=*/GetMDInt(3)); 4287 break; 4288 } 4289 } 4290 } 4291 4292 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4293 if (!KmpRoutineEntryPtrTy) { 4294 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4295 ASTContext &C = CGM.getContext(); 4296 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4297 FunctionProtoType::ExtProtoInfo EPI; 4298 KmpRoutineEntryPtrQTy = C.getPointerType( 4299 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4300 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4301 } 4302 } 4303 4304 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4305 // Make sure the type of the entry is already created. This is the type we 4306 // have to create: 4307 // struct __tgt_offload_entry{ 4308 // void *addr; // Pointer to the offload entry info. 4309 // // (function or global) 4310 // char *name; // Name of the function or global. 4311 // size_t size; // Size of the entry info (0 if it a function). 4312 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4313 // int32_t reserved; // Reserved, to use by the runtime library. 4314 // }; 4315 if (TgtOffloadEntryQTy.isNull()) { 4316 ASTContext &C = CGM.getContext(); 4317 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4318 RD->startDefinition(); 4319 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4320 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4321 addFieldToRecordDecl(C, RD, C.getSizeType()); 4322 addFieldToRecordDecl( 4323 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4324 addFieldToRecordDecl( 4325 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4326 RD->completeDefinition(); 4327 RD->addAttr(PackedAttr::CreateImplicit(C)); 4328 TgtOffloadEntryQTy = C.getRecordType(RD); 4329 } 4330 return TgtOffloadEntryQTy; 4331 } 4332 4333 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 4334 // These are the types we need to build: 4335 // struct __tgt_device_image{ 4336 // void *ImageStart; // Pointer to the target code start. 4337 // void *ImageEnd; // Pointer to the target code end. 4338 // // We also add the host entries to the device image, as it may be useful 4339 // // for the target runtime to have access to that information. 4340 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 4341 // // the entries. 4342 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4343 // // entries (non inclusive). 4344 // }; 4345 if (TgtDeviceImageQTy.isNull()) { 4346 ASTContext &C = CGM.getContext(); 4347 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image"); 4348 RD->startDefinition(); 4349 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4350 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4351 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4352 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4353 RD->completeDefinition(); 4354 TgtDeviceImageQTy = C.getRecordType(RD); 4355 } 4356 return TgtDeviceImageQTy; 4357 } 4358 4359 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 4360 // struct __tgt_bin_desc{ 4361 // int32_t NumDevices; // Number of devices supported. 4362 // __tgt_device_image *DeviceImages; // Arrays of device images 4363 // // (one per device). 4364 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 4365 // // entries. 4366 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4367 // // entries (non inclusive). 4368 // }; 4369 if (TgtBinaryDescriptorQTy.isNull()) { 4370 ASTContext &C = CGM.getContext(); 4371 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc"); 4372 RD->startDefinition(); 4373 addFieldToRecordDecl( 4374 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4375 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 4376 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4377 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4378 RD->completeDefinition(); 4379 TgtBinaryDescriptorQTy = C.getRecordType(RD); 4380 } 4381 return TgtBinaryDescriptorQTy; 4382 } 4383 4384 namespace { 4385 struct PrivateHelpersTy { 4386 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4387 const VarDecl *PrivateElemInit) 4388 : Original(Original), PrivateCopy(PrivateCopy), 4389 PrivateElemInit(PrivateElemInit) {} 4390 const VarDecl *Original; 4391 const VarDecl *PrivateCopy; 4392 const VarDecl *PrivateElemInit; 4393 }; 4394 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4395 } // anonymous namespace 4396 4397 static RecordDecl * 4398 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4399 if (!Privates.empty()) { 4400 ASTContext &C = CGM.getContext(); 4401 // Build struct .kmp_privates_t. { 4402 // /* private vars */ 4403 // }; 4404 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4405 RD->startDefinition(); 4406 for (const auto &Pair : Privates) { 4407 const VarDecl *VD = Pair.second.Original; 4408 QualType Type = VD->getType().getNonReferenceType(); 4409 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4410 if (VD->hasAttrs()) { 4411 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4412 E(VD->getAttrs().end()); 4413 I != E; ++I) 4414 FD->addAttr(*I); 4415 } 4416 } 4417 RD->completeDefinition(); 4418 return RD; 4419 } 4420 return nullptr; 4421 } 4422 4423 static RecordDecl * 4424 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4425 QualType KmpInt32Ty, 4426 QualType KmpRoutineEntryPointerQTy) { 4427 ASTContext &C = CGM.getContext(); 4428 // Build struct kmp_task_t { 4429 // void * shareds; 4430 // kmp_routine_entry_t routine; 4431 // kmp_int32 part_id; 4432 // kmp_cmplrdata_t data1; 4433 // kmp_cmplrdata_t data2; 4434 // For taskloops additional fields: 4435 // kmp_uint64 lb; 4436 // kmp_uint64 ub; 4437 // kmp_int64 st; 4438 // kmp_int32 liter; 4439 // void * reductions; 4440 // }; 4441 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4442 UD->startDefinition(); 4443 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4444 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4445 UD->completeDefinition(); 4446 QualType KmpCmplrdataTy = C.getRecordType(UD); 4447 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4448 RD->startDefinition(); 4449 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4450 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4451 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4452 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4453 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4454 if (isOpenMPTaskLoopDirective(Kind)) { 4455 QualType KmpUInt64Ty = 4456 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4457 QualType KmpInt64Ty = 4458 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4459 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4460 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4461 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4462 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4463 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4464 } 4465 RD->completeDefinition(); 4466 return RD; 4467 } 4468 4469 static RecordDecl * 4470 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4471 ArrayRef<PrivateDataTy> Privates) { 4472 ASTContext &C = CGM.getContext(); 4473 // Build struct kmp_task_t_with_privates { 4474 // kmp_task_t task_data; 4475 // .kmp_privates_t. privates; 4476 // }; 4477 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4478 RD->startDefinition(); 4479 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4480 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4481 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4482 RD->completeDefinition(); 4483 return RD; 4484 } 4485 4486 /// Emit a proxy function which accepts kmp_task_t as the second 4487 /// argument. 4488 /// \code 4489 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4490 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4491 /// For taskloops: 4492 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4493 /// tt->reductions, tt->shareds); 4494 /// return 0; 4495 /// } 4496 /// \endcode 4497 static llvm::Function * 4498 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4499 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4500 QualType KmpTaskTWithPrivatesPtrQTy, 4501 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4502 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4503 llvm::Value *TaskPrivatesMap) { 4504 ASTContext &C = CGM.getContext(); 4505 FunctionArgList Args; 4506 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4507 ImplicitParamDecl::Other); 4508 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4509 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4510 ImplicitParamDecl::Other); 4511 Args.push_back(&GtidArg); 4512 Args.push_back(&TaskTypeArg); 4513 const auto &TaskEntryFnInfo = 4514 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4515 llvm::FunctionType *TaskEntryTy = 4516 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4517 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4518 auto *TaskEntry = llvm::Function::Create( 4519 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4520 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4521 TaskEntry->setDoesNotRecurse(); 4522 CodeGenFunction CGF(CGM); 4523 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4524 Loc, Loc); 4525 4526 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4527 // tt, 4528 // For taskloops: 4529 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4530 // tt->task_data.shareds); 4531 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4532 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4533 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4534 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4535 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4536 const auto *KmpTaskTWithPrivatesQTyRD = 4537 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4538 LValue Base = 4539 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4540 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4541 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4542 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4543 llvm::Value *PartidParam = PartIdLVal.getPointer(); 4544 4545 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4546 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4547 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4548 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4549 CGF.ConvertTypeForMem(SharedsPtrTy)); 4550 4551 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4552 llvm::Value *PrivatesParam; 4553 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4554 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4555 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4556 PrivatesLVal.getPointer(), CGF.VoidPtrTy); 4557 } else { 4558 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4559 } 4560 4561 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4562 TaskPrivatesMap, 4563 CGF.Builder 4564 .CreatePointerBitCastOrAddrSpaceCast( 4565 TDBase.getAddress(), CGF.VoidPtrTy) 4566 .getPointer()}; 4567 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4568 std::end(CommonArgs)); 4569 if (isOpenMPTaskLoopDirective(Kind)) { 4570 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4571 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4572 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4573 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4574 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4575 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4576 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4577 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4578 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4579 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4580 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4581 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4582 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4583 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4584 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4585 CallArgs.push_back(LBParam); 4586 CallArgs.push_back(UBParam); 4587 CallArgs.push_back(StParam); 4588 CallArgs.push_back(LIParam); 4589 CallArgs.push_back(RParam); 4590 } 4591 CallArgs.push_back(SharedsParam); 4592 4593 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4594 CallArgs); 4595 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4596 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4597 CGF.FinishFunction(); 4598 return TaskEntry; 4599 } 4600 4601 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4602 SourceLocation Loc, 4603 QualType KmpInt32Ty, 4604 QualType KmpTaskTWithPrivatesPtrQTy, 4605 QualType KmpTaskTWithPrivatesQTy) { 4606 ASTContext &C = CGM.getContext(); 4607 FunctionArgList Args; 4608 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4609 ImplicitParamDecl::Other); 4610 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4611 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4612 ImplicitParamDecl::Other); 4613 Args.push_back(&GtidArg); 4614 Args.push_back(&TaskTypeArg); 4615 const auto &DestructorFnInfo = 4616 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4617 llvm::FunctionType *DestructorFnTy = 4618 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4619 std::string Name = 4620 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4621 auto *DestructorFn = 4622 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4623 Name, &CGM.getModule()); 4624 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4625 DestructorFnInfo); 4626 DestructorFn->setDoesNotRecurse(); 4627 CodeGenFunction CGF(CGM); 4628 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4629 Args, Loc, Loc); 4630 4631 LValue Base = CGF.EmitLoadOfPointerLValue( 4632 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4633 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4634 const auto *KmpTaskTWithPrivatesQTyRD = 4635 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4636 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4637 Base = CGF.EmitLValueForField(Base, *FI); 4638 for (const auto *Field : 4639 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4640 if (QualType::DestructionKind DtorKind = 4641 Field->getType().isDestructedType()) { 4642 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4643 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); 4644 } 4645 } 4646 CGF.FinishFunction(); 4647 return DestructorFn; 4648 } 4649 4650 /// Emit a privates mapping function for correct handling of private and 4651 /// firstprivate variables. 4652 /// \code 4653 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4654 /// **noalias priv1,..., <tyn> **noalias privn) { 4655 /// *priv1 = &.privates.priv1; 4656 /// ...; 4657 /// *privn = &.privates.privn; 4658 /// } 4659 /// \endcode 4660 static llvm::Value * 4661 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4662 ArrayRef<const Expr *> PrivateVars, 4663 ArrayRef<const Expr *> FirstprivateVars, 4664 ArrayRef<const Expr *> LastprivateVars, 4665 QualType PrivatesQTy, 4666 ArrayRef<PrivateDataTy> Privates) { 4667 ASTContext &C = CGM.getContext(); 4668 FunctionArgList Args; 4669 ImplicitParamDecl TaskPrivatesArg( 4670 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4671 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4672 ImplicitParamDecl::Other); 4673 Args.push_back(&TaskPrivatesArg); 4674 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4675 unsigned Counter = 1; 4676 for (const Expr *E : PrivateVars) { 4677 Args.push_back(ImplicitParamDecl::Create( 4678 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4679 C.getPointerType(C.getPointerType(E->getType())) 4680 .withConst() 4681 .withRestrict(), 4682 ImplicitParamDecl::Other)); 4683 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4684 PrivateVarsPos[VD] = Counter; 4685 ++Counter; 4686 } 4687 for (const Expr *E : FirstprivateVars) { 4688 Args.push_back(ImplicitParamDecl::Create( 4689 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4690 C.getPointerType(C.getPointerType(E->getType())) 4691 .withConst() 4692 .withRestrict(), 4693 ImplicitParamDecl::Other)); 4694 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4695 PrivateVarsPos[VD] = Counter; 4696 ++Counter; 4697 } 4698 for (const Expr *E : LastprivateVars) { 4699 Args.push_back(ImplicitParamDecl::Create( 4700 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4701 C.getPointerType(C.getPointerType(E->getType())) 4702 .withConst() 4703 .withRestrict(), 4704 ImplicitParamDecl::Other)); 4705 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4706 PrivateVarsPos[VD] = Counter; 4707 ++Counter; 4708 } 4709 const auto &TaskPrivatesMapFnInfo = 4710 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4711 llvm::FunctionType *TaskPrivatesMapTy = 4712 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4713 std::string Name = 4714 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4715 auto *TaskPrivatesMap = llvm::Function::Create( 4716 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4717 &CGM.getModule()); 4718 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4719 TaskPrivatesMapFnInfo); 4720 if (CGM.getLangOpts().Optimize) { 4721 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4722 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4723 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4724 } 4725 CodeGenFunction CGF(CGM); 4726 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4727 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4728 4729 // *privi = &.privates.privi; 4730 LValue Base = CGF.EmitLoadOfPointerLValue( 4731 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4732 TaskPrivatesArg.getType()->castAs<PointerType>()); 4733 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4734 Counter = 0; 4735 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4736 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4737 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4738 LValue RefLVal = 4739 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4740 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4741 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>()); 4742 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal); 4743 ++Counter; 4744 } 4745 CGF.FinishFunction(); 4746 return TaskPrivatesMap; 4747 } 4748 4749 /// Emit initialization for private variables in task-based directives. 4750 static void emitPrivatesInit(CodeGenFunction &CGF, 4751 const OMPExecutableDirective &D, 4752 Address KmpTaskSharedsPtr, LValue TDBase, 4753 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4754 QualType SharedsTy, QualType SharedsPtrTy, 4755 const OMPTaskDataTy &Data, 4756 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4757 ASTContext &C = CGF.getContext(); 4758 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4759 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4760 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4761 ? OMPD_taskloop 4762 : OMPD_task; 4763 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4764 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4765 LValue SrcBase; 4766 bool IsTargetTask = 4767 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4768 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4769 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4770 // PointersArray and SizesArray. The original variables for these arrays are 4771 // not captured and we get their addresses explicitly. 4772 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4773 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4774 SrcBase = CGF.MakeAddrLValue( 4775 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4776 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4777 SharedsTy); 4778 } 4779 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4780 for (const PrivateDataTy &Pair : Privates) { 4781 const VarDecl *VD = Pair.second.PrivateCopy; 4782 const Expr *Init = VD->getAnyInitializer(); 4783 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4784 !CGF.isTrivialInitializer(Init)))) { 4785 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4786 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4787 const VarDecl *OriginalVD = Pair.second.Original; 4788 // Check if the variable is the target-based BasePointersArray, 4789 // PointersArray or SizesArray. 4790 LValue SharedRefLValue; 4791 QualType Type = PrivateLValue.getType(); 4792 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4793 if (IsTargetTask && !SharedField) { 4794 assert(isa<ImplicitParamDecl>(OriginalVD) && 4795 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4796 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4797 ->getNumParams() == 0 && 4798 isa<TranslationUnitDecl>( 4799 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4800 ->getDeclContext()) && 4801 "Expected artificial target data variable."); 4802 SharedRefLValue = 4803 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4804 } else { 4805 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4806 SharedRefLValue = CGF.MakeAddrLValue( 4807 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), 4808 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4809 SharedRefLValue.getTBAAInfo()); 4810 } 4811 if (Type->isArrayType()) { 4812 // Initialize firstprivate array. 4813 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4814 // Perform simple memcpy. 4815 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4816 } else { 4817 // Initialize firstprivate array using element-by-element 4818 // initialization. 4819 CGF.EmitOMPAggregateAssign( 4820 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type, 4821 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4822 Address SrcElement) { 4823 // Clean up any temporaries needed by the initialization. 4824 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4825 InitScope.addPrivate( 4826 Elem, [SrcElement]() -> Address { return SrcElement; }); 4827 (void)InitScope.Privatize(); 4828 // Emit initialization for single element. 4829 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4830 CGF, &CapturesInfo); 4831 CGF.EmitAnyExprToMem(Init, DestElement, 4832 Init->getType().getQualifiers(), 4833 /*IsInitializer=*/false); 4834 }); 4835 } 4836 } else { 4837 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4838 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address { 4839 return SharedRefLValue.getAddress(); 4840 }); 4841 (void)InitScope.Privatize(); 4842 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4843 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4844 /*capturedByInit=*/false); 4845 } 4846 } else { 4847 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4848 } 4849 } 4850 ++FI; 4851 } 4852 } 4853 4854 /// Check if duplication function is required for taskloops. 4855 static bool checkInitIsRequired(CodeGenFunction &CGF, 4856 ArrayRef<PrivateDataTy> Privates) { 4857 bool InitRequired = false; 4858 for (const PrivateDataTy &Pair : Privates) { 4859 const VarDecl *VD = Pair.second.PrivateCopy; 4860 const Expr *Init = VD->getAnyInitializer(); 4861 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4862 !CGF.isTrivialInitializer(Init)); 4863 if (InitRequired) 4864 break; 4865 } 4866 return InitRequired; 4867 } 4868 4869 4870 /// Emit task_dup function (for initialization of 4871 /// private/firstprivate/lastprivate vars and last_iter flag) 4872 /// \code 4873 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4874 /// lastpriv) { 4875 /// // setup lastprivate flag 4876 /// task_dst->last = lastpriv; 4877 /// // could be constructor calls here... 4878 /// } 4879 /// \endcode 4880 static llvm::Value * 4881 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4882 const OMPExecutableDirective &D, 4883 QualType KmpTaskTWithPrivatesPtrQTy, 4884 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4885 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4886 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4887 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4888 ASTContext &C = CGM.getContext(); 4889 FunctionArgList Args; 4890 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4891 KmpTaskTWithPrivatesPtrQTy, 4892 ImplicitParamDecl::Other); 4893 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4894 KmpTaskTWithPrivatesPtrQTy, 4895 ImplicitParamDecl::Other); 4896 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4897 ImplicitParamDecl::Other); 4898 Args.push_back(&DstArg); 4899 Args.push_back(&SrcArg); 4900 Args.push_back(&LastprivArg); 4901 const auto &TaskDupFnInfo = 4902 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4903 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4904 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4905 auto *TaskDup = llvm::Function::Create( 4906 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4907 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4908 TaskDup->setDoesNotRecurse(); 4909 CodeGenFunction CGF(CGM); 4910 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4911 Loc); 4912 4913 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4914 CGF.GetAddrOfLocalVar(&DstArg), 4915 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4916 // task_dst->liter = lastpriv; 4917 if (WithLastIter) { 4918 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4919 LValue Base = CGF.EmitLValueForField( 4920 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4921 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4922 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4923 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4924 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4925 } 4926 4927 // Emit initial values for private copies (if any). 4928 assert(!Privates.empty()); 4929 Address KmpTaskSharedsPtr = Address::invalid(); 4930 if (!Data.FirstprivateVars.empty()) { 4931 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4932 CGF.GetAddrOfLocalVar(&SrcArg), 4933 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4934 LValue Base = CGF.EmitLValueForField( 4935 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4936 KmpTaskSharedsPtr = Address( 4937 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4938 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4939 KmpTaskTShareds)), 4940 Loc), 4941 CGF.getNaturalTypeAlignment(SharedsTy)); 4942 } 4943 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4944 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4945 CGF.FinishFunction(); 4946 return TaskDup; 4947 } 4948 4949 /// Checks if destructor function is required to be generated. 4950 /// \return true if cleanups are required, false otherwise. 4951 static bool 4952 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4953 bool NeedsCleanup = false; 4954 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4955 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4956 for (const FieldDecl *FD : PrivateRD->fields()) { 4957 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4958 if (NeedsCleanup) 4959 break; 4960 } 4961 return NeedsCleanup; 4962 } 4963 4964 CGOpenMPRuntime::TaskResultTy 4965 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4966 const OMPExecutableDirective &D, 4967 llvm::Function *TaskFunction, QualType SharedsTy, 4968 Address Shareds, const OMPTaskDataTy &Data) { 4969 ASTContext &C = CGM.getContext(); 4970 llvm::SmallVector<PrivateDataTy, 4> Privates; 4971 // Aggregate privates and sort them by the alignment. 4972 auto I = Data.PrivateCopies.begin(); 4973 for (const Expr *E : Data.PrivateVars) { 4974 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4975 Privates.emplace_back( 4976 C.getDeclAlign(VD), 4977 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4978 /*PrivateElemInit=*/nullptr)); 4979 ++I; 4980 } 4981 I = Data.FirstprivateCopies.begin(); 4982 auto IElemInitRef = Data.FirstprivateInits.begin(); 4983 for (const Expr *E : Data.FirstprivateVars) { 4984 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4985 Privates.emplace_back( 4986 C.getDeclAlign(VD), 4987 PrivateHelpersTy( 4988 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4989 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4990 ++I; 4991 ++IElemInitRef; 4992 } 4993 I = Data.LastprivateCopies.begin(); 4994 for (const Expr *E : Data.LastprivateVars) { 4995 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4996 Privates.emplace_back( 4997 C.getDeclAlign(VD), 4998 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4999 /*PrivateElemInit=*/nullptr)); 5000 ++I; 5001 } 5002 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 5003 return L.first > R.first; 5004 }); 5005 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 5006 // Build type kmp_routine_entry_t (if not built yet). 5007 emitKmpRoutineEntryT(KmpInt32Ty); 5008 // Build type kmp_task_t (if not built yet). 5009 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5010 if (SavedKmpTaskloopTQTy.isNull()) { 5011 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5012 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5013 } 5014 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5015 } else { 5016 assert((D.getDirectiveKind() == OMPD_task || 5017 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5018 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5019 "Expected taskloop, task or target directive"); 5020 if (SavedKmpTaskTQTy.isNull()) { 5021 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5022 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5023 } 5024 KmpTaskTQTy = SavedKmpTaskTQTy; 5025 } 5026 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5027 // Build particular struct kmp_task_t for the given task. 5028 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5029 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5030 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5031 QualType KmpTaskTWithPrivatesPtrQTy = 5032 C.getPointerType(KmpTaskTWithPrivatesQTy); 5033 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5034 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5035 KmpTaskTWithPrivatesTy->getPointerTo(); 5036 llvm::Value *KmpTaskTWithPrivatesTySize = 5037 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5038 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5039 5040 // Emit initial values for private copies (if any). 5041 llvm::Value *TaskPrivatesMap = nullptr; 5042 llvm::Type *TaskPrivatesMapTy = 5043 std::next(TaskFunction->arg_begin(), 3)->getType(); 5044 if (!Privates.empty()) { 5045 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5046 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5047 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5048 FI->getType(), Privates); 5049 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5050 TaskPrivatesMap, TaskPrivatesMapTy); 5051 } else { 5052 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5053 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5054 } 5055 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5056 // kmp_task_t *tt); 5057 llvm::Function *TaskEntry = emitProxyTaskFunction( 5058 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5059 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5060 TaskPrivatesMap); 5061 5062 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5063 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5064 // kmp_routine_entry_t *task_entry); 5065 // Task flags. Format is taken from 5066 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5067 // description of kmp_tasking_flags struct. 5068 enum { 5069 TiedFlag = 0x1, 5070 FinalFlag = 0x2, 5071 DestructorsFlag = 0x8, 5072 PriorityFlag = 0x20 5073 }; 5074 unsigned Flags = Data.Tied ? TiedFlag : 0; 5075 bool NeedsCleanup = false; 5076 if (!Privates.empty()) { 5077 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5078 if (NeedsCleanup) 5079 Flags = Flags | DestructorsFlag; 5080 } 5081 if (Data.Priority.getInt()) 5082 Flags = Flags | PriorityFlag; 5083 llvm::Value *TaskFlags = 5084 Data.Final.getPointer() 5085 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5086 CGF.Builder.getInt32(FinalFlag), 5087 CGF.Builder.getInt32(/*C=*/0)) 5088 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5089 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5090 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5091 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5092 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5093 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5094 TaskEntry, KmpRoutineEntryPtrTy)}; 5095 llvm::Value *NewTask; 5096 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5097 // Check if we have any device clause associated with the directive. 5098 const Expr *Device = nullptr; 5099 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5100 Device = C->getDevice(); 5101 // Emit device ID if any otherwise use default value. 5102 llvm::Value *DeviceID; 5103 if (Device) 5104 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5105 CGF.Int64Ty, /*isSigned=*/true); 5106 else 5107 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5108 AllocArgs.push_back(DeviceID); 5109 NewTask = CGF.EmitRuntimeCall( 5110 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5111 } else { 5112 NewTask = CGF.EmitRuntimeCall( 5113 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5114 } 5115 llvm::Value *NewTaskNewTaskTTy = 5116 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5117 NewTask, KmpTaskTWithPrivatesPtrTy); 5118 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5119 KmpTaskTWithPrivatesQTy); 5120 LValue TDBase = 5121 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5122 // Fill the data in the resulting kmp_task_t record. 5123 // Copy shareds if there are any. 5124 Address KmpTaskSharedsPtr = Address::invalid(); 5125 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5126 KmpTaskSharedsPtr = 5127 Address(CGF.EmitLoadOfScalar( 5128 CGF.EmitLValueForField( 5129 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5130 KmpTaskTShareds)), 5131 Loc), 5132 CGF.getNaturalTypeAlignment(SharedsTy)); 5133 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5134 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5135 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5136 } 5137 // Emit initial values for private copies (if any). 5138 TaskResultTy Result; 5139 if (!Privates.empty()) { 5140 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5141 SharedsTy, SharedsPtrTy, Data, Privates, 5142 /*ForDup=*/false); 5143 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5144 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5145 Result.TaskDupFn = emitTaskDupFunction( 5146 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5147 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5148 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5149 } 5150 } 5151 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5152 enum { Priority = 0, Destructors = 1 }; 5153 // Provide pointer to function with destructors for privates. 5154 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5155 const RecordDecl *KmpCmplrdataUD = 5156 (*FI)->getType()->getAsUnionType()->getDecl(); 5157 if (NeedsCleanup) { 5158 llvm::Value *DestructorFn = emitDestructorsFunction( 5159 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5160 KmpTaskTWithPrivatesQTy); 5161 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5162 LValue DestructorsLV = CGF.EmitLValueForField( 5163 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5164 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5165 DestructorFn, KmpRoutineEntryPtrTy), 5166 DestructorsLV); 5167 } 5168 // Set priority. 5169 if (Data.Priority.getInt()) { 5170 LValue Data2LV = CGF.EmitLValueForField( 5171 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5172 LValue PriorityLV = CGF.EmitLValueForField( 5173 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5174 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5175 } 5176 Result.NewTask = NewTask; 5177 Result.TaskEntry = TaskEntry; 5178 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5179 Result.TDBase = TDBase; 5180 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5181 return Result; 5182 } 5183 5184 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5185 const OMPExecutableDirective &D, 5186 llvm::Function *TaskFunction, 5187 QualType SharedsTy, Address Shareds, 5188 const Expr *IfCond, 5189 const OMPTaskDataTy &Data) { 5190 if (!CGF.HaveInsertPoint()) 5191 return; 5192 5193 TaskResultTy Result = 5194 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5195 llvm::Value *NewTask = Result.NewTask; 5196 llvm::Function *TaskEntry = Result.TaskEntry; 5197 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5198 LValue TDBase = Result.TDBase; 5199 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5200 ASTContext &C = CGM.getContext(); 5201 // Process list of dependences. 5202 Address DependenciesArray = Address::invalid(); 5203 unsigned NumDependencies = Data.Dependences.size(); 5204 if (NumDependencies) { 5205 // Dependence kind for RTL. 5206 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5207 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5208 RecordDecl *KmpDependInfoRD; 5209 QualType FlagsTy = 5210 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5211 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5212 if (KmpDependInfoTy.isNull()) { 5213 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5214 KmpDependInfoRD->startDefinition(); 5215 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5216 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5217 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5218 KmpDependInfoRD->completeDefinition(); 5219 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5220 } else { 5221 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5222 } 5223 // Define type kmp_depend_info[<Dependences.size()>]; 5224 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5225 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5226 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5227 // kmp_depend_info[<Dependences.size()>] deps; 5228 DependenciesArray = 5229 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5230 for (unsigned I = 0; I < NumDependencies; ++I) { 5231 const Expr *E = Data.Dependences[I].second; 5232 LValue Addr = CGF.EmitLValue(E); 5233 llvm::Value *Size; 5234 QualType Ty = E->getType(); 5235 if (const auto *ASE = 5236 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5237 LValue UpAddrLVal = 5238 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5239 llvm::Value *UpAddr = 5240 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1); 5241 llvm::Value *LowIntPtr = 5242 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy); 5243 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5244 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5245 } else { 5246 Size = CGF.getTypeSize(Ty); 5247 } 5248 LValue Base = CGF.MakeAddrLValue( 5249 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5250 KmpDependInfoTy); 5251 // deps[i].base_addr = &<Dependences[i].second>; 5252 LValue BaseAddrLVal = CGF.EmitLValueForField( 5253 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5254 CGF.EmitStoreOfScalar( 5255 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy), 5256 BaseAddrLVal); 5257 // deps[i].len = sizeof(<Dependences[i].second>); 5258 LValue LenLVal = CGF.EmitLValueForField( 5259 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5260 CGF.EmitStoreOfScalar(Size, LenLVal); 5261 // deps[i].flags = <Dependences[i].first>; 5262 RTLDependenceKindTy DepKind; 5263 switch (Data.Dependences[I].first) { 5264 case OMPC_DEPEND_in: 5265 DepKind = DepIn; 5266 break; 5267 // Out and InOut dependencies must use the same code. 5268 case OMPC_DEPEND_out: 5269 case OMPC_DEPEND_inout: 5270 DepKind = DepInOut; 5271 break; 5272 case OMPC_DEPEND_mutexinoutset: 5273 DepKind = DepMutexInOutSet; 5274 break; 5275 case OMPC_DEPEND_source: 5276 case OMPC_DEPEND_sink: 5277 case OMPC_DEPEND_unknown: 5278 llvm_unreachable("Unknown task dependence type"); 5279 } 5280 LValue FlagsLVal = CGF.EmitLValueForField( 5281 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5282 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5283 FlagsLVal); 5284 } 5285 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5286 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5287 } 5288 5289 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5290 // libcall. 5291 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5292 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5293 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5294 // list is not empty 5295 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5296 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5297 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5298 llvm::Value *DepTaskArgs[7]; 5299 if (NumDependencies) { 5300 DepTaskArgs[0] = UpLoc; 5301 DepTaskArgs[1] = ThreadID; 5302 DepTaskArgs[2] = NewTask; 5303 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5304 DepTaskArgs[4] = DependenciesArray.getPointer(); 5305 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5306 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5307 } 5308 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5309 &TaskArgs, 5310 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5311 if (!Data.Tied) { 5312 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5313 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5314 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5315 } 5316 if (NumDependencies) { 5317 CGF.EmitRuntimeCall( 5318 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5319 } else { 5320 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5321 TaskArgs); 5322 } 5323 // Check if parent region is untied and build return for untied task; 5324 if (auto *Region = 5325 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5326 Region->emitUntiedSwitch(CGF); 5327 }; 5328 5329 llvm::Value *DepWaitTaskArgs[6]; 5330 if (NumDependencies) { 5331 DepWaitTaskArgs[0] = UpLoc; 5332 DepWaitTaskArgs[1] = ThreadID; 5333 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5334 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5335 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5336 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5337 } 5338 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5339 NumDependencies, &DepWaitTaskArgs, 5340 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5341 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5342 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5343 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5344 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5345 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5346 // is specified. 5347 if (NumDependencies) 5348 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5349 DepWaitTaskArgs); 5350 // Call proxy_task_entry(gtid, new_task); 5351 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5352 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5353 Action.Enter(CGF); 5354 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5355 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5356 OutlinedFnArgs); 5357 }; 5358 5359 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5360 // kmp_task_t *new_task); 5361 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5362 // kmp_task_t *new_task); 5363 RegionCodeGenTy RCG(CodeGen); 5364 CommonActionTy Action( 5365 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5366 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5367 RCG.setAction(Action); 5368 RCG(CGF); 5369 }; 5370 5371 if (IfCond) { 5372 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5373 } else { 5374 RegionCodeGenTy ThenRCG(ThenCodeGen); 5375 ThenRCG(CGF); 5376 } 5377 } 5378 5379 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5380 const OMPLoopDirective &D, 5381 llvm::Function *TaskFunction, 5382 QualType SharedsTy, Address Shareds, 5383 const Expr *IfCond, 5384 const OMPTaskDataTy &Data) { 5385 if (!CGF.HaveInsertPoint()) 5386 return; 5387 TaskResultTy Result = 5388 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5389 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5390 // libcall. 5391 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5392 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5393 // sched, kmp_uint64 grainsize, void *task_dup); 5394 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5395 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5396 llvm::Value *IfVal; 5397 if (IfCond) { 5398 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5399 /*isSigned=*/true); 5400 } else { 5401 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5402 } 5403 5404 LValue LBLVal = CGF.EmitLValueForField( 5405 Result.TDBase, 5406 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5407 const auto *LBVar = 5408 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5409 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(), 5410 /*IsInitializer=*/true); 5411 LValue UBLVal = CGF.EmitLValueForField( 5412 Result.TDBase, 5413 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5414 const auto *UBVar = 5415 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5416 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(), 5417 /*IsInitializer=*/true); 5418 LValue StLVal = CGF.EmitLValueForField( 5419 Result.TDBase, 5420 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5421 const auto *StVar = 5422 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5423 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(), 5424 /*IsInitializer=*/true); 5425 // Store reductions address. 5426 LValue RedLVal = CGF.EmitLValueForField( 5427 Result.TDBase, 5428 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5429 if (Data.Reductions) { 5430 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5431 } else { 5432 CGF.EmitNullInitialization(RedLVal.getAddress(), 5433 CGF.getContext().VoidPtrTy); 5434 } 5435 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5436 llvm::Value *TaskArgs[] = { 5437 UpLoc, 5438 ThreadID, 5439 Result.NewTask, 5440 IfVal, 5441 LBLVal.getPointer(), 5442 UBLVal.getPointer(), 5443 CGF.EmitLoadOfScalar(StLVal, Loc), 5444 llvm::ConstantInt::getSigned( 5445 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5446 llvm::ConstantInt::getSigned( 5447 CGF.IntTy, Data.Schedule.getPointer() 5448 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5449 : NoSchedule), 5450 Data.Schedule.getPointer() 5451 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5452 /*isSigned=*/false) 5453 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5454 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5455 Result.TaskDupFn, CGF.VoidPtrTy) 5456 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5457 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5458 } 5459 5460 /// Emit reduction operation for each element of array (required for 5461 /// array sections) LHS op = RHS. 5462 /// \param Type Type of array. 5463 /// \param LHSVar Variable on the left side of the reduction operation 5464 /// (references element of array in original variable). 5465 /// \param RHSVar Variable on the right side of the reduction operation 5466 /// (references element of array in original variable). 5467 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5468 /// RHSVar. 5469 static void EmitOMPAggregateReduction( 5470 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5471 const VarDecl *RHSVar, 5472 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5473 const Expr *, const Expr *)> &RedOpGen, 5474 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5475 const Expr *UpExpr = nullptr) { 5476 // Perform element-by-element initialization. 5477 QualType ElementTy; 5478 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5479 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5480 5481 // Drill down to the base element type on both arrays. 5482 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5483 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5484 5485 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5486 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5487 // Cast from pointer to array type to pointer to single element. 5488 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5489 // The basic structure here is a while-do loop. 5490 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5491 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5492 llvm::Value *IsEmpty = 5493 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5494 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5495 5496 // Enter the loop body, making that address the current address. 5497 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5498 CGF.EmitBlock(BodyBB); 5499 5500 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5501 5502 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5503 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5504 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5505 Address RHSElementCurrent = 5506 Address(RHSElementPHI, 5507 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5508 5509 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5510 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5511 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5512 Address LHSElementCurrent = 5513 Address(LHSElementPHI, 5514 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5515 5516 // Emit copy. 5517 CodeGenFunction::OMPPrivateScope Scope(CGF); 5518 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5519 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5520 Scope.Privatize(); 5521 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5522 Scope.ForceCleanup(); 5523 5524 // Shift the address forward by one element. 5525 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5526 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5527 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5528 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5529 // Check whether we've reached the end. 5530 llvm::Value *Done = 5531 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5532 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5533 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5534 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5535 5536 // Done. 5537 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5538 } 5539 5540 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5541 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5542 /// UDR combiner function. 5543 static void emitReductionCombiner(CodeGenFunction &CGF, 5544 const Expr *ReductionOp) { 5545 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5546 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5547 if (const auto *DRE = 5548 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5549 if (const auto *DRD = 5550 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5551 std::pair<llvm::Function *, llvm::Function *> Reduction = 5552 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5553 RValue Func = RValue::get(Reduction.first); 5554 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5555 CGF.EmitIgnoredExpr(ReductionOp); 5556 return; 5557 } 5558 CGF.EmitIgnoredExpr(ReductionOp); 5559 } 5560 5561 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5562 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5563 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5564 ArrayRef<const Expr *> ReductionOps) { 5565 ASTContext &C = CGM.getContext(); 5566 5567 // void reduction_func(void *LHSArg, void *RHSArg); 5568 FunctionArgList Args; 5569 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5570 ImplicitParamDecl::Other); 5571 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5572 ImplicitParamDecl::Other); 5573 Args.push_back(&LHSArg); 5574 Args.push_back(&RHSArg); 5575 const auto &CGFI = 5576 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5577 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5578 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5579 llvm::GlobalValue::InternalLinkage, Name, 5580 &CGM.getModule()); 5581 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5582 Fn->setDoesNotRecurse(); 5583 CodeGenFunction CGF(CGM); 5584 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5585 5586 // Dst = (void*[n])(LHSArg); 5587 // Src = (void*[n])(RHSArg); 5588 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5589 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5590 ArgsType), CGF.getPointerAlign()); 5591 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5592 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5593 ArgsType), CGF.getPointerAlign()); 5594 5595 // ... 5596 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5597 // ... 5598 CodeGenFunction::OMPPrivateScope Scope(CGF); 5599 auto IPriv = Privates.begin(); 5600 unsigned Idx = 0; 5601 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5602 const auto *RHSVar = 5603 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5604 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5605 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5606 }); 5607 const auto *LHSVar = 5608 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5609 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5610 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5611 }); 5612 QualType PrivTy = (*IPriv)->getType(); 5613 if (PrivTy->isVariablyModifiedType()) { 5614 // Get array size and emit VLA type. 5615 ++Idx; 5616 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5617 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5618 const VariableArrayType *VLA = 5619 CGF.getContext().getAsVariableArrayType(PrivTy); 5620 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5621 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5622 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5623 CGF.EmitVariablyModifiedType(PrivTy); 5624 } 5625 } 5626 Scope.Privatize(); 5627 IPriv = Privates.begin(); 5628 auto ILHS = LHSExprs.begin(); 5629 auto IRHS = RHSExprs.begin(); 5630 for (const Expr *E : ReductionOps) { 5631 if ((*IPriv)->getType()->isArrayType()) { 5632 // Emit reduction for array section. 5633 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5634 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5635 EmitOMPAggregateReduction( 5636 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5637 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5638 emitReductionCombiner(CGF, E); 5639 }); 5640 } else { 5641 // Emit reduction for array subscript or single variable. 5642 emitReductionCombiner(CGF, E); 5643 } 5644 ++IPriv; 5645 ++ILHS; 5646 ++IRHS; 5647 } 5648 Scope.ForceCleanup(); 5649 CGF.FinishFunction(); 5650 return Fn; 5651 } 5652 5653 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5654 const Expr *ReductionOp, 5655 const Expr *PrivateRef, 5656 const DeclRefExpr *LHS, 5657 const DeclRefExpr *RHS) { 5658 if (PrivateRef->getType()->isArrayType()) { 5659 // Emit reduction for array section. 5660 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5661 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5662 EmitOMPAggregateReduction( 5663 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5664 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5665 emitReductionCombiner(CGF, ReductionOp); 5666 }); 5667 } else { 5668 // Emit reduction for array subscript or single variable. 5669 emitReductionCombiner(CGF, ReductionOp); 5670 } 5671 } 5672 5673 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5674 ArrayRef<const Expr *> Privates, 5675 ArrayRef<const Expr *> LHSExprs, 5676 ArrayRef<const Expr *> RHSExprs, 5677 ArrayRef<const Expr *> ReductionOps, 5678 ReductionOptionsTy Options) { 5679 if (!CGF.HaveInsertPoint()) 5680 return; 5681 5682 bool WithNowait = Options.WithNowait; 5683 bool SimpleReduction = Options.SimpleReduction; 5684 5685 // Next code should be emitted for reduction: 5686 // 5687 // static kmp_critical_name lock = { 0 }; 5688 // 5689 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5690 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5691 // ... 5692 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5693 // *(Type<n>-1*)rhs[<n>-1]); 5694 // } 5695 // 5696 // ... 5697 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5698 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5699 // RedList, reduce_func, &<lock>)) { 5700 // case 1: 5701 // ... 5702 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5703 // ... 5704 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5705 // break; 5706 // case 2: 5707 // ... 5708 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5709 // ... 5710 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5711 // break; 5712 // default:; 5713 // } 5714 // 5715 // if SimpleReduction is true, only the next code is generated: 5716 // ... 5717 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5718 // ... 5719 5720 ASTContext &C = CGM.getContext(); 5721 5722 if (SimpleReduction) { 5723 CodeGenFunction::RunCleanupsScope Scope(CGF); 5724 auto IPriv = Privates.begin(); 5725 auto ILHS = LHSExprs.begin(); 5726 auto IRHS = RHSExprs.begin(); 5727 for (const Expr *E : ReductionOps) { 5728 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5729 cast<DeclRefExpr>(*IRHS)); 5730 ++IPriv; 5731 ++ILHS; 5732 ++IRHS; 5733 } 5734 return; 5735 } 5736 5737 // 1. Build a list of reduction variables. 5738 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5739 auto Size = RHSExprs.size(); 5740 for (const Expr *E : Privates) { 5741 if (E->getType()->isVariablyModifiedType()) 5742 // Reserve place for array size. 5743 ++Size; 5744 } 5745 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5746 QualType ReductionArrayTy = 5747 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5748 /*IndexTypeQuals=*/0); 5749 Address ReductionList = 5750 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5751 auto IPriv = Privates.begin(); 5752 unsigned Idx = 0; 5753 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5754 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5755 CGF.Builder.CreateStore( 5756 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5757 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), 5758 Elem); 5759 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5760 // Store array size. 5761 ++Idx; 5762 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5763 llvm::Value *Size = CGF.Builder.CreateIntCast( 5764 CGF.getVLASize( 5765 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5766 .NumElts, 5767 CGF.SizeTy, /*isSigned=*/false); 5768 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5769 Elem); 5770 } 5771 } 5772 5773 // 2. Emit reduce_func(). 5774 llvm::Function *ReductionFn = emitReductionFunction( 5775 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5776 LHSExprs, RHSExprs, ReductionOps); 5777 5778 // 3. Create static kmp_critical_name lock = { 0 }; 5779 std::string Name = getName({"reduction"}); 5780 llvm::Value *Lock = getCriticalRegionLock(Name); 5781 5782 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5783 // RedList, reduce_func, &<lock>); 5784 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5785 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5786 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5787 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5788 ReductionList.getPointer(), CGF.VoidPtrTy); 5789 llvm::Value *Args[] = { 5790 IdentTLoc, // ident_t *<loc> 5791 ThreadId, // i32 <gtid> 5792 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5793 ReductionArrayTySize, // size_type sizeof(RedList) 5794 RL, // void *RedList 5795 ReductionFn, // void (*) (void *, void *) <reduce_func> 5796 Lock // kmp_critical_name *&<lock> 5797 }; 5798 llvm::Value *Res = CGF.EmitRuntimeCall( 5799 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5800 : OMPRTL__kmpc_reduce), 5801 Args); 5802 5803 // 5. Build switch(res) 5804 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5805 llvm::SwitchInst *SwInst = 5806 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5807 5808 // 6. Build case 1: 5809 // ... 5810 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5811 // ... 5812 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5813 // break; 5814 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5815 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5816 CGF.EmitBlock(Case1BB); 5817 5818 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5819 llvm::Value *EndArgs[] = { 5820 IdentTLoc, // ident_t *<loc> 5821 ThreadId, // i32 <gtid> 5822 Lock // kmp_critical_name *&<lock> 5823 }; 5824 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5825 CodeGenFunction &CGF, PrePostActionTy &Action) { 5826 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5827 auto IPriv = Privates.begin(); 5828 auto ILHS = LHSExprs.begin(); 5829 auto IRHS = RHSExprs.begin(); 5830 for (const Expr *E : ReductionOps) { 5831 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5832 cast<DeclRefExpr>(*IRHS)); 5833 ++IPriv; 5834 ++ILHS; 5835 ++IRHS; 5836 } 5837 }; 5838 RegionCodeGenTy RCG(CodeGen); 5839 CommonActionTy Action( 5840 nullptr, llvm::None, 5841 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5842 : OMPRTL__kmpc_end_reduce), 5843 EndArgs); 5844 RCG.setAction(Action); 5845 RCG(CGF); 5846 5847 CGF.EmitBranch(DefaultBB); 5848 5849 // 7. Build case 2: 5850 // ... 5851 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5852 // ... 5853 // break; 5854 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5855 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5856 CGF.EmitBlock(Case2BB); 5857 5858 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5859 CodeGenFunction &CGF, PrePostActionTy &Action) { 5860 auto ILHS = LHSExprs.begin(); 5861 auto IRHS = RHSExprs.begin(); 5862 auto IPriv = Privates.begin(); 5863 for (const Expr *E : ReductionOps) { 5864 const Expr *XExpr = nullptr; 5865 const Expr *EExpr = nullptr; 5866 const Expr *UpExpr = nullptr; 5867 BinaryOperatorKind BO = BO_Comma; 5868 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5869 if (BO->getOpcode() == BO_Assign) { 5870 XExpr = BO->getLHS(); 5871 UpExpr = BO->getRHS(); 5872 } 5873 } 5874 // Try to emit update expression as a simple atomic. 5875 const Expr *RHSExpr = UpExpr; 5876 if (RHSExpr) { 5877 // Analyze RHS part of the whole expression. 5878 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5879 RHSExpr->IgnoreParenImpCasts())) { 5880 // If this is a conditional operator, analyze its condition for 5881 // min/max reduction operator. 5882 RHSExpr = ACO->getCond(); 5883 } 5884 if (const auto *BORHS = 5885 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5886 EExpr = BORHS->getRHS(); 5887 BO = BORHS->getOpcode(); 5888 } 5889 } 5890 if (XExpr) { 5891 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5892 auto &&AtomicRedGen = [BO, VD, 5893 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5894 const Expr *EExpr, const Expr *UpExpr) { 5895 LValue X = CGF.EmitLValue(XExpr); 5896 RValue E; 5897 if (EExpr) 5898 E = CGF.EmitAnyExpr(EExpr); 5899 CGF.EmitOMPAtomicSimpleUpdateExpr( 5900 X, E, BO, /*IsXLHSInRHSPart=*/true, 5901 llvm::AtomicOrdering::Monotonic, Loc, 5902 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5903 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5904 PrivateScope.addPrivate( 5905 VD, [&CGF, VD, XRValue, Loc]() { 5906 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5907 CGF.emitOMPSimpleStore( 5908 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5909 VD->getType().getNonReferenceType(), Loc); 5910 return LHSTemp; 5911 }); 5912 (void)PrivateScope.Privatize(); 5913 return CGF.EmitAnyExpr(UpExpr); 5914 }); 5915 }; 5916 if ((*IPriv)->getType()->isArrayType()) { 5917 // Emit atomic reduction for array section. 5918 const auto *RHSVar = 5919 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5920 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5921 AtomicRedGen, XExpr, EExpr, UpExpr); 5922 } else { 5923 // Emit atomic reduction for array subscript or single variable. 5924 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5925 } 5926 } else { 5927 // Emit as a critical region. 5928 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5929 const Expr *, const Expr *) { 5930 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5931 std::string Name = RT.getName({"atomic_reduction"}); 5932 RT.emitCriticalRegion( 5933 CGF, Name, 5934 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5935 Action.Enter(CGF); 5936 emitReductionCombiner(CGF, E); 5937 }, 5938 Loc); 5939 }; 5940 if ((*IPriv)->getType()->isArrayType()) { 5941 const auto *LHSVar = 5942 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5943 const auto *RHSVar = 5944 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5945 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5946 CritRedGen); 5947 } else { 5948 CritRedGen(CGF, nullptr, nullptr, nullptr); 5949 } 5950 } 5951 ++ILHS; 5952 ++IRHS; 5953 ++IPriv; 5954 } 5955 }; 5956 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5957 if (!WithNowait) { 5958 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5959 llvm::Value *EndArgs[] = { 5960 IdentTLoc, // ident_t *<loc> 5961 ThreadId, // i32 <gtid> 5962 Lock // kmp_critical_name *&<lock> 5963 }; 5964 CommonActionTy Action(nullptr, llvm::None, 5965 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 5966 EndArgs); 5967 AtomicRCG.setAction(Action); 5968 AtomicRCG(CGF); 5969 } else { 5970 AtomicRCG(CGF); 5971 } 5972 5973 CGF.EmitBranch(DefaultBB); 5974 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5975 } 5976 5977 /// Generates unique name for artificial threadprivate variables. 5978 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5979 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5980 const Expr *Ref) { 5981 SmallString<256> Buffer; 5982 llvm::raw_svector_ostream Out(Buffer); 5983 const clang::DeclRefExpr *DE; 5984 const VarDecl *D = ::getBaseDecl(Ref, DE); 5985 if (!D) 5986 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5987 D = D->getCanonicalDecl(); 5988 std::string Name = CGM.getOpenMPRuntime().getName( 5989 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5990 Out << Prefix << Name << "_" 5991 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5992 return Out.str(); 5993 } 5994 5995 /// Emits reduction initializer function: 5996 /// \code 5997 /// void @.red_init(void* %arg) { 5998 /// %0 = bitcast void* %arg to <type>* 5999 /// store <type> <init>, <type>* %0 6000 /// ret void 6001 /// } 6002 /// \endcode 6003 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 6004 SourceLocation Loc, 6005 ReductionCodeGen &RCG, unsigned N) { 6006 ASTContext &C = CGM.getContext(); 6007 FunctionArgList Args; 6008 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6009 ImplicitParamDecl::Other); 6010 Args.emplace_back(&Param); 6011 const auto &FnInfo = 6012 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6013 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6014 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6015 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6016 Name, &CGM.getModule()); 6017 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6018 Fn->setDoesNotRecurse(); 6019 CodeGenFunction CGF(CGM); 6020 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6021 Address PrivateAddr = CGF.EmitLoadOfPointer( 6022 CGF.GetAddrOfLocalVar(&Param), 6023 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6024 llvm::Value *Size = nullptr; 6025 // If the size of the reduction item is non-constant, load it from global 6026 // threadprivate variable. 6027 if (RCG.getSizes(N).second) { 6028 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6029 CGF, CGM.getContext().getSizeType(), 6030 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6031 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6032 CGM.getContext().getSizeType(), Loc); 6033 } 6034 RCG.emitAggregateType(CGF, N, Size); 6035 LValue SharedLVal; 6036 // If initializer uses initializer from declare reduction construct, emit a 6037 // pointer to the address of the original reduction item (reuired by reduction 6038 // initializer) 6039 if (RCG.usesReductionInitializer(N)) { 6040 Address SharedAddr = 6041 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6042 CGF, CGM.getContext().VoidPtrTy, 6043 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6044 SharedAddr = CGF.EmitLoadOfPointer( 6045 SharedAddr, 6046 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6047 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6048 } else { 6049 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6050 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6051 CGM.getContext().VoidPtrTy); 6052 } 6053 // Emit the initializer: 6054 // %0 = bitcast void* %arg to <type>* 6055 // store <type> <init>, <type>* %0 6056 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6057 [](CodeGenFunction &) { return false; }); 6058 CGF.FinishFunction(); 6059 return Fn; 6060 } 6061 6062 /// Emits reduction combiner function: 6063 /// \code 6064 /// void @.red_comb(void* %arg0, void* %arg1) { 6065 /// %lhs = bitcast void* %arg0 to <type>* 6066 /// %rhs = bitcast void* %arg1 to <type>* 6067 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6068 /// store <type> %2, <type>* %lhs 6069 /// ret void 6070 /// } 6071 /// \endcode 6072 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6073 SourceLocation Loc, 6074 ReductionCodeGen &RCG, unsigned N, 6075 const Expr *ReductionOp, 6076 const Expr *LHS, const Expr *RHS, 6077 const Expr *PrivateRef) { 6078 ASTContext &C = CGM.getContext(); 6079 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6080 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6081 FunctionArgList Args; 6082 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6083 C.VoidPtrTy, ImplicitParamDecl::Other); 6084 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6085 ImplicitParamDecl::Other); 6086 Args.emplace_back(&ParamInOut); 6087 Args.emplace_back(&ParamIn); 6088 const auto &FnInfo = 6089 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6090 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6091 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6092 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6093 Name, &CGM.getModule()); 6094 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6095 Fn->setDoesNotRecurse(); 6096 CodeGenFunction CGF(CGM); 6097 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6098 llvm::Value *Size = nullptr; 6099 // If the size of the reduction item is non-constant, load it from global 6100 // threadprivate variable. 6101 if (RCG.getSizes(N).second) { 6102 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6103 CGF, CGM.getContext().getSizeType(), 6104 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6105 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6106 CGM.getContext().getSizeType(), Loc); 6107 } 6108 RCG.emitAggregateType(CGF, N, Size); 6109 // Remap lhs and rhs variables to the addresses of the function arguments. 6110 // %lhs = bitcast void* %arg0 to <type>* 6111 // %rhs = bitcast void* %arg1 to <type>* 6112 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6113 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6114 // Pull out the pointer to the variable. 6115 Address PtrAddr = CGF.EmitLoadOfPointer( 6116 CGF.GetAddrOfLocalVar(&ParamInOut), 6117 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6118 return CGF.Builder.CreateElementBitCast( 6119 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6120 }); 6121 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6122 // Pull out the pointer to the variable. 6123 Address PtrAddr = CGF.EmitLoadOfPointer( 6124 CGF.GetAddrOfLocalVar(&ParamIn), 6125 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6126 return CGF.Builder.CreateElementBitCast( 6127 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6128 }); 6129 PrivateScope.Privatize(); 6130 // Emit the combiner body: 6131 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6132 // store <type> %2, <type>* %lhs 6133 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6134 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6135 cast<DeclRefExpr>(RHS)); 6136 CGF.FinishFunction(); 6137 return Fn; 6138 } 6139 6140 /// Emits reduction finalizer function: 6141 /// \code 6142 /// void @.red_fini(void* %arg) { 6143 /// %0 = bitcast void* %arg to <type>* 6144 /// <destroy>(<type>* %0) 6145 /// ret void 6146 /// } 6147 /// \endcode 6148 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6149 SourceLocation Loc, 6150 ReductionCodeGen &RCG, unsigned N) { 6151 if (!RCG.needCleanups(N)) 6152 return nullptr; 6153 ASTContext &C = CGM.getContext(); 6154 FunctionArgList Args; 6155 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6156 ImplicitParamDecl::Other); 6157 Args.emplace_back(&Param); 6158 const auto &FnInfo = 6159 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6160 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6161 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6162 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6163 Name, &CGM.getModule()); 6164 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6165 Fn->setDoesNotRecurse(); 6166 CodeGenFunction CGF(CGM); 6167 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6168 Address PrivateAddr = CGF.EmitLoadOfPointer( 6169 CGF.GetAddrOfLocalVar(&Param), 6170 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6171 llvm::Value *Size = nullptr; 6172 // If the size of the reduction item is non-constant, load it from global 6173 // threadprivate variable. 6174 if (RCG.getSizes(N).second) { 6175 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6176 CGF, CGM.getContext().getSizeType(), 6177 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6178 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6179 CGM.getContext().getSizeType(), Loc); 6180 } 6181 RCG.emitAggregateType(CGF, N, Size); 6182 // Emit the finalizer body: 6183 // <destroy>(<type>* %0) 6184 RCG.emitCleanups(CGF, N, PrivateAddr); 6185 CGF.FinishFunction(); 6186 return Fn; 6187 } 6188 6189 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6190 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6191 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6192 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6193 return nullptr; 6194 6195 // Build typedef struct: 6196 // kmp_task_red_input { 6197 // void *reduce_shar; // shared reduction item 6198 // size_t reduce_size; // size of data item 6199 // void *reduce_init; // data initialization routine 6200 // void *reduce_fini; // data finalization routine 6201 // void *reduce_comb; // data combiner routine 6202 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6203 // } kmp_task_red_input_t; 6204 ASTContext &C = CGM.getContext(); 6205 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6206 RD->startDefinition(); 6207 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6208 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6209 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6210 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6211 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6212 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6213 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6214 RD->completeDefinition(); 6215 QualType RDType = C.getRecordType(RD); 6216 unsigned Size = Data.ReductionVars.size(); 6217 llvm::APInt ArraySize(/*numBits=*/64, Size); 6218 QualType ArrayRDType = C.getConstantArrayType( 6219 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6220 // kmp_task_red_input_t .rd_input.[Size]; 6221 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6222 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6223 Data.ReductionOps); 6224 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6225 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6226 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6227 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6228 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6229 TaskRedInput.getPointer(), Idxs, 6230 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6231 ".rd_input.gep."); 6232 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6233 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6234 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6235 RCG.emitSharedLValue(CGF, Cnt); 6236 llvm::Value *CastedShared = 6237 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer()); 6238 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6239 RCG.emitAggregateType(CGF, Cnt); 6240 llvm::Value *SizeValInChars; 6241 llvm::Value *SizeVal; 6242 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6243 // We use delayed creation/initialization for VLAs, array sections and 6244 // custom reduction initializations. It is required because runtime does not 6245 // provide the way to pass the sizes of VLAs/array sections to 6246 // initializer/combiner/finalizer functions and does not pass the pointer to 6247 // original reduction item to the initializer. Instead threadprivate global 6248 // variables are used to store these values and use them in the functions. 6249 bool DelayedCreation = !!SizeVal; 6250 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6251 /*isSigned=*/false); 6252 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6253 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6254 // ElemLVal.reduce_init = init; 6255 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6256 llvm::Value *InitAddr = 6257 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6258 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6259 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6260 // ElemLVal.reduce_fini = fini; 6261 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6262 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6263 llvm::Value *FiniAddr = Fini 6264 ? CGF.EmitCastToVoidPtr(Fini) 6265 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6266 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6267 // ElemLVal.reduce_comb = comb; 6268 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6269 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6270 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6271 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6272 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6273 // ElemLVal.flags = 0; 6274 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6275 if (DelayedCreation) { 6276 CGF.EmitStoreOfScalar( 6277 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6278 FlagsLVal); 6279 } else 6280 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType()); 6281 } 6282 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6283 // *data); 6284 llvm::Value *Args[] = { 6285 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6286 /*isSigned=*/true), 6287 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6288 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6289 CGM.VoidPtrTy)}; 6290 return CGF.EmitRuntimeCall( 6291 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6292 } 6293 6294 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6295 SourceLocation Loc, 6296 ReductionCodeGen &RCG, 6297 unsigned N) { 6298 auto Sizes = RCG.getSizes(N); 6299 // Emit threadprivate global variable if the type is non-constant 6300 // (Sizes.second = nullptr). 6301 if (Sizes.second) { 6302 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6303 /*isSigned=*/false); 6304 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6305 CGF, CGM.getContext().getSizeType(), 6306 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6307 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6308 } 6309 // Store address of the original reduction item if custom initializer is used. 6310 if (RCG.usesReductionInitializer(N)) { 6311 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6312 CGF, CGM.getContext().VoidPtrTy, 6313 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6314 CGF.Builder.CreateStore( 6315 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6316 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy), 6317 SharedAddr, /*IsVolatile=*/false); 6318 } 6319 } 6320 6321 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6322 SourceLocation Loc, 6323 llvm::Value *ReductionsPtr, 6324 LValue SharedLVal) { 6325 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6326 // *d); 6327 llvm::Value *Args[] = { 6328 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6329 /*isSigned=*/true), 6330 ReductionsPtr, 6331 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(), 6332 CGM.VoidPtrTy)}; 6333 return Address( 6334 CGF.EmitRuntimeCall( 6335 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6336 SharedLVal.getAlignment()); 6337 } 6338 6339 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6340 SourceLocation Loc) { 6341 if (!CGF.HaveInsertPoint()) 6342 return; 6343 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6344 // global_tid); 6345 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6346 // Ignore return result until untied tasks are supported. 6347 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6348 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6349 Region->emitUntiedSwitch(CGF); 6350 } 6351 6352 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6353 OpenMPDirectiveKind InnerKind, 6354 const RegionCodeGenTy &CodeGen, 6355 bool HasCancel) { 6356 if (!CGF.HaveInsertPoint()) 6357 return; 6358 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6359 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6360 } 6361 6362 namespace { 6363 enum RTCancelKind { 6364 CancelNoreq = 0, 6365 CancelParallel = 1, 6366 CancelLoop = 2, 6367 CancelSections = 3, 6368 CancelTaskgroup = 4 6369 }; 6370 } // anonymous namespace 6371 6372 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6373 RTCancelKind CancelKind = CancelNoreq; 6374 if (CancelRegion == OMPD_parallel) 6375 CancelKind = CancelParallel; 6376 else if (CancelRegion == OMPD_for) 6377 CancelKind = CancelLoop; 6378 else if (CancelRegion == OMPD_sections) 6379 CancelKind = CancelSections; 6380 else { 6381 assert(CancelRegion == OMPD_taskgroup); 6382 CancelKind = CancelTaskgroup; 6383 } 6384 return CancelKind; 6385 } 6386 6387 void CGOpenMPRuntime::emitCancellationPointCall( 6388 CodeGenFunction &CGF, SourceLocation Loc, 6389 OpenMPDirectiveKind CancelRegion) { 6390 if (!CGF.HaveInsertPoint()) 6391 return; 6392 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6393 // global_tid, kmp_int32 cncl_kind); 6394 if (auto *OMPRegionInfo = 6395 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6396 // For 'cancellation point taskgroup', the task region info may not have a 6397 // cancel. This may instead happen in another adjacent task. 6398 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6399 llvm::Value *Args[] = { 6400 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6401 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6402 // Ignore return result until untied tasks are supported. 6403 llvm::Value *Result = CGF.EmitRuntimeCall( 6404 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6405 // if (__kmpc_cancellationpoint()) { 6406 // exit from construct; 6407 // } 6408 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6409 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6410 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6411 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6412 CGF.EmitBlock(ExitBB); 6413 // exit from construct; 6414 CodeGenFunction::JumpDest CancelDest = 6415 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6416 CGF.EmitBranchThroughCleanup(CancelDest); 6417 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6418 } 6419 } 6420 } 6421 6422 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6423 const Expr *IfCond, 6424 OpenMPDirectiveKind CancelRegion) { 6425 if (!CGF.HaveInsertPoint()) 6426 return; 6427 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6428 // kmp_int32 cncl_kind); 6429 if (auto *OMPRegionInfo = 6430 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6431 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6432 PrePostActionTy &) { 6433 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6434 llvm::Value *Args[] = { 6435 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6436 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6437 // Ignore return result until untied tasks are supported. 6438 llvm::Value *Result = CGF.EmitRuntimeCall( 6439 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6440 // if (__kmpc_cancel()) { 6441 // exit from construct; 6442 // } 6443 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6444 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6445 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6446 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6447 CGF.EmitBlock(ExitBB); 6448 // exit from construct; 6449 CodeGenFunction::JumpDest CancelDest = 6450 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6451 CGF.EmitBranchThroughCleanup(CancelDest); 6452 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6453 }; 6454 if (IfCond) { 6455 emitIfClause(CGF, IfCond, ThenGen, 6456 [](CodeGenFunction &, PrePostActionTy &) {}); 6457 } else { 6458 RegionCodeGenTy ThenRCG(ThenGen); 6459 ThenRCG(CGF); 6460 } 6461 } 6462 } 6463 6464 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6465 const OMPExecutableDirective &D, StringRef ParentName, 6466 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6467 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6468 assert(!ParentName.empty() && "Invalid target region parent name!"); 6469 HasEmittedTargetRegion = true; 6470 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6471 IsOffloadEntry, CodeGen); 6472 } 6473 6474 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6475 const OMPExecutableDirective &D, StringRef ParentName, 6476 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6477 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6478 // Create a unique name for the entry function using the source location 6479 // information of the current target region. The name will be something like: 6480 // 6481 // __omp_offloading_DD_FFFF_PP_lBB 6482 // 6483 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6484 // mangled name of the function that encloses the target region and BB is the 6485 // line number of the target region. 6486 6487 unsigned DeviceID; 6488 unsigned FileID; 6489 unsigned Line; 6490 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6491 Line); 6492 SmallString<64> EntryFnName; 6493 { 6494 llvm::raw_svector_ostream OS(EntryFnName); 6495 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6496 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6497 } 6498 6499 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6500 6501 CodeGenFunction CGF(CGM, true); 6502 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6503 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6504 6505 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 6506 6507 // If this target outline function is not an offload entry, we don't need to 6508 // register it. 6509 if (!IsOffloadEntry) 6510 return; 6511 6512 // The target region ID is used by the runtime library to identify the current 6513 // target region, so it only has to be unique and not necessarily point to 6514 // anything. It could be the pointer to the outlined function that implements 6515 // the target region, but we aren't using that so that the compiler doesn't 6516 // need to keep that, and could therefore inline the host function if proven 6517 // worthwhile during optimization. In the other hand, if emitting code for the 6518 // device, the ID has to be the function address so that it can retrieved from 6519 // the offloading entry and launched by the runtime library. We also mark the 6520 // outlined function to have external linkage in case we are emitting code for 6521 // the device, because these functions will be entry points to the device. 6522 6523 if (CGM.getLangOpts().OpenMPIsDevice) { 6524 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6525 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6526 OutlinedFn->setDSOLocal(false); 6527 } else { 6528 std::string Name = getName({EntryFnName, "region_id"}); 6529 OutlinedFnID = new llvm::GlobalVariable( 6530 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6531 llvm::GlobalValue::WeakAnyLinkage, 6532 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6533 } 6534 6535 // Register the information for the entry associated with this target region. 6536 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6537 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6538 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6539 } 6540 6541 /// Checks if the expression is constant or does not have non-trivial function 6542 /// calls. 6543 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6544 // We can skip constant expressions. 6545 // We can skip expressions with trivial calls or simple expressions. 6546 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6547 !E->hasNonTrivialCall(Ctx)) && 6548 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6549 } 6550 6551 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6552 const Stmt *Body) { 6553 const Stmt *Child = Body->IgnoreContainers(); 6554 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6555 Child = nullptr; 6556 for (const Stmt *S : C->body()) { 6557 if (const auto *E = dyn_cast<Expr>(S)) { 6558 if (isTrivial(Ctx, E)) 6559 continue; 6560 } 6561 // Some of the statements can be ignored. 6562 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6563 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6564 continue; 6565 // Analyze declarations. 6566 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6567 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6568 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6569 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6570 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6571 isa<UsingDirectiveDecl>(D) || 6572 isa<OMPDeclareReductionDecl>(D) || 6573 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6574 return true; 6575 const auto *VD = dyn_cast<VarDecl>(D); 6576 if (!VD) 6577 return false; 6578 return VD->isConstexpr() || 6579 ((VD->getType().isTrivialType(Ctx) || 6580 VD->getType()->isReferenceType()) && 6581 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6582 })) 6583 continue; 6584 } 6585 // Found multiple children - cannot get the one child only. 6586 if (Child) 6587 return nullptr; 6588 Child = S; 6589 } 6590 if (Child) 6591 Child = Child->IgnoreContainers(); 6592 } 6593 return Child; 6594 } 6595 6596 /// Emit the number of teams for a target directive. Inspect the num_teams 6597 /// clause associated with a teams construct combined or closely nested 6598 /// with the target directive. 6599 /// 6600 /// Emit a team of size one for directives such as 'target parallel' that 6601 /// have no associated teams construct. 6602 /// 6603 /// Otherwise, return nullptr. 6604 static llvm::Value * 6605 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6606 const OMPExecutableDirective &D) { 6607 assert(!CGF.getLangOpts().OpenMPIsDevice && 6608 "Clauses associated with the teams directive expected to be emitted " 6609 "only for the host!"); 6610 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6611 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6612 "Expected target-based executable directive."); 6613 CGBuilderTy &Bld = CGF.Builder; 6614 switch (DirectiveKind) { 6615 case OMPD_target: { 6616 const auto *CS = D.getInnermostCapturedStmt(); 6617 const auto *Body = 6618 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6619 const Stmt *ChildStmt = 6620 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6621 if (const auto *NestedDir = 6622 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6623 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6624 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6625 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6626 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6627 const Expr *NumTeams = 6628 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6629 llvm::Value *NumTeamsVal = 6630 CGF.EmitScalarExpr(NumTeams, 6631 /*IgnoreResultAssign*/ true); 6632 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6633 /*isSigned=*/true); 6634 } 6635 return Bld.getInt32(0); 6636 } 6637 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6638 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6639 return Bld.getInt32(1); 6640 return Bld.getInt32(0); 6641 } 6642 return nullptr; 6643 } 6644 case OMPD_target_teams: 6645 case OMPD_target_teams_distribute: 6646 case OMPD_target_teams_distribute_simd: 6647 case OMPD_target_teams_distribute_parallel_for: 6648 case OMPD_target_teams_distribute_parallel_for_simd: { 6649 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6650 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6651 const Expr *NumTeams = 6652 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6653 llvm::Value *NumTeamsVal = 6654 CGF.EmitScalarExpr(NumTeams, 6655 /*IgnoreResultAssign*/ true); 6656 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6657 /*isSigned=*/true); 6658 } 6659 return Bld.getInt32(0); 6660 } 6661 case OMPD_target_parallel: 6662 case OMPD_target_parallel_for: 6663 case OMPD_target_parallel_for_simd: 6664 case OMPD_target_simd: 6665 return Bld.getInt32(1); 6666 case OMPD_parallel: 6667 case OMPD_for: 6668 case OMPD_parallel_for: 6669 case OMPD_parallel_sections: 6670 case OMPD_for_simd: 6671 case OMPD_parallel_for_simd: 6672 case OMPD_cancel: 6673 case OMPD_cancellation_point: 6674 case OMPD_ordered: 6675 case OMPD_threadprivate: 6676 case OMPD_allocate: 6677 case OMPD_task: 6678 case OMPD_simd: 6679 case OMPD_sections: 6680 case OMPD_section: 6681 case OMPD_single: 6682 case OMPD_master: 6683 case OMPD_critical: 6684 case OMPD_taskyield: 6685 case OMPD_barrier: 6686 case OMPD_taskwait: 6687 case OMPD_taskgroup: 6688 case OMPD_atomic: 6689 case OMPD_flush: 6690 case OMPD_teams: 6691 case OMPD_target_data: 6692 case OMPD_target_exit_data: 6693 case OMPD_target_enter_data: 6694 case OMPD_distribute: 6695 case OMPD_distribute_simd: 6696 case OMPD_distribute_parallel_for: 6697 case OMPD_distribute_parallel_for_simd: 6698 case OMPD_teams_distribute: 6699 case OMPD_teams_distribute_simd: 6700 case OMPD_teams_distribute_parallel_for: 6701 case OMPD_teams_distribute_parallel_for_simd: 6702 case OMPD_target_update: 6703 case OMPD_declare_simd: 6704 case OMPD_declare_variant: 6705 case OMPD_declare_target: 6706 case OMPD_end_declare_target: 6707 case OMPD_declare_reduction: 6708 case OMPD_declare_mapper: 6709 case OMPD_taskloop: 6710 case OMPD_taskloop_simd: 6711 case OMPD_master_taskloop: 6712 case OMPD_master_taskloop_simd: 6713 case OMPD_parallel_master_taskloop: 6714 case OMPD_parallel_master_taskloop_simd: 6715 case OMPD_requires: 6716 case OMPD_unknown: 6717 break; 6718 } 6719 llvm_unreachable("Unexpected directive kind."); 6720 } 6721 6722 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6723 llvm::Value *DefaultThreadLimitVal) { 6724 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6725 CGF.getContext(), CS->getCapturedStmt()); 6726 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6727 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6728 llvm::Value *NumThreads = nullptr; 6729 llvm::Value *CondVal = nullptr; 6730 // Handle if clause. If if clause present, the number of threads is 6731 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6732 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6733 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6734 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6735 const OMPIfClause *IfClause = nullptr; 6736 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6737 if (C->getNameModifier() == OMPD_unknown || 6738 C->getNameModifier() == OMPD_parallel) { 6739 IfClause = C; 6740 break; 6741 } 6742 } 6743 if (IfClause) { 6744 const Expr *Cond = IfClause->getCondition(); 6745 bool Result; 6746 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6747 if (!Result) 6748 return CGF.Builder.getInt32(1); 6749 } else { 6750 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6751 if (const auto *PreInit = 6752 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6753 for (const auto *I : PreInit->decls()) { 6754 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6755 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6756 } else { 6757 CodeGenFunction::AutoVarEmission Emission = 6758 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6759 CGF.EmitAutoVarCleanups(Emission); 6760 } 6761 } 6762 } 6763 CondVal = CGF.EvaluateExprAsBool(Cond); 6764 } 6765 } 6766 } 6767 // Check the value of num_threads clause iff if clause was not specified 6768 // or is not evaluated to false. 6769 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6770 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6771 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6772 const auto *NumThreadsClause = 6773 Dir->getSingleClause<OMPNumThreadsClause>(); 6774 CodeGenFunction::LexicalScope Scope( 6775 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6776 if (const auto *PreInit = 6777 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6778 for (const auto *I : PreInit->decls()) { 6779 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6780 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6781 } else { 6782 CodeGenFunction::AutoVarEmission Emission = 6783 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6784 CGF.EmitAutoVarCleanups(Emission); 6785 } 6786 } 6787 } 6788 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6789 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6790 /*isSigned=*/false); 6791 if (DefaultThreadLimitVal) 6792 NumThreads = CGF.Builder.CreateSelect( 6793 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6794 DefaultThreadLimitVal, NumThreads); 6795 } else { 6796 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6797 : CGF.Builder.getInt32(0); 6798 } 6799 // Process condition of the if clause. 6800 if (CondVal) { 6801 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6802 CGF.Builder.getInt32(1)); 6803 } 6804 return NumThreads; 6805 } 6806 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6807 return CGF.Builder.getInt32(1); 6808 return DefaultThreadLimitVal; 6809 } 6810 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6811 : CGF.Builder.getInt32(0); 6812 } 6813 6814 /// Emit the number of threads for a target directive. Inspect the 6815 /// thread_limit clause associated with a teams construct combined or closely 6816 /// nested with the target directive. 6817 /// 6818 /// Emit the num_threads clause for directives such as 'target parallel' that 6819 /// have no associated teams construct. 6820 /// 6821 /// Otherwise, return nullptr. 6822 static llvm::Value * 6823 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6824 const OMPExecutableDirective &D) { 6825 assert(!CGF.getLangOpts().OpenMPIsDevice && 6826 "Clauses associated with the teams directive expected to be emitted " 6827 "only for the host!"); 6828 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6829 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6830 "Expected target-based executable directive."); 6831 CGBuilderTy &Bld = CGF.Builder; 6832 llvm::Value *ThreadLimitVal = nullptr; 6833 llvm::Value *NumThreadsVal = nullptr; 6834 switch (DirectiveKind) { 6835 case OMPD_target: { 6836 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6837 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6838 return NumThreads; 6839 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6840 CGF.getContext(), CS->getCapturedStmt()); 6841 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6842 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6843 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6844 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6845 const auto *ThreadLimitClause = 6846 Dir->getSingleClause<OMPThreadLimitClause>(); 6847 CodeGenFunction::LexicalScope Scope( 6848 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6849 if (const auto *PreInit = 6850 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6851 for (const auto *I : PreInit->decls()) { 6852 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6853 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6854 } else { 6855 CodeGenFunction::AutoVarEmission Emission = 6856 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6857 CGF.EmitAutoVarCleanups(Emission); 6858 } 6859 } 6860 } 6861 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6862 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6863 ThreadLimitVal = 6864 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6865 } 6866 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6867 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6868 CS = Dir->getInnermostCapturedStmt(); 6869 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6870 CGF.getContext(), CS->getCapturedStmt()); 6871 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6872 } 6873 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6874 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6875 CS = Dir->getInnermostCapturedStmt(); 6876 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6877 return NumThreads; 6878 } 6879 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6880 return Bld.getInt32(1); 6881 } 6882 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6883 } 6884 case OMPD_target_teams: { 6885 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6886 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6887 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6888 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6889 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6890 ThreadLimitVal = 6891 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6892 } 6893 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6894 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6895 return NumThreads; 6896 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6897 CGF.getContext(), CS->getCapturedStmt()); 6898 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6899 if (Dir->getDirectiveKind() == OMPD_distribute) { 6900 CS = Dir->getInnermostCapturedStmt(); 6901 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6902 return NumThreads; 6903 } 6904 } 6905 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6906 } 6907 case OMPD_target_teams_distribute: 6908 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6909 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6910 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6911 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6912 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6913 ThreadLimitVal = 6914 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6915 } 6916 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6917 case OMPD_target_parallel: 6918 case OMPD_target_parallel_for: 6919 case OMPD_target_parallel_for_simd: 6920 case OMPD_target_teams_distribute_parallel_for: 6921 case OMPD_target_teams_distribute_parallel_for_simd: { 6922 llvm::Value *CondVal = nullptr; 6923 // Handle if clause. If if clause present, the number of threads is 6924 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6925 if (D.hasClausesOfKind<OMPIfClause>()) { 6926 const OMPIfClause *IfClause = nullptr; 6927 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6928 if (C->getNameModifier() == OMPD_unknown || 6929 C->getNameModifier() == OMPD_parallel) { 6930 IfClause = C; 6931 break; 6932 } 6933 } 6934 if (IfClause) { 6935 const Expr *Cond = IfClause->getCondition(); 6936 bool Result; 6937 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6938 if (!Result) 6939 return Bld.getInt32(1); 6940 } else { 6941 CodeGenFunction::RunCleanupsScope Scope(CGF); 6942 CondVal = CGF.EvaluateExprAsBool(Cond); 6943 } 6944 } 6945 } 6946 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6947 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6948 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6949 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6950 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6951 ThreadLimitVal = 6952 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6953 } 6954 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6955 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6956 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6957 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6958 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6959 NumThreadsVal = 6960 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6961 ThreadLimitVal = ThreadLimitVal 6962 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6963 ThreadLimitVal), 6964 NumThreadsVal, ThreadLimitVal) 6965 : NumThreadsVal; 6966 } 6967 if (!ThreadLimitVal) 6968 ThreadLimitVal = Bld.getInt32(0); 6969 if (CondVal) 6970 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6971 return ThreadLimitVal; 6972 } 6973 case OMPD_target_teams_distribute_simd: 6974 case OMPD_target_simd: 6975 return Bld.getInt32(1); 6976 case OMPD_parallel: 6977 case OMPD_for: 6978 case OMPD_parallel_for: 6979 case OMPD_parallel_sections: 6980 case OMPD_for_simd: 6981 case OMPD_parallel_for_simd: 6982 case OMPD_cancel: 6983 case OMPD_cancellation_point: 6984 case OMPD_ordered: 6985 case OMPD_threadprivate: 6986 case OMPD_allocate: 6987 case OMPD_task: 6988 case OMPD_simd: 6989 case OMPD_sections: 6990 case OMPD_section: 6991 case OMPD_single: 6992 case OMPD_master: 6993 case OMPD_critical: 6994 case OMPD_taskyield: 6995 case OMPD_barrier: 6996 case OMPD_taskwait: 6997 case OMPD_taskgroup: 6998 case OMPD_atomic: 6999 case OMPD_flush: 7000 case OMPD_teams: 7001 case OMPD_target_data: 7002 case OMPD_target_exit_data: 7003 case OMPD_target_enter_data: 7004 case OMPD_distribute: 7005 case OMPD_distribute_simd: 7006 case OMPD_distribute_parallel_for: 7007 case OMPD_distribute_parallel_for_simd: 7008 case OMPD_teams_distribute: 7009 case OMPD_teams_distribute_simd: 7010 case OMPD_teams_distribute_parallel_for: 7011 case OMPD_teams_distribute_parallel_for_simd: 7012 case OMPD_target_update: 7013 case OMPD_declare_simd: 7014 case OMPD_declare_variant: 7015 case OMPD_declare_target: 7016 case OMPD_end_declare_target: 7017 case OMPD_declare_reduction: 7018 case OMPD_declare_mapper: 7019 case OMPD_taskloop: 7020 case OMPD_taskloop_simd: 7021 case OMPD_master_taskloop: 7022 case OMPD_master_taskloop_simd: 7023 case OMPD_parallel_master_taskloop: 7024 case OMPD_parallel_master_taskloop_simd: 7025 case OMPD_requires: 7026 case OMPD_unknown: 7027 break; 7028 } 7029 llvm_unreachable("Unsupported directive kind."); 7030 } 7031 7032 namespace { 7033 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7034 7035 // Utility to handle information from clauses associated with a given 7036 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7037 // It provides a convenient interface to obtain the information and generate 7038 // code for that information. 7039 class MappableExprsHandler { 7040 public: 7041 /// Values for bit flags used to specify the mapping type for 7042 /// offloading. 7043 enum OpenMPOffloadMappingFlags : uint64_t { 7044 /// No flags 7045 OMP_MAP_NONE = 0x0, 7046 /// Allocate memory on the device and move data from host to device. 7047 OMP_MAP_TO = 0x01, 7048 /// Allocate memory on the device and move data from device to host. 7049 OMP_MAP_FROM = 0x02, 7050 /// Always perform the requested mapping action on the element, even 7051 /// if it was already mapped before. 7052 OMP_MAP_ALWAYS = 0x04, 7053 /// Delete the element from the device environment, ignoring the 7054 /// current reference count associated with the element. 7055 OMP_MAP_DELETE = 0x08, 7056 /// The element being mapped is a pointer-pointee pair; both the 7057 /// pointer and the pointee should be mapped. 7058 OMP_MAP_PTR_AND_OBJ = 0x10, 7059 /// This flags signals that the base address of an entry should be 7060 /// passed to the target kernel as an argument. 7061 OMP_MAP_TARGET_PARAM = 0x20, 7062 /// Signal that the runtime library has to return the device pointer 7063 /// in the current position for the data being mapped. Used when we have the 7064 /// use_device_ptr clause. 7065 OMP_MAP_RETURN_PARAM = 0x40, 7066 /// This flag signals that the reference being passed is a pointer to 7067 /// private data. 7068 OMP_MAP_PRIVATE = 0x80, 7069 /// Pass the element to the device by value. 7070 OMP_MAP_LITERAL = 0x100, 7071 /// Implicit map 7072 OMP_MAP_IMPLICIT = 0x200, 7073 /// Close is a hint to the runtime to allocate memory close to 7074 /// the target device. 7075 OMP_MAP_CLOSE = 0x400, 7076 /// The 16 MSBs of the flags indicate whether the entry is member of some 7077 /// struct/class. 7078 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7079 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7080 }; 7081 7082 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7083 static unsigned getFlagMemberOffset() { 7084 unsigned Offset = 0; 7085 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7086 Remain = Remain >> 1) 7087 Offset++; 7088 return Offset; 7089 } 7090 7091 /// Class that associates information with a base pointer to be passed to the 7092 /// runtime library. 7093 class BasePointerInfo { 7094 /// The base pointer. 7095 llvm::Value *Ptr = nullptr; 7096 /// The base declaration that refers to this device pointer, or null if 7097 /// there is none. 7098 const ValueDecl *DevPtrDecl = nullptr; 7099 7100 public: 7101 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7102 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7103 llvm::Value *operator*() const { return Ptr; } 7104 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7105 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7106 }; 7107 7108 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7109 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7110 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7111 7112 /// Map between a struct and the its lowest & highest elements which have been 7113 /// mapped. 7114 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7115 /// HE(FieldIndex, Pointer)} 7116 struct StructRangeInfoTy { 7117 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7118 0, Address::invalid()}; 7119 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7120 0, Address::invalid()}; 7121 Address Base = Address::invalid(); 7122 }; 7123 7124 private: 7125 /// Kind that defines how a device pointer has to be returned. 7126 struct MapInfo { 7127 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7128 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7129 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7130 bool ReturnDevicePointer = false; 7131 bool IsImplicit = false; 7132 7133 MapInfo() = default; 7134 MapInfo( 7135 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7136 OpenMPMapClauseKind MapType, 7137 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7138 bool ReturnDevicePointer, bool IsImplicit) 7139 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7140 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7141 }; 7142 7143 /// If use_device_ptr is used on a pointer which is a struct member and there 7144 /// is no map information about it, then emission of that entry is deferred 7145 /// until the whole struct has been processed. 7146 struct DeferredDevicePtrEntryTy { 7147 const Expr *IE = nullptr; 7148 const ValueDecl *VD = nullptr; 7149 7150 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7151 : IE(IE), VD(VD) {} 7152 }; 7153 7154 /// The target directive from where the mappable clauses were extracted. It 7155 /// is either a executable directive or a user-defined mapper directive. 7156 llvm::PointerUnion<const OMPExecutableDirective *, 7157 const OMPDeclareMapperDecl *> 7158 CurDir; 7159 7160 /// Function the directive is being generated for. 7161 CodeGenFunction &CGF; 7162 7163 /// Set of all first private variables in the current directive. 7164 /// bool data is set to true if the variable is implicitly marked as 7165 /// firstprivate, false otherwise. 7166 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7167 7168 /// Map between device pointer declarations and their expression components. 7169 /// The key value for declarations in 'this' is null. 7170 llvm::DenseMap< 7171 const ValueDecl *, 7172 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7173 DevPointersMap; 7174 7175 llvm::Value *getExprTypeSize(const Expr *E) const { 7176 QualType ExprTy = E->getType().getCanonicalType(); 7177 7178 // Reference types are ignored for mapping purposes. 7179 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7180 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7181 7182 // Given that an array section is considered a built-in type, we need to 7183 // do the calculation based on the length of the section instead of relying 7184 // on CGF.getTypeSize(E->getType()). 7185 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7186 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7187 OAE->getBase()->IgnoreParenImpCasts()) 7188 .getCanonicalType(); 7189 7190 // If there is no length associated with the expression and lower bound is 7191 // not specified too, that means we are using the whole length of the 7192 // base. 7193 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7194 !OAE->getLowerBound()) 7195 return CGF.getTypeSize(BaseTy); 7196 7197 llvm::Value *ElemSize; 7198 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7199 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7200 } else { 7201 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7202 assert(ATy && "Expecting array type if not a pointer type."); 7203 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7204 } 7205 7206 // If we don't have a length at this point, that is because we have an 7207 // array section with a single element. 7208 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7209 return ElemSize; 7210 7211 if (const Expr *LenExpr = OAE->getLength()) { 7212 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7213 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7214 CGF.getContext().getSizeType(), 7215 LenExpr->getExprLoc()); 7216 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7217 } 7218 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7219 OAE->getLowerBound() && "expected array_section[lb:]."); 7220 // Size = sizetype - lb * elemtype; 7221 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7222 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7223 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7224 CGF.getContext().getSizeType(), 7225 OAE->getLowerBound()->getExprLoc()); 7226 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7227 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7228 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7229 LengthVal = CGF.Builder.CreateSelect( 7230 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7231 return LengthVal; 7232 } 7233 return CGF.getTypeSize(ExprTy); 7234 } 7235 7236 /// Return the corresponding bits for a given map clause modifier. Add 7237 /// a flag marking the map as a pointer if requested. Add a flag marking the 7238 /// map as the first one of a series of maps that relate to the same map 7239 /// expression. 7240 OpenMPOffloadMappingFlags getMapTypeBits( 7241 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7242 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7243 OpenMPOffloadMappingFlags Bits = 7244 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7245 switch (MapType) { 7246 case OMPC_MAP_alloc: 7247 case OMPC_MAP_release: 7248 // alloc and release is the default behavior in the runtime library, i.e. 7249 // if we don't pass any bits alloc/release that is what the runtime is 7250 // going to do. Therefore, we don't need to signal anything for these two 7251 // type modifiers. 7252 break; 7253 case OMPC_MAP_to: 7254 Bits |= OMP_MAP_TO; 7255 break; 7256 case OMPC_MAP_from: 7257 Bits |= OMP_MAP_FROM; 7258 break; 7259 case OMPC_MAP_tofrom: 7260 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7261 break; 7262 case OMPC_MAP_delete: 7263 Bits |= OMP_MAP_DELETE; 7264 break; 7265 case OMPC_MAP_unknown: 7266 llvm_unreachable("Unexpected map type!"); 7267 } 7268 if (AddPtrFlag) 7269 Bits |= OMP_MAP_PTR_AND_OBJ; 7270 if (AddIsTargetParamFlag) 7271 Bits |= OMP_MAP_TARGET_PARAM; 7272 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7273 != MapModifiers.end()) 7274 Bits |= OMP_MAP_ALWAYS; 7275 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7276 != MapModifiers.end()) 7277 Bits |= OMP_MAP_CLOSE; 7278 return Bits; 7279 } 7280 7281 /// Return true if the provided expression is a final array section. A 7282 /// final array section, is one whose length can't be proved to be one. 7283 bool isFinalArraySectionExpression(const Expr *E) const { 7284 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7285 7286 // It is not an array section and therefore not a unity-size one. 7287 if (!OASE) 7288 return false; 7289 7290 // An array section with no colon always refer to a single element. 7291 if (OASE->getColonLoc().isInvalid()) 7292 return false; 7293 7294 const Expr *Length = OASE->getLength(); 7295 7296 // If we don't have a length we have to check if the array has size 1 7297 // for this dimension. Also, we should always expect a length if the 7298 // base type is pointer. 7299 if (!Length) { 7300 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7301 OASE->getBase()->IgnoreParenImpCasts()) 7302 .getCanonicalType(); 7303 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7304 return ATy->getSize().getSExtValue() != 1; 7305 // If we don't have a constant dimension length, we have to consider 7306 // the current section as having any size, so it is not necessarily 7307 // unitary. If it happen to be unity size, that's user fault. 7308 return true; 7309 } 7310 7311 // Check if the length evaluates to 1. 7312 Expr::EvalResult Result; 7313 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7314 return true; // Can have more that size 1. 7315 7316 llvm::APSInt ConstLength = Result.Val.getInt(); 7317 return ConstLength.getSExtValue() != 1; 7318 } 7319 7320 /// Generate the base pointers, section pointers, sizes and map type 7321 /// bits for the provided map type, map modifier, and expression components. 7322 /// \a IsFirstComponent should be set to true if the provided set of 7323 /// components is the first associated with a capture. 7324 void generateInfoForComponentList( 7325 OpenMPMapClauseKind MapType, 7326 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7327 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7328 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7329 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7330 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7331 bool IsImplicit, 7332 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7333 OverlappedElements = llvm::None) const { 7334 // The following summarizes what has to be generated for each map and the 7335 // types below. The generated information is expressed in this order: 7336 // base pointer, section pointer, size, flags 7337 // (to add to the ones that come from the map type and modifier). 7338 // 7339 // double d; 7340 // int i[100]; 7341 // float *p; 7342 // 7343 // struct S1 { 7344 // int i; 7345 // float f[50]; 7346 // } 7347 // struct S2 { 7348 // int i; 7349 // float f[50]; 7350 // S1 s; 7351 // double *p; 7352 // struct S2 *ps; 7353 // } 7354 // S2 s; 7355 // S2 *ps; 7356 // 7357 // map(d) 7358 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7359 // 7360 // map(i) 7361 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7362 // 7363 // map(i[1:23]) 7364 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7365 // 7366 // map(p) 7367 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7368 // 7369 // map(p[1:24]) 7370 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7371 // 7372 // map(s) 7373 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7374 // 7375 // map(s.i) 7376 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7377 // 7378 // map(s.s.f) 7379 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7380 // 7381 // map(s.p) 7382 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7383 // 7384 // map(to: s.p[:22]) 7385 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7386 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7387 // &(s.p), &(s.p[0]), 22*sizeof(double), 7388 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7389 // (*) alloc space for struct members, only this is a target parameter 7390 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7391 // optimizes this entry out, same in the examples below) 7392 // (***) map the pointee (map: to) 7393 // 7394 // map(s.ps) 7395 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7396 // 7397 // map(from: s.ps->s.i) 7398 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7399 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7400 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7401 // 7402 // map(to: s.ps->ps) 7403 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7404 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7405 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7406 // 7407 // map(s.ps->ps->ps) 7408 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7409 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7410 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7411 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7412 // 7413 // map(to: s.ps->ps->s.f[:22]) 7414 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7415 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7416 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7417 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7418 // 7419 // map(ps) 7420 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7421 // 7422 // map(ps->i) 7423 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7424 // 7425 // map(ps->s.f) 7426 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7427 // 7428 // map(from: ps->p) 7429 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7430 // 7431 // map(to: ps->p[:22]) 7432 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7433 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7434 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7435 // 7436 // map(ps->ps) 7437 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7438 // 7439 // map(from: ps->ps->s.i) 7440 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7441 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7442 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7443 // 7444 // map(from: ps->ps->ps) 7445 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7446 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7447 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7448 // 7449 // map(ps->ps->ps->ps) 7450 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7451 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7452 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7453 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7454 // 7455 // map(to: ps->ps->ps->s.f[:22]) 7456 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7457 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7458 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7459 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7460 // 7461 // map(to: s.f[:22]) map(from: s.p[:33]) 7462 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7463 // sizeof(double*) (**), TARGET_PARAM 7464 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7465 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7466 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7467 // (*) allocate contiguous space needed to fit all mapped members even if 7468 // we allocate space for members not mapped (in this example, 7469 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7470 // them as well because they fall between &s.f[0] and &s.p) 7471 // 7472 // map(from: s.f[:22]) map(to: ps->p[:33]) 7473 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7474 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7475 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7476 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7477 // (*) the struct this entry pertains to is the 2nd element in the list of 7478 // arguments, hence MEMBER_OF(2) 7479 // 7480 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7481 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7482 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7483 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7484 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7485 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7486 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7487 // (*) the struct this entry pertains to is the 4th element in the list 7488 // of arguments, hence MEMBER_OF(4) 7489 7490 // Track if the map information being generated is the first for a capture. 7491 bool IsCaptureFirstInfo = IsFirstComponentList; 7492 // When the variable is on a declare target link or in a to clause with 7493 // unified memory, a reference is needed to hold the host/device address 7494 // of the variable. 7495 bool RequiresReference = false; 7496 7497 // Scan the components from the base to the complete expression. 7498 auto CI = Components.rbegin(); 7499 auto CE = Components.rend(); 7500 auto I = CI; 7501 7502 // Track if the map information being generated is the first for a list of 7503 // components. 7504 bool IsExpressionFirstInfo = true; 7505 Address BP = Address::invalid(); 7506 const Expr *AssocExpr = I->getAssociatedExpression(); 7507 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7508 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7509 7510 if (isa<MemberExpr>(AssocExpr)) { 7511 // The base is the 'this' pointer. The content of the pointer is going 7512 // to be the base of the field being mapped. 7513 BP = CGF.LoadCXXThisAddress(); 7514 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7515 (OASE && 7516 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7517 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); 7518 } else { 7519 // The base is the reference to the variable. 7520 // BP = &Var. 7521 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); 7522 if (const auto *VD = 7523 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7524 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7525 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7526 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7527 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7528 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7529 RequiresReference = true; 7530 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7531 } 7532 } 7533 } 7534 7535 // If the variable is a pointer and is being dereferenced (i.e. is not 7536 // the last component), the base has to be the pointer itself, not its 7537 // reference. References are ignored for mapping purposes. 7538 QualType Ty = 7539 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7540 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7541 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7542 7543 // We do not need to generate individual map information for the 7544 // pointer, it can be associated with the combined storage. 7545 ++I; 7546 } 7547 } 7548 7549 // Track whether a component of the list should be marked as MEMBER_OF some 7550 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7551 // in a component list should be marked as MEMBER_OF, all subsequent entries 7552 // do not belong to the base struct. E.g. 7553 // struct S2 s; 7554 // s.ps->ps->ps->f[:] 7555 // (1) (2) (3) (4) 7556 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7557 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7558 // is the pointee of ps(2) which is not member of struct s, so it should not 7559 // be marked as such (it is still PTR_AND_OBJ). 7560 // The variable is initialized to false so that PTR_AND_OBJ entries which 7561 // are not struct members are not considered (e.g. array of pointers to 7562 // data). 7563 bool ShouldBeMemberOf = false; 7564 7565 // Variable keeping track of whether or not we have encountered a component 7566 // in the component list which is a member expression. Useful when we have a 7567 // pointer or a final array section, in which case it is the previous 7568 // component in the list which tells us whether we have a member expression. 7569 // E.g. X.f[:] 7570 // While processing the final array section "[:]" it is "f" which tells us 7571 // whether we are dealing with a member of a declared struct. 7572 const MemberExpr *EncounteredME = nullptr; 7573 7574 for (; I != CE; ++I) { 7575 // If the current component is member of a struct (parent struct) mark it. 7576 if (!EncounteredME) { 7577 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7578 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7579 // as MEMBER_OF the parent struct. 7580 if (EncounteredME) 7581 ShouldBeMemberOf = true; 7582 } 7583 7584 auto Next = std::next(I); 7585 7586 // We need to generate the addresses and sizes if this is the last 7587 // component, if the component is a pointer or if it is an array section 7588 // whose length can't be proved to be one. If this is a pointer, it 7589 // becomes the base address for the following components. 7590 7591 // A final array section, is one whose length can't be proved to be one. 7592 bool IsFinalArraySection = 7593 isFinalArraySectionExpression(I->getAssociatedExpression()); 7594 7595 // Get information on whether the element is a pointer. Have to do a 7596 // special treatment for array sections given that they are built-in 7597 // types. 7598 const auto *OASE = 7599 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7600 bool IsPointer = 7601 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7602 .getCanonicalType() 7603 ->isAnyPointerType()) || 7604 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7605 7606 if (Next == CE || IsPointer || IsFinalArraySection) { 7607 // If this is not the last component, we expect the pointer to be 7608 // associated with an array expression or member expression. 7609 assert((Next == CE || 7610 isa<MemberExpr>(Next->getAssociatedExpression()) || 7611 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7612 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 7613 "Unexpected expression"); 7614 7615 Address LB = 7616 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress(); 7617 7618 // If this component is a pointer inside the base struct then we don't 7619 // need to create any entry for it - it will be combined with the object 7620 // it is pointing to into a single PTR_AND_OBJ entry. 7621 bool IsMemberPointer = 7622 IsPointer && EncounteredME && 7623 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7624 EncounteredME); 7625 if (!OverlappedElements.empty()) { 7626 // Handle base element with the info for overlapped elements. 7627 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7628 assert(Next == CE && 7629 "Expected last element for the overlapped elements."); 7630 assert(!IsPointer && 7631 "Unexpected base element with the pointer type."); 7632 // Mark the whole struct as the struct that requires allocation on the 7633 // device. 7634 PartialStruct.LowestElem = {0, LB}; 7635 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7636 I->getAssociatedExpression()->getType()); 7637 Address HB = CGF.Builder.CreateConstGEP( 7638 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7639 CGF.VoidPtrTy), 7640 TypeSize.getQuantity() - 1); 7641 PartialStruct.HighestElem = { 7642 std::numeric_limits<decltype( 7643 PartialStruct.HighestElem.first)>::max(), 7644 HB}; 7645 PartialStruct.Base = BP; 7646 // Emit data for non-overlapped data. 7647 OpenMPOffloadMappingFlags Flags = 7648 OMP_MAP_MEMBER_OF | 7649 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7650 /*AddPtrFlag=*/false, 7651 /*AddIsTargetParamFlag=*/false); 7652 LB = BP; 7653 llvm::Value *Size = nullptr; 7654 // Do bitcopy of all non-overlapped structure elements. 7655 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7656 Component : OverlappedElements) { 7657 Address ComponentLB = Address::invalid(); 7658 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7659 Component) { 7660 if (MC.getAssociatedDeclaration()) { 7661 ComponentLB = 7662 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7663 .getAddress(); 7664 Size = CGF.Builder.CreatePtrDiff( 7665 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7666 CGF.EmitCastToVoidPtr(LB.getPointer())); 7667 break; 7668 } 7669 } 7670 BasePointers.push_back(BP.getPointer()); 7671 Pointers.push_back(LB.getPointer()); 7672 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7673 /*isSigned=*/true)); 7674 Types.push_back(Flags); 7675 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7676 } 7677 BasePointers.push_back(BP.getPointer()); 7678 Pointers.push_back(LB.getPointer()); 7679 Size = CGF.Builder.CreatePtrDiff( 7680 CGF.EmitCastToVoidPtr( 7681 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7682 CGF.EmitCastToVoidPtr(LB.getPointer())); 7683 Sizes.push_back( 7684 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7685 Types.push_back(Flags); 7686 break; 7687 } 7688 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7689 if (!IsMemberPointer) { 7690 BasePointers.push_back(BP.getPointer()); 7691 Pointers.push_back(LB.getPointer()); 7692 Sizes.push_back( 7693 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7694 7695 // We need to add a pointer flag for each map that comes from the 7696 // same expression except for the first one. We also need to signal 7697 // this map is the first one that relates with the current capture 7698 // (there is a set of entries for each capture). 7699 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7700 MapType, MapModifiers, IsImplicit, 7701 !IsExpressionFirstInfo || RequiresReference, 7702 IsCaptureFirstInfo && !RequiresReference); 7703 7704 if (!IsExpressionFirstInfo) { 7705 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7706 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7707 if (IsPointer) 7708 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7709 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7710 7711 if (ShouldBeMemberOf) { 7712 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7713 // should be later updated with the correct value of MEMBER_OF. 7714 Flags |= OMP_MAP_MEMBER_OF; 7715 // From now on, all subsequent PTR_AND_OBJ entries should not be 7716 // marked as MEMBER_OF. 7717 ShouldBeMemberOf = false; 7718 } 7719 } 7720 7721 Types.push_back(Flags); 7722 } 7723 7724 // If we have encountered a member expression so far, keep track of the 7725 // mapped member. If the parent is "*this", then the value declaration 7726 // is nullptr. 7727 if (EncounteredME) { 7728 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); 7729 unsigned FieldIndex = FD->getFieldIndex(); 7730 7731 // Update info about the lowest and highest elements for this struct 7732 if (!PartialStruct.Base.isValid()) { 7733 PartialStruct.LowestElem = {FieldIndex, LB}; 7734 PartialStruct.HighestElem = {FieldIndex, LB}; 7735 PartialStruct.Base = BP; 7736 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7737 PartialStruct.LowestElem = {FieldIndex, LB}; 7738 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7739 PartialStruct.HighestElem = {FieldIndex, LB}; 7740 } 7741 } 7742 7743 // If we have a final array section, we are done with this expression. 7744 if (IsFinalArraySection) 7745 break; 7746 7747 // The pointer becomes the base for the next element. 7748 if (Next != CE) 7749 BP = LB; 7750 7751 IsExpressionFirstInfo = false; 7752 IsCaptureFirstInfo = false; 7753 } 7754 } 7755 } 7756 7757 /// Return the adjusted map modifiers if the declaration a capture refers to 7758 /// appears in a first-private clause. This is expected to be used only with 7759 /// directives that start with 'target'. 7760 MappableExprsHandler::OpenMPOffloadMappingFlags 7761 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7762 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7763 7764 // A first private variable captured by reference will use only the 7765 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7766 // declaration is known as first-private in this handler. 7767 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7768 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7769 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7770 return MappableExprsHandler::OMP_MAP_ALWAYS | 7771 MappableExprsHandler::OMP_MAP_TO; 7772 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7773 return MappableExprsHandler::OMP_MAP_TO | 7774 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7775 return MappableExprsHandler::OMP_MAP_PRIVATE | 7776 MappableExprsHandler::OMP_MAP_TO; 7777 } 7778 return MappableExprsHandler::OMP_MAP_TO | 7779 MappableExprsHandler::OMP_MAP_FROM; 7780 } 7781 7782 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7783 // Rotate by getFlagMemberOffset() bits. 7784 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7785 << getFlagMemberOffset()); 7786 } 7787 7788 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7789 OpenMPOffloadMappingFlags MemberOfFlag) { 7790 // If the entry is PTR_AND_OBJ but has not been marked with the special 7791 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7792 // marked as MEMBER_OF. 7793 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7794 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7795 return; 7796 7797 // Reset the placeholder value to prepare the flag for the assignment of the 7798 // proper MEMBER_OF value. 7799 Flags &= ~OMP_MAP_MEMBER_OF; 7800 Flags |= MemberOfFlag; 7801 } 7802 7803 void getPlainLayout(const CXXRecordDecl *RD, 7804 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7805 bool AsBase) const { 7806 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7807 7808 llvm::StructType *St = 7809 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7810 7811 unsigned NumElements = St->getNumElements(); 7812 llvm::SmallVector< 7813 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7814 RecordLayout(NumElements); 7815 7816 // Fill bases. 7817 for (const auto &I : RD->bases()) { 7818 if (I.isVirtual()) 7819 continue; 7820 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7821 // Ignore empty bases. 7822 if (Base->isEmpty() || CGF.getContext() 7823 .getASTRecordLayout(Base) 7824 .getNonVirtualSize() 7825 .isZero()) 7826 continue; 7827 7828 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7829 RecordLayout[FieldIndex] = Base; 7830 } 7831 // Fill in virtual bases. 7832 for (const auto &I : RD->vbases()) { 7833 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7834 // Ignore empty bases. 7835 if (Base->isEmpty()) 7836 continue; 7837 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7838 if (RecordLayout[FieldIndex]) 7839 continue; 7840 RecordLayout[FieldIndex] = Base; 7841 } 7842 // Fill in all the fields. 7843 assert(!RD->isUnion() && "Unexpected union."); 7844 for (const auto *Field : RD->fields()) { 7845 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7846 // will fill in later.) 7847 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7848 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7849 RecordLayout[FieldIndex] = Field; 7850 } 7851 } 7852 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7853 &Data : RecordLayout) { 7854 if (Data.isNull()) 7855 continue; 7856 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7857 getPlainLayout(Base, Layout, /*AsBase=*/true); 7858 else 7859 Layout.push_back(Data.get<const FieldDecl *>()); 7860 } 7861 } 7862 7863 public: 7864 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7865 : CurDir(&Dir), CGF(CGF) { 7866 // Extract firstprivate clause information. 7867 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7868 for (const auto *D : C->varlists()) 7869 FirstPrivateDecls.try_emplace( 7870 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 7871 // Extract device pointer clause information. 7872 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7873 for (auto L : C->component_lists()) 7874 DevPointersMap[L.first].push_back(L.second); 7875 } 7876 7877 /// Constructor for the declare mapper directive. 7878 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 7879 : CurDir(&Dir), CGF(CGF) {} 7880 7881 /// Generate code for the combined entry if we have a partially mapped struct 7882 /// and take care of the mapping flags of the arguments corresponding to 7883 /// individual struct members. 7884 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 7885 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7886 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 7887 const StructRangeInfoTy &PartialStruct) const { 7888 // Base is the base of the struct 7889 BasePointers.push_back(PartialStruct.Base.getPointer()); 7890 // Pointer is the address of the lowest element 7891 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7892 Pointers.push_back(LB); 7893 // Size is (addr of {highest+1} element) - (addr of lowest element) 7894 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7895 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7896 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7897 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7898 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7899 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 7900 /*isSigned=*/false); 7901 Sizes.push_back(Size); 7902 // Map type is always TARGET_PARAM 7903 Types.push_back(OMP_MAP_TARGET_PARAM); 7904 // Remove TARGET_PARAM flag from the first element 7905 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7906 7907 // All other current entries will be MEMBER_OF the combined entry 7908 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7909 // 0xFFFF in the MEMBER_OF field). 7910 OpenMPOffloadMappingFlags MemberOfFlag = 7911 getMemberOfFlag(BasePointers.size() - 1); 7912 for (auto &M : CurTypes) 7913 setCorrectMemberOfFlag(M, MemberOfFlag); 7914 } 7915 7916 /// Generate all the base pointers, section pointers, sizes and map 7917 /// types for the extracted mappable expressions. Also, for each item that 7918 /// relates with a device pointer, a pair of the relevant declaration and 7919 /// index where it occurs is appended to the device pointers info array. 7920 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 7921 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7922 MapFlagsArrayTy &Types) const { 7923 // We have to process the component lists that relate with the same 7924 // declaration in a single chunk so that we can generate the map flags 7925 // correctly. Therefore, we organize all lists in a map. 7926 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7927 7928 // Helper function to fill the information map for the different supported 7929 // clauses. 7930 auto &&InfoGen = [&Info]( 7931 const ValueDecl *D, 7932 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7933 OpenMPMapClauseKind MapType, 7934 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7935 bool ReturnDevicePointer, bool IsImplicit) { 7936 const ValueDecl *VD = 7937 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7938 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7939 IsImplicit); 7940 }; 7941 7942 assert(CurDir.is<const OMPExecutableDirective *>() && 7943 "Expect a executable directive"); 7944 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 7945 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 7946 for (const auto L : C->component_lists()) { 7947 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 7948 /*ReturnDevicePointer=*/false, C->isImplicit()); 7949 } 7950 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 7951 for (const auto L : C->component_lists()) { 7952 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 7953 /*ReturnDevicePointer=*/false, C->isImplicit()); 7954 } 7955 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 7956 for (const auto L : C->component_lists()) { 7957 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 7958 /*ReturnDevicePointer=*/false, C->isImplicit()); 7959 } 7960 7961 // Look at the use_device_ptr clause information and mark the existing map 7962 // entries as such. If there is no map information for an entry in the 7963 // use_device_ptr list, we create one with map type 'alloc' and zero size 7964 // section. It is the user fault if that was not mapped before. If there is 7965 // no map information and the pointer is a struct member, then we defer the 7966 // emission of that entry until the whole struct has been processed. 7967 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 7968 DeferredInfo; 7969 7970 for (const auto *C : 7971 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 7972 for (const auto L : C->component_lists()) { 7973 assert(!L.second.empty() && "Not expecting empty list of components!"); 7974 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 7975 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 7976 const Expr *IE = L.second.back().getAssociatedExpression(); 7977 // If the first component is a member expression, we have to look into 7978 // 'this', which maps to null in the map of map information. Otherwise 7979 // look directly for the information. 7980 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 7981 7982 // We potentially have map information for this declaration already. 7983 // Look for the first set of components that refer to it. 7984 if (It != Info.end()) { 7985 auto CI = std::find_if( 7986 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 7987 return MI.Components.back().getAssociatedDeclaration() == VD; 7988 }); 7989 // If we found a map entry, signal that the pointer has to be returned 7990 // and move on to the next declaration. 7991 if (CI != It->second.end()) { 7992 CI->ReturnDevicePointer = true; 7993 continue; 7994 } 7995 } 7996 7997 // We didn't find any match in our map information - generate a zero 7998 // size array section - if the pointer is a struct member we defer this 7999 // action until the whole struct has been processed. 8000 if (isa<MemberExpr>(IE)) { 8001 // Insert the pointer into Info to be processed by 8002 // generateInfoForComponentList. Because it is a member pointer 8003 // without a pointee, no entry will be generated for it, therefore 8004 // we need to generate one after the whole struct has been processed. 8005 // Nonetheless, generateInfoForComponentList must be called to take 8006 // the pointer into account for the calculation of the range of the 8007 // partial struct. 8008 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 8009 /*ReturnDevicePointer=*/false, C->isImplicit()); 8010 DeferredInfo[nullptr].emplace_back(IE, VD); 8011 } else { 8012 llvm::Value *Ptr = 8013 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8014 BasePointers.emplace_back(Ptr, VD); 8015 Pointers.push_back(Ptr); 8016 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8017 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8018 } 8019 } 8020 } 8021 8022 for (const auto &M : Info) { 8023 // We need to know when we generate information for the first component 8024 // associated with a capture, because the mapping flags depend on it. 8025 bool IsFirstComponentList = true; 8026 8027 // Temporary versions of arrays 8028 MapBaseValuesArrayTy CurBasePointers; 8029 MapValuesArrayTy CurPointers; 8030 MapValuesArrayTy CurSizes; 8031 MapFlagsArrayTy CurTypes; 8032 StructRangeInfoTy PartialStruct; 8033 8034 for (const MapInfo &L : M.second) { 8035 assert(!L.Components.empty() && 8036 "Not expecting declaration with no component lists."); 8037 8038 // Remember the current base pointer index. 8039 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8040 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8041 CurBasePointers, CurPointers, CurSizes, 8042 CurTypes, PartialStruct, 8043 IsFirstComponentList, L.IsImplicit); 8044 8045 // If this entry relates with a device pointer, set the relevant 8046 // declaration and add the 'return pointer' flag. 8047 if (L.ReturnDevicePointer) { 8048 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8049 "Unexpected number of mapped base pointers."); 8050 8051 const ValueDecl *RelevantVD = 8052 L.Components.back().getAssociatedDeclaration(); 8053 assert(RelevantVD && 8054 "No relevant declaration related with device pointer??"); 8055 8056 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8057 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8058 } 8059 IsFirstComponentList = false; 8060 } 8061 8062 // Append any pending zero-length pointers which are struct members and 8063 // used with use_device_ptr. 8064 auto CI = DeferredInfo.find(M.first); 8065 if (CI != DeferredInfo.end()) { 8066 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8067 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(); 8068 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8069 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8070 CurBasePointers.emplace_back(BasePtr, L.VD); 8071 CurPointers.push_back(Ptr); 8072 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8073 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8074 // value MEMBER_OF=FFFF so that the entry is later updated with the 8075 // correct value of MEMBER_OF. 8076 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8077 OMP_MAP_MEMBER_OF); 8078 } 8079 } 8080 8081 // If there is an entry in PartialStruct it means we have a struct with 8082 // individual members mapped. Emit an extra combined entry. 8083 if (PartialStruct.Base.isValid()) 8084 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8085 PartialStruct); 8086 8087 // We need to append the results of this capture to what we already have. 8088 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8089 Pointers.append(CurPointers.begin(), CurPointers.end()); 8090 Sizes.append(CurSizes.begin(), CurSizes.end()); 8091 Types.append(CurTypes.begin(), CurTypes.end()); 8092 } 8093 } 8094 8095 /// Generate all the base pointers, section pointers, sizes and map types for 8096 /// the extracted map clauses of user-defined mapper. 8097 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8098 MapValuesArrayTy &Pointers, 8099 MapValuesArrayTy &Sizes, 8100 MapFlagsArrayTy &Types) const { 8101 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8102 "Expect a declare mapper directive"); 8103 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8104 // We have to process the component lists that relate with the same 8105 // declaration in a single chunk so that we can generate the map flags 8106 // correctly. Therefore, we organize all lists in a map. 8107 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8108 8109 // Helper function to fill the information map for the different supported 8110 // clauses. 8111 auto &&InfoGen = [&Info]( 8112 const ValueDecl *D, 8113 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8114 OpenMPMapClauseKind MapType, 8115 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8116 bool ReturnDevicePointer, bool IsImplicit) { 8117 const ValueDecl *VD = 8118 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8119 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8120 IsImplicit); 8121 }; 8122 8123 for (const auto *C : CurMapperDir->clauselists()) { 8124 const auto *MC = cast<OMPMapClause>(C); 8125 for (const auto L : MC->component_lists()) { 8126 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8127 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8128 } 8129 } 8130 8131 for (const auto &M : Info) { 8132 // We need to know when we generate information for the first component 8133 // associated with a capture, because the mapping flags depend on it. 8134 bool IsFirstComponentList = true; 8135 8136 // Temporary versions of arrays 8137 MapBaseValuesArrayTy CurBasePointers; 8138 MapValuesArrayTy CurPointers; 8139 MapValuesArrayTy CurSizes; 8140 MapFlagsArrayTy CurTypes; 8141 StructRangeInfoTy PartialStruct; 8142 8143 for (const MapInfo &L : M.second) { 8144 assert(!L.Components.empty() && 8145 "Not expecting declaration with no component lists."); 8146 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8147 CurBasePointers, CurPointers, CurSizes, 8148 CurTypes, PartialStruct, 8149 IsFirstComponentList, L.IsImplicit); 8150 IsFirstComponentList = false; 8151 } 8152 8153 // If there is an entry in PartialStruct it means we have a struct with 8154 // individual members mapped. Emit an extra combined entry. 8155 if (PartialStruct.Base.isValid()) 8156 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8157 PartialStruct); 8158 8159 // We need to append the results of this capture to what we already have. 8160 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8161 Pointers.append(CurPointers.begin(), CurPointers.end()); 8162 Sizes.append(CurSizes.begin(), CurSizes.end()); 8163 Types.append(CurTypes.begin(), CurTypes.end()); 8164 } 8165 } 8166 8167 /// Emit capture info for lambdas for variables captured by reference. 8168 void generateInfoForLambdaCaptures( 8169 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8170 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8171 MapFlagsArrayTy &Types, 8172 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8173 const auto *RD = VD->getType() 8174 .getCanonicalType() 8175 .getNonReferenceType() 8176 ->getAsCXXRecordDecl(); 8177 if (!RD || !RD->isLambda()) 8178 return; 8179 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8180 LValue VDLVal = CGF.MakeAddrLValue( 8181 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8182 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8183 FieldDecl *ThisCapture = nullptr; 8184 RD->getCaptureFields(Captures, ThisCapture); 8185 if (ThisCapture) { 8186 LValue ThisLVal = 8187 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8188 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8189 LambdaPointers.try_emplace(ThisLVal.getPointer(), VDLVal.getPointer()); 8190 BasePointers.push_back(ThisLVal.getPointer()); 8191 Pointers.push_back(ThisLValVal.getPointer()); 8192 Sizes.push_back( 8193 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8194 CGF.Int64Ty, /*isSigned=*/true)); 8195 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8196 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8197 } 8198 for (const LambdaCapture &LC : RD->captures()) { 8199 if (!LC.capturesVariable()) 8200 continue; 8201 const VarDecl *VD = LC.getCapturedVar(); 8202 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8203 continue; 8204 auto It = Captures.find(VD); 8205 assert(It != Captures.end() && "Found lambda capture without field."); 8206 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8207 if (LC.getCaptureKind() == LCK_ByRef) { 8208 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8209 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer()); 8210 BasePointers.push_back(VarLVal.getPointer()); 8211 Pointers.push_back(VarLValVal.getPointer()); 8212 Sizes.push_back(CGF.Builder.CreateIntCast( 8213 CGF.getTypeSize( 8214 VD->getType().getCanonicalType().getNonReferenceType()), 8215 CGF.Int64Ty, /*isSigned=*/true)); 8216 } else { 8217 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8218 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer()); 8219 BasePointers.push_back(VarLVal.getPointer()); 8220 Pointers.push_back(VarRVal.getScalarVal()); 8221 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8222 } 8223 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8224 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8225 } 8226 } 8227 8228 /// Set correct indices for lambdas captures. 8229 void adjustMemberOfForLambdaCaptures( 8230 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8231 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8232 MapFlagsArrayTy &Types) const { 8233 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8234 // Set correct member_of idx for all implicit lambda captures. 8235 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8236 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8237 continue; 8238 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8239 assert(BasePtr && "Unable to find base lambda address."); 8240 int TgtIdx = -1; 8241 for (unsigned J = I; J > 0; --J) { 8242 unsigned Idx = J - 1; 8243 if (Pointers[Idx] != BasePtr) 8244 continue; 8245 TgtIdx = Idx; 8246 break; 8247 } 8248 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8249 // All other current entries will be MEMBER_OF the combined entry 8250 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8251 // 0xFFFF in the MEMBER_OF field). 8252 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8253 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8254 } 8255 } 8256 8257 /// Generate the base pointers, section pointers, sizes and map types 8258 /// associated to a given capture. 8259 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8260 llvm::Value *Arg, 8261 MapBaseValuesArrayTy &BasePointers, 8262 MapValuesArrayTy &Pointers, 8263 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8264 StructRangeInfoTy &PartialStruct) const { 8265 assert(!Cap->capturesVariableArrayType() && 8266 "Not expecting to generate map info for a variable array type!"); 8267 8268 // We need to know when we generating information for the first component 8269 const ValueDecl *VD = Cap->capturesThis() 8270 ? nullptr 8271 : Cap->getCapturedVar()->getCanonicalDecl(); 8272 8273 // If this declaration appears in a is_device_ptr clause we just have to 8274 // pass the pointer by value. If it is a reference to a declaration, we just 8275 // pass its value. 8276 if (DevPointersMap.count(VD)) { 8277 BasePointers.emplace_back(Arg, VD); 8278 Pointers.push_back(Arg); 8279 Sizes.push_back( 8280 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8281 CGF.Int64Ty, /*isSigned=*/true)); 8282 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8283 return; 8284 } 8285 8286 using MapData = 8287 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8288 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8289 SmallVector<MapData, 4> DeclComponentLists; 8290 assert(CurDir.is<const OMPExecutableDirective *>() && 8291 "Expect a executable directive"); 8292 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8293 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8294 for (const auto L : C->decl_component_lists(VD)) { 8295 assert(L.first == VD && 8296 "We got information for the wrong declaration??"); 8297 assert(!L.second.empty() && 8298 "Not expecting declaration with no component lists."); 8299 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8300 C->getMapTypeModifiers(), 8301 C->isImplicit()); 8302 } 8303 } 8304 8305 // Find overlapping elements (including the offset from the base element). 8306 llvm::SmallDenseMap< 8307 const MapData *, 8308 llvm::SmallVector< 8309 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8310 4> 8311 OverlappedData; 8312 size_t Count = 0; 8313 for (const MapData &L : DeclComponentLists) { 8314 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8315 OpenMPMapClauseKind MapType; 8316 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8317 bool IsImplicit; 8318 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8319 ++Count; 8320 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8321 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8322 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8323 auto CI = Components.rbegin(); 8324 auto CE = Components.rend(); 8325 auto SI = Components1.rbegin(); 8326 auto SE = Components1.rend(); 8327 for (; CI != CE && SI != SE; ++CI, ++SI) { 8328 if (CI->getAssociatedExpression()->getStmtClass() != 8329 SI->getAssociatedExpression()->getStmtClass()) 8330 break; 8331 // Are we dealing with different variables/fields? 8332 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8333 break; 8334 } 8335 // Found overlapping if, at least for one component, reached the head of 8336 // the components list. 8337 if (CI == CE || SI == SE) { 8338 assert((CI != CE || SI != SE) && 8339 "Unexpected full match of the mapping components."); 8340 const MapData &BaseData = CI == CE ? L : L1; 8341 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8342 SI == SE ? Components : Components1; 8343 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8344 OverlappedElements.getSecond().push_back(SubData); 8345 } 8346 } 8347 } 8348 // Sort the overlapped elements for each item. 8349 llvm::SmallVector<const FieldDecl *, 4> Layout; 8350 if (!OverlappedData.empty()) { 8351 if (const auto *CRD = 8352 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8353 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8354 else { 8355 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8356 Layout.append(RD->field_begin(), RD->field_end()); 8357 } 8358 } 8359 for (auto &Pair : OverlappedData) { 8360 llvm::sort( 8361 Pair.getSecond(), 8362 [&Layout]( 8363 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8364 OMPClauseMappableExprCommon::MappableExprComponentListRef 8365 Second) { 8366 auto CI = First.rbegin(); 8367 auto CE = First.rend(); 8368 auto SI = Second.rbegin(); 8369 auto SE = Second.rend(); 8370 for (; CI != CE && SI != SE; ++CI, ++SI) { 8371 if (CI->getAssociatedExpression()->getStmtClass() != 8372 SI->getAssociatedExpression()->getStmtClass()) 8373 break; 8374 // Are we dealing with different variables/fields? 8375 if (CI->getAssociatedDeclaration() != 8376 SI->getAssociatedDeclaration()) 8377 break; 8378 } 8379 8380 // Lists contain the same elements. 8381 if (CI == CE && SI == SE) 8382 return false; 8383 8384 // List with less elements is less than list with more elements. 8385 if (CI == CE || SI == SE) 8386 return CI == CE; 8387 8388 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8389 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8390 if (FD1->getParent() == FD2->getParent()) 8391 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8392 const auto It = 8393 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8394 return FD == FD1 || FD == FD2; 8395 }); 8396 return *It == FD1; 8397 }); 8398 } 8399 8400 // Associated with a capture, because the mapping flags depend on it. 8401 // Go through all of the elements with the overlapped elements. 8402 for (const auto &Pair : OverlappedData) { 8403 const MapData &L = *Pair.getFirst(); 8404 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8405 OpenMPMapClauseKind MapType; 8406 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8407 bool IsImplicit; 8408 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8409 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8410 OverlappedComponents = Pair.getSecond(); 8411 bool IsFirstComponentList = true; 8412 generateInfoForComponentList(MapType, MapModifiers, Components, 8413 BasePointers, Pointers, Sizes, Types, 8414 PartialStruct, IsFirstComponentList, 8415 IsImplicit, OverlappedComponents); 8416 } 8417 // Go through other elements without overlapped elements. 8418 bool IsFirstComponentList = OverlappedData.empty(); 8419 for (const MapData &L : DeclComponentLists) { 8420 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8421 OpenMPMapClauseKind MapType; 8422 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8423 bool IsImplicit; 8424 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8425 auto It = OverlappedData.find(&L); 8426 if (It == OverlappedData.end()) 8427 generateInfoForComponentList(MapType, MapModifiers, Components, 8428 BasePointers, Pointers, Sizes, Types, 8429 PartialStruct, IsFirstComponentList, 8430 IsImplicit); 8431 IsFirstComponentList = false; 8432 } 8433 } 8434 8435 /// Generate the base pointers, section pointers, sizes and map types 8436 /// associated with the declare target link variables. 8437 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8438 MapValuesArrayTy &Pointers, 8439 MapValuesArrayTy &Sizes, 8440 MapFlagsArrayTy &Types) const { 8441 assert(CurDir.is<const OMPExecutableDirective *>() && 8442 "Expect a executable directive"); 8443 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8444 // Map other list items in the map clause which are not captured variables 8445 // but "declare target link" global variables. 8446 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8447 for (const auto L : C->component_lists()) { 8448 if (!L.first) 8449 continue; 8450 const auto *VD = dyn_cast<VarDecl>(L.first); 8451 if (!VD) 8452 continue; 8453 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8454 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8455 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8456 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8457 continue; 8458 StructRangeInfoTy PartialStruct; 8459 generateInfoForComponentList( 8460 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8461 Pointers, Sizes, Types, PartialStruct, 8462 /*IsFirstComponentList=*/true, C->isImplicit()); 8463 assert(!PartialStruct.Base.isValid() && 8464 "No partial structs for declare target link expected."); 8465 } 8466 } 8467 } 8468 8469 /// Generate the default map information for a given capture \a CI, 8470 /// record field declaration \a RI and captured value \a CV. 8471 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8472 const FieldDecl &RI, llvm::Value *CV, 8473 MapBaseValuesArrayTy &CurBasePointers, 8474 MapValuesArrayTy &CurPointers, 8475 MapValuesArrayTy &CurSizes, 8476 MapFlagsArrayTy &CurMapTypes) const { 8477 bool IsImplicit = true; 8478 // Do the default mapping. 8479 if (CI.capturesThis()) { 8480 CurBasePointers.push_back(CV); 8481 CurPointers.push_back(CV); 8482 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8483 CurSizes.push_back( 8484 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8485 CGF.Int64Ty, /*isSigned=*/true)); 8486 // Default map type. 8487 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8488 } else if (CI.capturesVariableByCopy()) { 8489 CurBasePointers.push_back(CV); 8490 CurPointers.push_back(CV); 8491 if (!RI.getType()->isAnyPointerType()) { 8492 // We have to signal to the runtime captures passed by value that are 8493 // not pointers. 8494 CurMapTypes.push_back(OMP_MAP_LITERAL); 8495 CurSizes.push_back(CGF.Builder.CreateIntCast( 8496 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8497 } else { 8498 // Pointers are implicitly mapped with a zero size and no flags 8499 // (other than first map that is added for all implicit maps). 8500 CurMapTypes.push_back(OMP_MAP_NONE); 8501 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8502 } 8503 const VarDecl *VD = CI.getCapturedVar(); 8504 auto I = FirstPrivateDecls.find(VD); 8505 if (I != FirstPrivateDecls.end()) 8506 IsImplicit = I->getSecond(); 8507 } else { 8508 assert(CI.capturesVariable() && "Expected captured reference."); 8509 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8510 QualType ElementType = PtrTy->getPointeeType(); 8511 CurSizes.push_back(CGF.Builder.CreateIntCast( 8512 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8513 // The default map type for a scalar/complex type is 'to' because by 8514 // default the value doesn't have to be retrieved. For an aggregate 8515 // type, the default is 'tofrom'. 8516 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8517 const VarDecl *VD = CI.getCapturedVar(); 8518 auto I = FirstPrivateDecls.find(VD); 8519 if (I != FirstPrivateDecls.end() && 8520 VD->getType().isConstant(CGF.getContext())) { 8521 llvm::Constant *Addr = 8522 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8523 // Copy the value of the original variable to the new global copy. 8524 CGF.Builder.CreateMemCpy( 8525 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(), 8526 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8527 CurSizes.back(), /*IsVolatile=*/false); 8528 // Use new global variable as the base pointers. 8529 CurBasePointers.push_back(Addr); 8530 CurPointers.push_back(Addr); 8531 } else { 8532 CurBasePointers.push_back(CV); 8533 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8534 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8535 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8536 AlignmentSource::Decl)); 8537 CurPointers.push_back(PtrAddr.getPointer()); 8538 } else { 8539 CurPointers.push_back(CV); 8540 } 8541 } 8542 if (I != FirstPrivateDecls.end()) 8543 IsImplicit = I->getSecond(); 8544 } 8545 // Every default map produces a single argument which is a target parameter. 8546 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8547 8548 // Add flag stating this is an implicit map. 8549 if (IsImplicit) 8550 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8551 } 8552 }; 8553 } // anonymous namespace 8554 8555 /// Emit the arrays used to pass the captures and map information to the 8556 /// offloading runtime library. If there is no map or capture information, 8557 /// return nullptr by reference. 8558 static void 8559 emitOffloadingArrays(CodeGenFunction &CGF, 8560 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8561 MappableExprsHandler::MapValuesArrayTy &Pointers, 8562 MappableExprsHandler::MapValuesArrayTy &Sizes, 8563 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8564 CGOpenMPRuntime::TargetDataInfo &Info) { 8565 CodeGenModule &CGM = CGF.CGM; 8566 ASTContext &Ctx = CGF.getContext(); 8567 8568 // Reset the array information. 8569 Info.clearArrayInfo(); 8570 Info.NumberOfPtrs = BasePointers.size(); 8571 8572 if (Info.NumberOfPtrs) { 8573 // Detect if we have any capture size requiring runtime evaluation of the 8574 // size so that a constant array could be eventually used. 8575 bool hasRuntimeEvaluationCaptureSize = false; 8576 for (llvm::Value *S : Sizes) 8577 if (!isa<llvm::Constant>(S)) { 8578 hasRuntimeEvaluationCaptureSize = true; 8579 break; 8580 } 8581 8582 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8583 QualType PointerArrayType = Ctx.getConstantArrayType( 8584 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8585 /*IndexTypeQuals=*/0); 8586 8587 Info.BasePointersArray = 8588 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8589 Info.PointersArray = 8590 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8591 8592 // If we don't have any VLA types or other types that require runtime 8593 // evaluation, we can use a constant array for the map sizes, otherwise we 8594 // need to fill up the arrays as we do for the pointers. 8595 QualType Int64Ty = 8596 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8597 if (hasRuntimeEvaluationCaptureSize) { 8598 QualType SizeArrayType = Ctx.getConstantArrayType( 8599 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8600 /*IndexTypeQuals=*/0); 8601 Info.SizesArray = 8602 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8603 } else { 8604 // We expect all the sizes to be constant, so we collect them to create 8605 // a constant array. 8606 SmallVector<llvm::Constant *, 16> ConstSizes; 8607 for (llvm::Value *S : Sizes) 8608 ConstSizes.push_back(cast<llvm::Constant>(S)); 8609 8610 auto *SizesArrayInit = llvm::ConstantArray::get( 8611 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8612 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8613 auto *SizesArrayGbl = new llvm::GlobalVariable( 8614 CGM.getModule(), SizesArrayInit->getType(), 8615 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8616 SizesArrayInit, Name); 8617 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8618 Info.SizesArray = SizesArrayGbl; 8619 } 8620 8621 // The map types are always constant so we don't need to generate code to 8622 // fill arrays. Instead, we create an array constant. 8623 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8624 llvm::copy(MapTypes, Mapping.begin()); 8625 llvm::Constant *MapTypesArrayInit = 8626 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8627 std::string MaptypesName = 8628 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8629 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8630 CGM.getModule(), MapTypesArrayInit->getType(), 8631 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8632 MapTypesArrayInit, MaptypesName); 8633 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8634 Info.MapTypesArray = MapTypesArrayGbl; 8635 8636 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8637 llvm::Value *BPVal = *BasePointers[I]; 8638 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8639 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8640 Info.BasePointersArray, 0, I); 8641 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8642 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8643 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8644 CGF.Builder.CreateStore(BPVal, BPAddr); 8645 8646 if (Info.requiresDevicePointerInfo()) 8647 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8648 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8649 8650 llvm::Value *PVal = Pointers[I]; 8651 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8652 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8653 Info.PointersArray, 0, I); 8654 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8655 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8656 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8657 CGF.Builder.CreateStore(PVal, PAddr); 8658 8659 if (hasRuntimeEvaluationCaptureSize) { 8660 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8661 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8662 Info.SizesArray, 8663 /*Idx0=*/0, 8664 /*Idx1=*/I); 8665 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8666 CGF.Builder.CreateStore( 8667 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8668 SAddr); 8669 } 8670 } 8671 } 8672 } 8673 8674 /// Emit the arguments to be passed to the runtime library based on the 8675 /// arrays of pointers, sizes and map types. 8676 static void emitOffloadingArraysArgument( 8677 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8678 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8679 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8680 CodeGenModule &CGM = CGF.CGM; 8681 if (Info.NumberOfPtrs) { 8682 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8683 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8684 Info.BasePointersArray, 8685 /*Idx0=*/0, /*Idx1=*/0); 8686 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8687 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8688 Info.PointersArray, 8689 /*Idx0=*/0, 8690 /*Idx1=*/0); 8691 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8692 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8693 /*Idx0=*/0, /*Idx1=*/0); 8694 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8695 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8696 Info.MapTypesArray, 8697 /*Idx0=*/0, 8698 /*Idx1=*/0); 8699 } else { 8700 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8701 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8702 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8703 MapTypesArrayArg = 8704 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8705 } 8706 } 8707 8708 /// Check for inner distribute directive. 8709 static const OMPExecutableDirective * 8710 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8711 const auto *CS = D.getInnermostCapturedStmt(); 8712 const auto *Body = 8713 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8714 const Stmt *ChildStmt = 8715 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8716 8717 if (const auto *NestedDir = 8718 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8719 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8720 switch (D.getDirectiveKind()) { 8721 case OMPD_target: 8722 if (isOpenMPDistributeDirective(DKind)) 8723 return NestedDir; 8724 if (DKind == OMPD_teams) { 8725 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8726 /*IgnoreCaptured=*/true); 8727 if (!Body) 8728 return nullptr; 8729 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8730 if (const auto *NND = 8731 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8732 DKind = NND->getDirectiveKind(); 8733 if (isOpenMPDistributeDirective(DKind)) 8734 return NND; 8735 } 8736 } 8737 return nullptr; 8738 case OMPD_target_teams: 8739 if (isOpenMPDistributeDirective(DKind)) 8740 return NestedDir; 8741 return nullptr; 8742 case OMPD_target_parallel: 8743 case OMPD_target_simd: 8744 case OMPD_target_parallel_for: 8745 case OMPD_target_parallel_for_simd: 8746 return nullptr; 8747 case OMPD_target_teams_distribute: 8748 case OMPD_target_teams_distribute_simd: 8749 case OMPD_target_teams_distribute_parallel_for: 8750 case OMPD_target_teams_distribute_parallel_for_simd: 8751 case OMPD_parallel: 8752 case OMPD_for: 8753 case OMPD_parallel_for: 8754 case OMPD_parallel_sections: 8755 case OMPD_for_simd: 8756 case OMPD_parallel_for_simd: 8757 case OMPD_cancel: 8758 case OMPD_cancellation_point: 8759 case OMPD_ordered: 8760 case OMPD_threadprivate: 8761 case OMPD_allocate: 8762 case OMPD_task: 8763 case OMPD_simd: 8764 case OMPD_sections: 8765 case OMPD_section: 8766 case OMPD_single: 8767 case OMPD_master: 8768 case OMPD_critical: 8769 case OMPD_taskyield: 8770 case OMPD_barrier: 8771 case OMPD_taskwait: 8772 case OMPD_taskgroup: 8773 case OMPD_atomic: 8774 case OMPD_flush: 8775 case OMPD_teams: 8776 case OMPD_target_data: 8777 case OMPD_target_exit_data: 8778 case OMPD_target_enter_data: 8779 case OMPD_distribute: 8780 case OMPD_distribute_simd: 8781 case OMPD_distribute_parallel_for: 8782 case OMPD_distribute_parallel_for_simd: 8783 case OMPD_teams_distribute: 8784 case OMPD_teams_distribute_simd: 8785 case OMPD_teams_distribute_parallel_for: 8786 case OMPD_teams_distribute_parallel_for_simd: 8787 case OMPD_target_update: 8788 case OMPD_declare_simd: 8789 case OMPD_declare_variant: 8790 case OMPD_declare_target: 8791 case OMPD_end_declare_target: 8792 case OMPD_declare_reduction: 8793 case OMPD_declare_mapper: 8794 case OMPD_taskloop: 8795 case OMPD_taskloop_simd: 8796 case OMPD_master_taskloop: 8797 case OMPD_master_taskloop_simd: 8798 case OMPD_parallel_master_taskloop: 8799 case OMPD_parallel_master_taskloop_simd: 8800 case OMPD_requires: 8801 case OMPD_unknown: 8802 llvm_unreachable("Unexpected directive."); 8803 } 8804 } 8805 8806 return nullptr; 8807 } 8808 8809 /// Emit the user-defined mapper function. The code generation follows the 8810 /// pattern in the example below. 8811 /// \code 8812 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8813 /// void *base, void *begin, 8814 /// int64_t size, int64_t type) { 8815 /// // Allocate space for an array section first. 8816 /// if (size > 1 && !maptype.IsDelete) 8817 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8818 /// size*sizeof(Ty), clearToFrom(type)); 8819 /// // Map members. 8820 /// for (unsigned i = 0; i < size; i++) { 8821 /// // For each component specified by this mapper: 8822 /// for (auto c : all_components) { 8823 /// if (c.hasMapper()) 8824 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8825 /// c.arg_type); 8826 /// else 8827 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8828 /// c.arg_begin, c.arg_size, c.arg_type); 8829 /// } 8830 /// } 8831 /// // Delete the array section. 8832 /// if (size > 1 && maptype.IsDelete) 8833 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8834 /// size*sizeof(Ty), clearToFrom(type)); 8835 /// } 8836 /// \endcode 8837 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8838 CodeGenFunction *CGF) { 8839 if (UDMMap.count(D) > 0) 8840 return; 8841 ASTContext &C = CGM.getContext(); 8842 QualType Ty = D->getType(); 8843 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8844 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8845 auto *MapperVarDecl = 8846 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8847 SourceLocation Loc = D->getLocation(); 8848 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8849 8850 // Prepare mapper function arguments and attributes. 8851 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8852 C.VoidPtrTy, ImplicitParamDecl::Other); 8853 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8854 ImplicitParamDecl::Other); 8855 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8856 C.VoidPtrTy, ImplicitParamDecl::Other); 8857 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8858 ImplicitParamDecl::Other); 8859 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8860 ImplicitParamDecl::Other); 8861 FunctionArgList Args; 8862 Args.push_back(&HandleArg); 8863 Args.push_back(&BaseArg); 8864 Args.push_back(&BeginArg); 8865 Args.push_back(&SizeArg); 8866 Args.push_back(&TypeArg); 8867 const CGFunctionInfo &FnInfo = 8868 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8869 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8870 SmallString<64> TyStr; 8871 llvm::raw_svector_ostream Out(TyStr); 8872 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 8873 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 8874 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 8875 Name, &CGM.getModule()); 8876 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 8877 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 8878 // Start the mapper function code generation. 8879 CodeGenFunction MapperCGF(CGM); 8880 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 8881 // Compute the starting and end addreses of array elements. 8882 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 8883 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 8884 C.getPointerType(Int64Ty), Loc); 8885 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 8886 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 8887 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 8888 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 8889 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 8890 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 8891 C.getPointerType(Int64Ty), Loc); 8892 // Prepare common arguments for array initiation and deletion. 8893 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 8894 MapperCGF.GetAddrOfLocalVar(&HandleArg), 8895 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8896 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 8897 MapperCGF.GetAddrOfLocalVar(&BaseArg), 8898 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8899 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 8900 MapperCGF.GetAddrOfLocalVar(&BeginArg), 8901 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8902 8903 // Emit array initiation if this is an array section and \p MapType indicates 8904 // that memory allocation is required. 8905 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 8906 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8907 ElementSize, HeadBB, /*IsInit=*/true); 8908 8909 // Emit a for loop to iterate through SizeArg of elements and map all of them. 8910 8911 // Emit the loop header block. 8912 MapperCGF.EmitBlock(HeadBB); 8913 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 8914 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 8915 // Evaluate whether the initial condition is satisfied. 8916 llvm::Value *IsEmpty = 8917 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 8918 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 8919 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 8920 8921 // Emit the loop body block. 8922 MapperCGF.EmitBlock(BodyBB); 8923 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 8924 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 8925 PtrPHI->addIncoming(PtrBegin, EntryBB); 8926 Address PtrCurrent = 8927 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 8928 .getAlignment() 8929 .alignmentOfArrayElement(ElementSize)); 8930 // Privatize the declared variable of mapper to be the current array element. 8931 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 8932 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 8933 return MapperCGF 8934 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 8935 .getAddress(); 8936 }); 8937 (void)Scope.Privatize(); 8938 8939 // Get map clause information. Fill up the arrays with all mapped variables. 8940 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 8941 MappableExprsHandler::MapValuesArrayTy Pointers; 8942 MappableExprsHandler::MapValuesArrayTy Sizes; 8943 MappableExprsHandler::MapFlagsArrayTy MapTypes; 8944 MappableExprsHandler MEHandler(*D, MapperCGF); 8945 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 8946 8947 // Call the runtime API __tgt_mapper_num_components to get the number of 8948 // pre-existing components. 8949 llvm::Value *OffloadingArgs[] = {Handle}; 8950 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 8951 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 8952 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 8953 PreviousSize, 8954 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 8955 8956 // Fill up the runtime mapper handle for all components. 8957 for (unsigned I = 0; I < BasePointers.size(); ++I) { 8958 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 8959 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8960 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 8961 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8962 llvm::Value *CurSizeArg = Sizes[I]; 8963 8964 // Extract the MEMBER_OF field from the map type. 8965 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 8966 MapperCGF.EmitBlock(MemberBB); 8967 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 8968 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 8969 OriMapType, 8970 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 8971 llvm::BasicBlock *MemberCombineBB = 8972 MapperCGF.createBasicBlock("omp.member.combine"); 8973 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 8974 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 8975 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 8976 // Add the number of pre-existing components to the MEMBER_OF field if it 8977 // is valid. 8978 MapperCGF.EmitBlock(MemberCombineBB); 8979 llvm::Value *CombinedMember = 8980 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 8981 // Do nothing if it is not a member of previous components. 8982 MapperCGF.EmitBlock(TypeBB); 8983 llvm::PHINode *MemberMapType = 8984 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 8985 MemberMapType->addIncoming(OriMapType, MemberBB); 8986 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 8987 8988 // Combine the map type inherited from user-defined mapper with that 8989 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 8990 // bits of the \a MapType, which is the input argument of the mapper 8991 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 8992 // bits of MemberMapType. 8993 // [OpenMP 5.0], 1.2.6. map-type decay. 8994 // | alloc | to | from | tofrom | release | delete 8995 // ---------------------------------------------------------- 8996 // alloc | alloc | alloc | alloc | alloc | release | delete 8997 // to | alloc | to | alloc | to | release | delete 8998 // from | alloc | alloc | from | from | release | delete 8999 // tofrom | alloc | to | from | tofrom | release | delete 9000 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 9001 MapType, 9002 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 9003 MappableExprsHandler::OMP_MAP_FROM)); 9004 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 9005 llvm::BasicBlock *AllocElseBB = 9006 MapperCGF.createBasicBlock("omp.type.alloc.else"); 9007 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 9008 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 9009 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9010 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9011 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9012 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9013 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9014 MapperCGF.EmitBlock(AllocBB); 9015 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9016 MemberMapType, 9017 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9018 MappableExprsHandler::OMP_MAP_FROM))); 9019 MapperCGF.Builder.CreateBr(EndBB); 9020 MapperCGF.EmitBlock(AllocElseBB); 9021 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9022 LeftToFrom, 9023 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9024 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9025 // In case of to, clear OMP_MAP_FROM. 9026 MapperCGF.EmitBlock(ToBB); 9027 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9028 MemberMapType, 9029 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9030 MapperCGF.Builder.CreateBr(EndBB); 9031 MapperCGF.EmitBlock(ToElseBB); 9032 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9033 LeftToFrom, 9034 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9035 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9036 // In case of from, clear OMP_MAP_TO. 9037 MapperCGF.EmitBlock(FromBB); 9038 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9039 MemberMapType, 9040 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9041 // In case of tofrom, do nothing. 9042 MapperCGF.EmitBlock(EndBB); 9043 llvm::PHINode *CurMapType = 9044 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9045 CurMapType->addIncoming(AllocMapType, AllocBB); 9046 CurMapType->addIncoming(ToMapType, ToBB); 9047 CurMapType->addIncoming(FromMapType, FromBB); 9048 CurMapType->addIncoming(MemberMapType, ToElseBB); 9049 9050 // TODO: call the corresponding mapper function if a user-defined mapper is 9051 // associated with this map clause. 9052 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9053 // data structure. 9054 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9055 CurSizeArg, CurMapType}; 9056 MapperCGF.EmitRuntimeCall( 9057 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9058 OffloadingArgs); 9059 } 9060 9061 // Update the pointer to point to the next element that needs to be mapped, 9062 // and check whether we have mapped all elements. 9063 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9064 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9065 PtrPHI->addIncoming(PtrNext, BodyBB); 9066 llvm::Value *IsDone = 9067 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9068 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9069 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9070 9071 MapperCGF.EmitBlock(ExitBB); 9072 // Emit array deletion if this is an array section and \p MapType indicates 9073 // that deletion is required. 9074 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9075 ElementSize, DoneBB, /*IsInit=*/false); 9076 9077 // Emit the function exit block. 9078 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9079 MapperCGF.FinishFunction(); 9080 UDMMap.try_emplace(D, Fn); 9081 if (CGF) { 9082 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9083 Decls.second.push_back(D); 9084 } 9085 } 9086 9087 /// Emit the array initialization or deletion portion for user-defined mapper 9088 /// code generation. First, it evaluates whether an array section is mapped and 9089 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9090 /// true, and \a MapType indicates to not delete this array, array 9091 /// initialization code is generated. If \a IsInit is false, and \a MapType 9092 /// indicates to not this array, array deletion code is generated. 9093 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9094 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9095 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9096 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9097 StringRef Prefix = IsInit ? ".init" : ".del"; 9098 9099 // Evaluate if this is an array section. 9100 llvm::BasicBlock *IsDeleteBB = 9101 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete"); 9102 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix); 9103 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9104 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9105 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9106 9107 // Evaluate if we are going to delete this section. 9108 MapperCGF.EmitBlock(IsDeleteBB); 9109 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9110 MapType, 9111 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9112 llvm::Value *DeleteCond; 9113 if (IsInit) { 9114 DeleteCond = MapperCGF.Builder.CreateIsNull( 9115 DeleteBit, "omp.array" + Prefix + ".delete"); 9116 } else { 9117 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9118 DeleteBit, "omp.array" + Prefix + ".delete"); 9119 } 9120 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9121 9122 MapperCGF.EmitBlock(BodyBB); 9123 // Get the array size by multiplying element size and element number (i.e., \p 9124 // Size). 9125 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9126 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9127 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9128 // memory allocation/deletion purpose only. 9129 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9130 MapType, 9131 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9132 MappableExprsHandler::OMP_MAP_FROM))); 9133 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9134 // data structure. 9135 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9136 MapperCGF.EmitRuntimeCall( 9137 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9138 } 9139 9140 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9141 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9142 llvm::Value *DeviceID, 9143 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9144 const OMPLoopDirective &D)> 9145 SizeEmitter) { 9146 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9147 const OMPExecutableDirective *TD = &D; 9148 // Get nested teams distribute kind directive, if any. 9149 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9150 TD = getNestedDistributeDirective(CGM.getContext(), D); 9151 if (!TD) 9152 return; 9153 const auto *LD = cast<OMPLoopDirective>(TD); 9154 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9155 PrePostActionTy &) { 9156 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9157 llvm::Value *Args[] = {DeviceID, NumIterations}; 9158 CGF.EmitRuntimeCall( 9159 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9160 } 9161 }; 9162 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9163 } 9164 9165 void CGOpenMPRuntime::emitTargetCall( 9166 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9167 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9168 const Expr *Device, 9169 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9170 const OMPLoopDirective &D)> 9171 SizeEmitter) { 9172 if (!CGF.HaveInsertPoint()) 9173 return; 9174 9175 assert(OutlinedFn && "Invalid outlined function!"); 9176 9177 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9178 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9179 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9180 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9181 PrePostActionTy &) { 9182 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9183 }; 9184 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9185 9186 CodeGenFunction::OMPTargetDataInfo InputInfo; 9187 llvm::Value *MapTypesArray = nullptr; 9188 // Fill up the pointer arrays and transfer execution to the device. 9189 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9190 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9191 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9192 // On top of the arrays that were filled up, the target offloading call 9193 // takes as arguments the device id as well as the host pointer. The host 9194 // pointer is used by the runtime library to identify the current target 9195 // region, so it only has to be unique and not necessarily point to 9196 // anything. It could be the pointer to the outlined function that 9197 // implements the target region, but we aren't using that so that the 9198 // compiler doesn't need to keep that, and could therefore inline the host 9199 // function if proven worthwhile during optimization. 9200 9201 // From this point on, we need to have an ID of the target region defined. 9202 assert(OutlinedFnID && "Invalid outlined function ID!"); 9203 9204 // Emit device ID if any. 9205 llvm::Value *DeviceID; 9206 if (Device) { 9207 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9208 CGF.Int64Ty, /*isSigned=*/true); 9209 } else { 9210 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9211 } 9212 9213 // Emit the number of elements in the offloading arrays. 9214 llvm::Value *PointerNum = 9215 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9216 9217 // Return value of the runtime offloading call. 9218 llvm::Value *Return; 9219 9220 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9221 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9222 9223 // Emit tripcount for the target loop-based directive. 9224 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9225 9226 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9227 // The target region is an outlined function launched by the runtime 9228 // via calls __tgt_target() or __tgt_target_teams(). 9229 // 9230 // __tgt_target() launches a target region with one team and one thread, 9231 // executing a serial region. This master thread may in turn launch 9232 // more threads within its team upon encountering a parallel region, 9233 // however, no additional teams can be launched on the device. 9234 // 9235 // __tgt_target_teams() launches a target region with one or more teams, 9236 // each with one or more threads. This call is required for target 9237 // constructs such as: 9238 // 'target teams' 9239 // 'target' / 'teams' 9240 // 'target teams distribute parallel for' 9241 // 'target parallel' 9242 // and so on. 9243 // 9244 // Note that on the host and CPU targets, the runtime implementation of 9245 // these calls simply call the outlined function without forking threads. 9246 // The outlined functions themselves have runtime calls to 9247 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9248 // the compiler in emitTeamsCall() and emitParallelCall(). 9249 // 9250 // In contrast, on the NVPTX target, the implementation of 9251 // __tgt_target_teams() launches a GPU kernel with the requested number 9252 // of teams and threads so no additional calls to the runtime are required. 9253 if (NumTeams) { 9254 // If we have NumTeams defined this means that we have an enclosed teams 9255 // region. Therefore we also expect to have NumThreads defined. These two 9256 // values should be defined in the presence of a teams directive, 9257 // regardless of having any clauses associated. If the user is using teams 9258 // but no clauses, these two values will be the default that should be 9259 // passed to the runtime library - a 32-bit integer with the value zero. 9260 assert(NumThreads && "Thread limit expression should be available along " 9261 "with number of teams."); 9262 llvm::Value *OffloadingArgs[] = {DeviceID, 9263 OutlinedFnID, 9264 PointerNum, 9265 InputInfo.BasePointersArray.getPointer(), 9266 InputInfo.PointersArray.getPointer(), 9267 InputInfo.SizesArray.getPointer(), 9268 MapTypesArray, 9269 NumTeams, 9270 NumThreads}; 9271 Return = CGF.EmitRuntimeCall( 9272 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9273 : OMPRTL__tgt_target_teams), 9274 OffloadingArgs); 9275 } else { 9276 llvm::Value *OffloadingArgs[] = {DeviceID, 9277 OutlinedFnID, 9278 PointerNum, 9279 InputInfo.BasePointersArray.getPointer(), 9280 InputInfo.PointersArray.getPointer(), 9281 InputInfo.SizesArray.getPointer(), 9282 MapTypesArray}; 9283 Return = CGF.EmitRuntimeCall( 9284 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9285 : OMPRTL__tgt_target), 9286 OffloadingArgs); 9287 } 9288 9289 // Check the error code and execute the host version if required. 9290 llvm::BasicBlock *OffloadFailedBlock = 9291 CGF.createBasicBlock("omp_offload.failed"); 9292 llvm::BasicBlock *OffloadContBlock = 9293 CGF.createBasicBlock("omp_offload.cont"); 9294 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9295 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9296 9297 CGF.EmitBlock(OffloadFailedBlock); 9298 if (RequiresOuterTask) { 9299 CapturedVars.clear(); 9300 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9301 } 9302 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9303 CGF.EmitBranch(OffloadContBlock); 9304 9305 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9306 }; 9307 9308 // Notify that the host version must be executed. 9309 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9310 RequiresOuterTask](CodeGenFunction &CGF, 9311 PrePostActionTy &) { 9312 if (RequiresOuterTask) { 9313 CapturedVars.clear(); 9314 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9315 } 9316 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9317 }; 9318 9319 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9320 &CapturedVars, RequiresOuterTask, 9321 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9322 // Fill up the arrays with all the captured variables. 9323 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9324 MappableExprsHandler::MapValuesArrayTy Pointers; 9325 MappableExprsHandler::MapValuesArrayTy Sizes; 9326 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9327 9328 // Get mappable expression information. 9329 MappableExprsHandler MEHandler(D, CGF); 9330 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9331 9332 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9333 auto CV = CapturedVars.begin(); 9334 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9335 CE = CS.capture_end(); 9336 CI != CE; ++CI, ++RI, ++CV) { 9337 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9338 MappableExprsHandler::MapValuesArrayTy CurPointers; 9339 MappableExprsHandler::MapValuesArrayTy CurSizes; 9340 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9341 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9342 9343 // VLA sizes are passed to the outlined region by copy and do not have map 9344 // information associated. 9345 if (CI->capturesVariableArrayType()) { 9346 CurBasePointers.push_back(*CV); 9347 CurPointers.push_back(*CV); 9348 CurSizes.push_back(CGF.Builder.CreateIntCast( 9349 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9350 // Copy to the device as an argument. No need to retrieve it. 9351 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9352 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9353 MappableExprsHandler::OMP_MAP_IMPLICIT); 9354 } else { 9355 // If we have any information in the map clause, we use it, otherwise we 9356 // just do a default mapping. 9357 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9358 CurSizes, CurMapTypes, PartialStruct); 9359 if (CurBasePointers.empty()) 9360 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9361 CurPointers, CurSizes, CurMapTypes); 9362 // Generate correct mapping for variables captured by reference in 9363 // lambdas. 9364 if (CI->capturesVariable()) 9365 MEHandler.generateInfoForLambdaCaptures( 9366 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9367 CurMapTypes, LambdaPointers); 9368 } 9369 // We expect to have at least an element of information for this capture. 9370 assert(!CurBasePointers.empty() && 9371 "Non-existing map pointer for capture!"); 9372 assert(CurBasePointers.size() == CurPointers.size() && 9373 CurBasePointers.size() == CurSizes.size() && 9374 CurBasePointers.size() == CurMapTypes.size() && 9375 "Inconsistent map information sizes!"); 9376 9377 // If there is an entry in PartialStruct it means we have a struct with 9378 // individual members mapped. Emit an extra combined entry. 9379 if (PartialStruct.Base.isValid()) 9380 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9381 CurMapTypes, PartialStruct); 9382 9383 // We need to append the results of this capture to what we already have. 9384 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9385 Pointers.append(CurPointers.begin(), CurPointers.end()); 9386 Sizes.append(CurSizes.begin(), CurSizes.end()); 9387 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9388 } 9389 // Adjust MEMBER_OF flags for the lambdas captures. 9390 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9391 Pointers, MapTypes); 9392 // Map other list items in the map clause which are not captured variables 9393 // but "declare target link" global variables. 9394 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9395 MapTypes); 9396 9397 TargetDataInfo Info; 9398 // Fill up the arrays and create the arguments. 9399 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9400 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9401 Info.PointersArray, Info.SizesArray, 9402 Info.MapTypesArray, Info); 9403 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9404 InputInfo.BasePointersArray = 9405 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9406 InputInfo.PointersArray = 9407 Address(Info.PointersArray, CGM.getPointerAlign()); 9408 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9409 MapTypesArray = Info.MapTypesArray; 9410 if (RequiresOuterTask) 9411 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9412 else 9413 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9414 }; 9415 9416 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9417 CodeGenFunction &CGF, PrePostActionTy &) { 9418 if (RequiresOuterTask) { 9419 CodeGenFunction::OMPTargetDataInfo InputInfo; 9420 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9421 } else { 9422 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9423 } 9424 }; 9425 9426 // If we have a target function ID it means that we need to support 9427 // offloading, otherwise, just execute on the host. We need to execute on host 9428 // regardless of the conditional in the if clause if, e.g., the user do not 9429 // specify target triples. 9430 if (OutlinedFnID) { 9431 if (IfCond) { 9432 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9433 } else { 9434 RegionCodeGenTy ThenRCG(TargetThenGen); 9435 ThenRCG(CGF); 9436 } 9437 } else { 9438 RegionCodeGenTy ElseRCG(TargetElseGen); 9439 ElseRCG(CGF); 9440 } 9441 } 9442 9443 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9444 StringRef ParentName) { 9445 if (!S) 9446 return; 9447 9448 // Codegen OMP target directives that offload compute to the device. 9449 bool RequiresDeviceCodegen = 9450 isa<OMPExecutableDirective>(S) && 9451 isOpenMPTargetExecutionDirective( 9452 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9453 9454 if (RequiresDeviceCodegen) { 9455 const auto &E = *cast<OMPExecutableDirective>(S); 9456 unsigned DeviceID; 9457 unsigned FileID; 9458 unsigned Line; 9459 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9460 FileID, Line); 9461 9462 // Is this a target region that should not be emitted as an entry point? If 9463 // so just signal we are done with this target region. 9464 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9465 ParentName, Line)) 9466 return; 9467 9468 switch (E.getDirectiveKind()) { 9469 case OMPD_target: 9470 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9471 cast<OMPTargetDirective>(E)); 9472 break; 9473 case OMPD_target_parallel: 9474 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9475 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9476 break; 9477 case OMPD_target_teams: 9478 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9479 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9480 break; 9481 case OMPD_target_teams_distribute: 9482 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9483 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9484 break; 9485 case OMPD_target_teams_distribute_simd: 9486 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9487 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9488 break; 9489 case OMPD_target_parallel_for: 9490 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9491 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9492 break; 9493 case OMPD_target_parallel_for_simd: 9494 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9495 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9496 break; 9497 case OMPD_target_simd: 9498 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9499 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9500 break; 9501 case OMPD_target_teams_distribute_parallel_for: 9502 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9503 CGM, ParentName, 9504 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9505 break; 9506 case OMPD_target_teams_distribute_parallel_for_simd: 9507 CodeGenFunction:: 9508 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9509 CGM, ParentName, 9510 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9511 break; 9512 case OMPD_parallel: 9513 case OMPD_for: 9514 case OMPD_parallel_for: 9515 case OMPD_parallel_sections: 9516 case OMPD_for_simd: 9517 case OMPD_parallel_for_simd: 9518 case OMPD_cancel: 9519 case OMPD_cancellation_point: 9520 case OMPD_ordered: 9521 case OMPD_threadprivate: 9522 case OMPD_allocate: 9523 case OMPD_task: 9524 case OMPD_simd: 9525 case OMPD_sections: 9526 case OMPD_section: 9527 case OMPD_single: 9528 case OMPD_master: 9529 case OMPD_critical: 9530 case OMPD_taskyield: 9531 case OMPD_barrier: 9532 case OMPD_taskwait: 9533 case OMPD_taskgroup: 9534 case OMPD_atomic: 9535 case OMPD_flush: 9536 case OMPD_teams: 9537 case OMPD_target_data: 9538 case OMPD_target_exit_data: 9539 case OMPD_target_enter_data: 9540 case OMPD_distribute: 9541 case OMPD_distribute_simd: 9542 case OMPD_distribute_parallel_for: 9543 case OMPD_distribute_parallel_for_simd: 9544 case OMPD_teams_distribute: 9545 case OMPD_teams_distribute_simd: 9546 case OMPD_teams_distribute_parallel_for: 9547 case OMPD_teams_distribute_parallel_for_simd: 9548 case OMPD_target_update: 9549 case OMPD_declare_simd: 9550 case OMPD_declare_variant: 9551 case OMPD_declare_target: 9552 case OMPD_end_declare_target: 9553 case OMPD_declare_reduction: 9554 case OMPD_declare_mapper: 9555 case OMPD_taskloop: 9556 case OMPD_taskloop_simd: 9557 case OMPD_master_taskloop: 9558 case OMPD_master_taskloop_simd: 9559 case OMPD_parallel_master_taskloop: 9560 case OMPD_parallel_master_taskloop_simd: 9561 case OMPD_requires: 9562 case OMPD_unknown: 9563 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9564 } 9565 return; 9566 } 9567 9568 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9569 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9570 return; 9571 9572 scanForTargetRegionsFunctions( 9573 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9574 return; 9575 } 9576 9577 // If this is a lambda function, look into its body. 9578 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9579 S = L->getBody(); 9580 9581 // Keep looking for target regions recursively. 9582 for (const Stmt *II : S->children()) 9583 scanForTargetRegionsFunctions(II, ParentName); 9584 } 9585 9586 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9587 // If emitting code for the host, we do not process FD here. Instead we do 9588 // the normal code generation. 9589 if (!CGM.getLangOpts().OpenMPIsDevice) { 9590 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9591 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9592 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9593 // Do not emit device_type(nohost) functions for the host. 9594 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9595 return true; 9596 } 9597 return false; 9598 } 9599 9600 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9601 StringRef Name = CGM.getMangledName(GD); 9602 // Try to detect target regions in the function. 9603 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9604 scanForTargetRegionsFunctions(FD->getBody(), Name); 9605 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9606 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9607 // Do not emit device_type(nohost) functions for the host. 9608 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9609 return true; 9610 } 9611 9612 // Do not to emit function if it is not marked as declare target. 9613 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9614 AlreadyEmittedTargetFunctions.count(Name) == 0; 9615 } 9616 9617 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9618 if (!CGM.getLangOpts().OpenMPIsDevice) 9619 return false; 9620 9621 // Check if there are Ctors/Dtors in this declaration and look for target 9622 // regions in it. We use the complete variant to produce the kernel name 9623 // mangling. 9624 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9625 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9626 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9627 StringRef ParentName = 9628 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9629 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9630 } 9631 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9632 StringRef ParentName = 9633 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9634 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9635 } 9636 } 9637 9638 // Do not to emit variable if it is not marked as declare target. 9639 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9640 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9641 cast<VarDecl>(GD.getDecl())); 9642 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9643 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9644 HasRequiresUnifiedSharedMemory)) { 9645 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9646 return true; 9647 } 9648 return false; 9649 } 9650 9651 llvm::Constant * 9652 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9653 const VarDecl *VD) { 9654 assert(VD->getType().isConstant(CGM.getContext()) && 9655 "Expected constant variable."); 9656 StringRef VarName; 9657 llvm::Constant *Addr; 9658 llvm::GlobalValue::LinkageTypes Linkage; 9659 QualType Ty = VD->getType(); 9660 SmallString<128> Buffer; 9661 { 9662 unsigned DeviceID; 9663 unsigned FileID; 9664 unsigned Line; 9665 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9666 FileID, Line); 9667 llvm::raw_svector_ostream OS(Buffer); 9668 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9669 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9670 VarName = OS.str(); 9671 } 9672 Linkage = llvm::GlobalValue::InternalLinkage; 9673 Addr = 9674 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9675 getDefaultFirstprivateAddressSpace()); 9676 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9677 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9678 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9679 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9680 VarName, Addr, VarSize, 9681 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9682 return Addr; 9683 } 9684 9685 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9686 llvm::Constant *Addr) { 9687 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9688 !CGM.getLangOpts().OpenMPIsDevice) 9689 return; 9690 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9691 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9692 if (!Res) { 9693 if (CGM.getLangOpts().OpenMPIsDevice) { 9694 // Register non-target variables being emitted in device code (debug info 9695 // may cause this). 9696 StringRef VarName = CGM.getMangledName(VD); 9697 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9698 } 9699 return; 9700 } 9701 // Register declare target variables. 9702 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9703 StringRef VarName; 9704 CharUnits VarSize; 9705 llvm::GlobalValue::LinkageTypes Linkage; 9706 9707 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9708 !HasRequiresUnifiedSharedMemory) { 9709 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9710 VarName = CGM.getMangledName(VD); 9711 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9712 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9713 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9714 } else { 9715 VarSize = CharUnits::Zero(); 9716 } 9717 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9718 // Temp solution to prevent optimizations of the internal variables. 9719 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9720 std::string RefName = getName({VarName, "ref"}); 9721 if (!CGM.GetGlobalValue(RefName)) { 9722 llvm::Constant *AddrRef = 9723 getOrCreateInternalVariable(Addr->getType(), RefName); 9724 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9725 GVAddrRef->setConstant(/*Val=*/true); 9726 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9727 GVAddrRef->setInitializer(Addr); 9728 CGM.addCompilerUsedGlobal(GVAddrRef); 9729 } 9730 } 9731 } else { 9732 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9733 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9734 HasRequiresUnifiedSharedMemory)) && 9735 "Declare target attribute must link or to with unified memory."); 9736 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9737 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9738 else 9739 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9740 9741 if (CGM.getLangOpts().OpenMPIsDevice) { 9742 VarName = Addr->getName(); 9743 Addr = nullptr; 9744 } else { 9745 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9746 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9747 } 9748 VarSize = CGM.getPointerSize(); 9749 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9750 } 9751 9752 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9753 VarName, Addr, VarSize, Flags, Linkage); 9754 } 9755 9756 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9757 if (isa<FunctionDecl>(GD.getDecl()) || 9758 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9759 return emitTargetFunctions(GD); 9760 9761 return emitTargetGlobalVariable(GD); 9762 } 9763 9764 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9765 for (const VarDecl *VD : DeferredGlobalVariables) { 9766 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9767 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9768 if (!Res) 9769 continue; 9770 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9771 !HasRequiresUnifiedSharedMemory) { 9772 CGM.EmitGlobal(VD); 9773 } else { 9774 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9775 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9776 HasRequiresUnifiedSharedMemory)) && 9777 "Expected link clause or to clause with unified memory."); 9778 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9779 } 9780 } 9781 } 9782 9783 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9784 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9785 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9786 " Expected target-based directive."); 9787 } 9788 9789 void CGOpenMPRuntime::checkArchForUnifiedAddressing( 9790 const OMPRequiresDecl *D) { 9791 for (const OMPClause *Clause : D->clauselists()) { 9792 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9793 HasRequiresUnifiedSharedMemory = true; 9794 break; 9795 } 9796 } 9797 } 9798 9799 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9800 LangAS &AS) { 9801 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9802 return false; 9803 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9804 switch(A->getAllocatorType()) { 9805 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9806 // Not supported, fallback to the default mem space. 9807 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9808 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9809 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9810 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9811 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9812 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9813 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9814 AS = LangAS::Default; 9815 return true; 9816 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9817 llvm_unreachable("Expected predefined allocator for the variables with the " 9818 "static storage."); 9819 } 9820 return false; 9821 } 9822 9823 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9824 return HasRequiresUnifiedSharedMemory; 9825 } 9826 9827 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9828 CodeGenModule &CGM) 9829 : CGM(CGM) { 9830 if (CGM.getLangOpts().OpenMPIsDevice) { 9831 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9832 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9833 } 9834 } 9835 9836 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9837 if (CGM.getLangOpts().OpenMPIsDevice) 9838 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9839 } 9840 9841 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9842 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9843 return true; 9844 9845 StringRef Name = CGM.getMangledName(GD); 9846 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9847 // Do not to emit function if it is marked as declare target as it was already 9848 // emitted. 9849 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9850 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) { 9851 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name))) 9852 return !F->isDeclaration(); 9853 return false; 9854 } 9855 return true; 9856 } 9857 9858 return !AlreadyEmittedTargetFunctions.insert(Name).second; 9859 } 9860 9861 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9862 // If we don't have entries or if we are emitting code for the device, we 9863 // don't need to do anything. 9864 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9865 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9866 (OffloadEntriesInfoManager.empty() && 9867 !HasEmittedDeclareTargetRegion && 9868 !HasEmittedTargetRegion)) 9869 return nullptr; 9870 9871 // Create and register the function that handles the requires directives. 9872 ASTContext &C = CGM.getContext(); 9873 9874 llvm::Function *RequiresRegFn; 9875 { 9876 CodeGenFunction CGF(CGM); 9877 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9878 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9879 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9880 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9881 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9882 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9883 // TODO: check for other requires clauses. 9884 // The requires directive takes effect only when a target region is 9885 // present in the compilation unit. Otherwise it is ignored and not 9886 // passed to the runtime. This avoids the runtime from throwing an error 9887 // for mismatching requires clauses across compilation units that don't 9888 // contain at least 1 target region. 9889 assert((HasEmittedTargetRegion || 9890 HasEmittedDeclareTargetRegion || 9891 !OffloadEntriesInfoManager.empty()) && 9892 "Target or declare target region expected."); 9893 if (HasRequiresUnifiedSharedMemory) 9894 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9895 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 9896 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9897 CGF.FinishFunction(); 9898 } 9899 return RequiresRegFn; 9900 } 9901 9902 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9903 const OMPExecutableDirective &D, 9904 SourceLocation Loc, 9905 llvm::Function *OutlinedFn, 9906 ArrayRef<llvm::Value *> CapturedVars) { 9907 if (!CGF.HaveInsertPoint()) 9908 return; 9909 9910 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9911 CodeGenFunction::RunCleanupsScope Scope(CGF); 9912 9913 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9914 llvm::Value *Args[] = { 9915 RTLoc, 9916 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9917 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9918 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9919 RealArgs.append(std::begin(Args), std::end(Args)); 9920 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9921 9922 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 9923 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9924 } 9925 9926 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9927 const Expr *NumTeams, 9928 const Expr *ThreadLimit, 9929 SourceLocation Loc) { 9930 if (!CGF.HaveInsertPoint()) 9931 return; 9932 9933 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9934 9935 llvm::Value *NumTeamsVal = 9936 NumTeams 9937 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9938 CGF.CGM.Int32Ty, /* isSigned = */ true) 9939 : CGF.Builder.getInt32(0); 9940 9941 llvm::Value *ThreadLimitVal = 9942 ThreadLimit 9943 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 9944 CGF.CGM.Int32Ty, /* isSigned = */ true) 9945 : CGF.Builder.getInt32(0); 9946 9947 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 9948 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 9949 ThreadLimitVal}; 9950 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 9951 PushNumTeamsArgs); 9952 } 9953 9954 void CGOpenMPRuntime::emitTargetDataCalls( 9955 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 9956 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 9957 if (!CGF.HaveInsertPoint()) 9958 return; 9959 9960 // Action used to replace the default codegen action and turn privatization 9961 // off. 9962 PrePostActionTy NoPrivAction; 9963 9964 // Generate the code for the opening of the data environment. Capture all the 9965 // arguments of the runtime call by reference because they are used in the 9966 // closing of the region. 9967 auto &&BeginThenGen = [this, &D, Device, &Info, 9968 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 9969 // Fill up the arrays with all the mapped variables. 9970 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9971 MappableExprsHandler::MapValuesArrayTy Pointers; 9972 MappableExprsHandler::MapValuesArrayTy Sizes; 9973 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9974 9975 // Get map clause information. 9976 MappableExprsHandler MCHandler(D, CGF); 9977 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 9978 9979 // Fill up the arrays and create the arguments. 9980 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9981 9982 llvm::Value *BasePointersArrayArg = nullptr; 9983 llvm::Value *PointersArrayArg = nullptr; 9984 llvm::Value *SizesArrayArg = nullptr; 9985 llvm::Value *MapTypesArrayArg = nullptr; 9986 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 9987 SizesArrayArg, MapTypesArrayArg, Info); 9988 9989 // Emit device ID if any. 9990 llvm::Value *DeviceID = nullptr; 9991 if (Device) { 9992 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9993 CGF.Int64Ty, /*isSigned=*/true); 9994 } else { 9995 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9996 } 9997 9998 // Emit the number of elements in the offloading arrays. 9999 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10000 10001 llvm::Value *OffloadingArgs[] = { 10002 DeviceID, PointerNum, BasePointersArrayArg, 10003 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10004 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 10005 OffloadingArgs); 10006 10007 // If device pointer privatization is required, emit the body of the region 10008 // here. It will have to be duplicated: with and without privatization. 10009 if (!Info.CaptureDeviceAddrMap.empty()) 10010 CodeGen(CGF); 10011 }; 10012 10013 // Generate code for the closing of the data region. 10014 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10015 PrePostActionTy &) { 10016 assert(Info.isValid() && "Invalid data environment closing arguments."); 10017 10018 llvm::Value *BasePointersArrayArg = nullptr; 10019 llvm::Value *PointersArrayArg = nullptr; 10020 llvm::Value *SizesArrayArg = nullptr; 10021 llvm::Value *MapTypesArrayArg = nullptr; 10022 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10023 SizesArrayArg, MapTypesArrayArg, Info); 10024 10025 // Emit device ID if any. 10026 llvm::Value *DeviceID = nullptr; 10027 if (Device) { 10028 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10029 CGF.Int64Ty, /*isSigned=*/true); 10030 } else { 10031 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10032 } 10033 10034 // Emit the number of elements in the offloading arrays. 10035 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10036 10037 llvm::Value *OffloadingArgs[] = { 10038 DeviceID, PointerNum, BasePointersArrayArg, 10039 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10040 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10041 OffloadingArgs); 10042 }; 10043 10044 // If we need device pointer privatization, we need to emit the body of the 10045 // region with no privatization in the 'else' branch of the conditional. 10046 // Otherwise, we don't have to do anything. 10047 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10048 PrePostActionTy &) { 10049 if (!Info.CaptureDeviceAddrMap.empty()) { 10050 CodeGen.setAction(NoPrivAction); 10051 CodeGen(CGF); 10052 } 10053 }; 10054 10055 // We don't have to do anything to close the region if the if clause evaluates 10056 // to false. 10057 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10058 10059 if (IfCond) { 10060 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10061 } else { 10062 RegionCodeGenTy RCG(BeginThenGen); 10063 RCG(CGF); 10064 } 10065 10066 // If we don't require privatization of device pointers, we emit the body in 10067 // between the runtime calls. This avoids duplicating the body code. 10068 if (Info.CaptureDeviceAddrMap.empty()) { 10069 CodeGen.setAction(NoPrivAction); 10070 CodeGen(CGF); 10071 } 10072 10073 if (IfCond) { 10074 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10075 } else { 10076 RegionCodeGenTy RCG(EndThenGen); 10077 RCG(CGF); 10078 } 10079 } 10080 10081 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10082 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10083 const Expr *Device) { 10084 if (!CGF.HaveInsertPoint()) 10085 return; 10086 10087 assert((isa<OMPTargetEnterDataDirective>(D) || 10088 isa<OMPTargetExitDataDirective>(D) || 10089 isa<OMPTargetUpdateDirective>(D)) && 10090 "Expecting either target enter, exit data, or update directives."); 10091 10092 CodeGenFunction::OMPTargetDataInfo InputInfo; 10093 llvm::Value *MapTypesArray = nullptr; 10094 // Generate the code for the opening of the data environment. 10095 auto &&ThenGen = [this, &D, Device, &InputInfo, 10096 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10097 // Emit device ID if any. 10098 llvm::Value *DeviceID = nullptr; 10099 if (Device) { 10100 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10101 CGF.Int64Ty, /*isSigned=*/true); 10102 } else { 10103 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10104 } 10105 10106 // Emit the number of elements in the offloading arrays. 10107 llvm::Constant *PointerNum = 10108 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10109 10110 llvm::Value *OffloadingArgs[] = {DeviceID, 10111 PointerNum, 10112 InputInfo.BasePointersArray.getPointer(), 10113 InputInfo.PointersArray.getPointer(), 10114 InputInfo.SizesArray.getPointer(), 10115 MapTypesArray}; 10116 10117 // Select the right runtime function call for each expected standalone 10118 // directive. 10119 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10120 OpenMPRTLFunction RTLFn; 10121 switch (D.getDirectiveKind()) { 10122 case OMPD_target_enter_data: 10123 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10124 : OMPRTL__tgt_target_data_begin; 10125 break; 10126 case OMPD_target_exit_data: 10127 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10128 : OMPRTL__tgt_target_data_end; 10129 break; 10130 case OMPD_target_update: 10131 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10132 : OMPRTL__tgt_target_data_update; 10133 break; 10134 case OMPD_parallel: 10135 case OMPD_for: 10136 case OMPD_parallel_for: 10137 case OMPD_parallel_sections: 10138 case OMPD_for_simd: 10139 case OMPD_parallel_for_simd: 10140 case OMPD_cancel: 10141 case OMPD_cancellation_point: 10142 case OMPD_ordered: 10143 case OMPD_threadprivate: 10144 case OMPD_allocate: 10145 case OMPD_task: 10146 case OMPD_simd: 10147 case OMPD_sections: 10148 case OMPD_section: 10149 case OMPD_single: 10150 case OMPD_master: 10151 case OMPD_critical: 10152 case OMPD_taskyield: 10153 case OMPD_barrier: 10154 case OMPD_taskwait: 10155 case OMPD_taskgroup: 10156 case OMPD_atomic: 10157 case OMPD_flush: 10158 case OMPD_teams: 10159 case OMPD_target_data: 10160 case OMPD_distribute: 10161 case OMPD_distribute_simd: 10162 case OMPD_distribute_parallel_for: 10163 case OMPD_distribute_parallel_for_simd: 10164 case OMPD_teams_distribute: 10165 case OMPD_teams_distribute_simd: 10166 case OMPD_teams_distribute_parallel_for: 10167 case OMPD_teams_distribute_parallel_for_simd: 10168 case OMPD_declare_simd: 10169 case OMPD_declare_variant: 10170 case OMPD_declare_target: 10171 case OMPD_end_declare_target: 10172 case OMPD_declare_reduction: 10173 case OMPD_declare_mapper: 10174 case OMPD_taskloop: 10175 case OMPD_taskloop_simd: 10176 case OMPD_master_taskloop: 10177 case OMPD_master_taskloop_simd: 10178 case OMPD_parallel_master_taskloop: 10179 case OMPD_parallel_master_taskloop_simd: 10180 case OMPD_target: 10181 case OMPD_target_simd: 10182 case OMPD_target_teams_distribute: 10183 case OMPD_target_teams_distribute_simd: 10184 case OMPD_target_teams_distribute_parallel_for: 10185 case OMPD_target_teams_distribute_parallel_for_simd: 10186 case OMPD_target_teams: 10187 case OMPD_target_parallel: 10188 case OMPD_target_parallel_for: 10189 case OMPD_target_parallel_for_simd: 10190 case OMPD_requires: 10191 case OMPD_unknown: 10192 llvm_unreachable("Unexpected standalone target data directive."); 10193 break; 10194 } 10195 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10196 }; 10197 10198 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10199 CodeGenFunction &CGF, PrePostActionTy &) { 10200 // Fill up the arrays with all the mapped variables. 10201 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10202 MappableExprsHandler::MapValuesArrayTy Pointers; 10203 MappableExprsHandler::MapValuesArrayTy Sizes; 10204 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10205 10206 // Get map clause information. 10207 MappableExprsHandler MEHandler(D, CGF); 10208 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10209 10210 TargetDataInfo Info; 10211 // Fill up the arrays and create the arguments. 10212 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10213 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10214 Info.PointersArray, Info.SizesArray, 10215 Info.MapTypesArray, Info); 10216 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10217 InputInfo.BasePointersArray = 10218 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10219 InputInfo.PointersArray = 10220 Address(Info.PointersArray, CGM.getPointerAlign()); 10221 InputInfo.SizesArray = 10222 Address(Info.SizesArray, CGM.getPointerAlign()); 10223 MapTypesArray = Info.MapTypesArray; 10224 if (D.hasClausesOfKind<OMPDependClause>()) 10225 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10226 else 10227 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10228 }; 10229 10230 if (IfCond) { 10231 emitIfClause(CGF, IfCond, TargetThenGen, 10232 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10233 } else { 10234 RegionCodeGenTy ThenRCG(TargetThenGen); 10235 ThenRCG(CGF); 10236 } 10237 } 10238 10239 namespace { 10240 /// Kind of parameter in a function with 'declare simd' directive. 10241 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10242 /// Attribute set of the parameter. 10243 struct ParamAttrTy { 10244 ParamKindTy Kind = Vector; 10245 llvm::APSInt StrideOrArg; 10246 llvm::APSInt Alignment; 10247 }; 10248 } // namespace 10249 10250 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10251 ArrayRef<ParamAttrTy> ParamAttrs) { 10252 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10253 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10254 // of that clause. The VLEN value must be power of 2. 10255 // In other case the notion of the function`s "characteristic data type" (CDT) 10256 // is used to compute the vector length. 10257 // CDT is defined in the following order: 10258 // a) For non-void function, the CDT is the return type. 10259 // b) If the function has any non-uniform, non-linear parameters, then the 10260 // CDT is the type of the first such parameter. 10261 // c) If the CDT determined by a) or b) above is struct, union, or class 10262 // type which is pass-by-value (except for the type that maps to the 10263 // built-in complex data type), the characteristic data type is int. 10264 // d) If none of the above three cases is applicable, the CDT is int. 10265 // The VLEN is then determined based on the CDT and the size of vector 10266 // register of that ISA for which current vector version is generated. The 10267 // VLEN is computed using the formula below: 10268 // VLEN = sizeof(vector_register) / sizeof(CDT), 10269 // where vector register size specified in section 3.2.1 Registers and the 10270 // Stack Frame of original AMD64 ABI document. 10271 QualType RetType = FD->getReturnType(); 10272 if (RetType.isNull()) 10273 return 0; 10274 ASTContext &C = FD->getASTContext(); 10275 QualType CDT; 10276 if (!RetType.isNull() && !RetType->isVoidType()) { 10277 CDT = RetType; 10278 } else { 10279 unsigned Offset = 0; 10280 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10281 if (ParamAttrs[Offset].Kind == Vector) 10282 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10283 ++Offset; 10284 } 10285 if (CDT.isNull()) { 10286 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10287 if (ParamAttrs[I + Offset].Kind == Vector) { 10288 CDT = FD->getParamDecl(I)->getType(); 10289 break; 10290 } 10291 } 10292 } 10293 } 10294 if (CDT.isNull()) 10295 CDT = C.IntTy; 10296 CDT = CDT->getCanonicalTypeUnqualified(); 10297 if (CDT->isRecordType() || CDT->isUnionType()) 10298 CDT = C.IntTy; 10299 return C.getTypeSize(CDT); 10300 } 10301 10302 static void 10303 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10304 const llvm::APSInt &VLENVal, 10305 ArrayRef<ParamAttrTy> ParamAttrs, 10306 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10307 struct ISADataTy { 10308 char ISA; 10309 unsigned VecRegSize; 10310 }; 10311 ISADataTy ISAData[] = { 10312 { 10313 'b', 128 10314 }, // SSE 10315 { 10316 'c', 256 10317 }, // AVX 10318 { 10319 'd', 256 10320 }, // AVX2 10321 { 10322 'e', 512 10323 }, // AVX512 10324 }; 10325 llvm::SmallVector<char, 2> Masked; 10326 switch (State) { 10327 case OMPDeclareSimdDeclAttr::BS_Undefined: 10328 Masked.push_back('N'); 10329 Masked.push_back('M'); 10330 break; 10331 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10332 Masked.push_back('N'); 10333 break; 10334 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10335 Masked.push_back('M'); 10336 break; 10337 } 10338 for (char Mask : Masked) { 10339 for (const ISADataTy &Data : ISAData) { 10340 SmallString<256> Buffer; 10341 llvm::raw_svector_ostream Out(Buffer); 10342 Out << "_ZGV" << Data.ISA << Mask; 10343 if (!VLENVal) { 10344 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10345 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10346 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10347 } else { 10348 Out << VLENVal; 10349 } 10350 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10351 switch (ParamAttr.Kind){ 10352 case LinearWithVarStride: 10353 Out << 's' << ParamAttr.StrideOrArg; 10354 break; 10355 case Linear: 10356 Out << 'l'; 10357 if (!!ParamAttr.StrideOrArg) 10358 Out << ParamAttr.StrideOrArg; 10359 break; 10360 case Uniform: 10361 Out << 'u'; 10362 break; 10363 case Vector: 10364 Out << 'v'; 10365 break; 10366 } 10367 if (!!ParamAttr.Alignment) 10368 Out << 'a' << ParamAttr.Alignment; 10369 } 10370 Out << '_' << Fn->getName(); 10371 Fn->addFnAttr(Out.str()); 10372 } 10373 } 10374 } 10375 10376 // This are the Functions that are needed to mangle the name of the 10377 // vector functions generated by the compiler, according to the rules 10378 // defined in the "Vector Function ABI specifications for AArch64", 10379 // available at 10380 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10381 10382 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10383 /// 10384 /// TODO: Need to implement the behavior for reference marked with a 10385 /// var or no linear modifiers (1.b in the section). For this, we 10386 /// need to extend ParamKindTy to support the linear modifiers. 10387 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10388 QT = QT.getCanonicalType(); 10389 10390 if (QT->isVoidType()) 10391 return false; 10392 10393 if (Kind == ParamKindTy::Uniform) 10394 return false; 10395 10396 if (Kind == ParamKindTy::Linear) 10397 return false; 10398 10399 // TODO: Handle linear references with modifiers 10400 10401 if (Kind == ParamKindTy::LinearWithVarStride) 10402 return false; 10403 10404 return true; 10405 } 10406 10407 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10408 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10409 QT = QT.getCanonicalType(); 10410 unsigned Size = C.getTypeSize(QT); 10411 10412 // Only scalars and complex within 16 bytes wide set PVB to true. 10413 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10414 return false; 10415 10416 if (QT->isFloatingType()) 10417 return true; 10418 10419 if (QT->isIntegerType()) 10420 return true; 10421 10422 if (QT->isPointerType()) 10423 return true; 10424 10425 // TODO: Add support for complex types (section 3.1.2, item 2). 10426 10427 return false; 10428 } 10429 10430 /// Computes the lane size (LS) of a return type or of an input parameter, 10431 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10432 /// TODO: Add support for references, section 3.2.1, item 1. 10433 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10434 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10435 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10436 if (getAArch64PBV(PTy, C)) 10437 return C.getTypeSize(PTy); 10438 } 10439 if (getAArch64PBV(QT, C)) 10440 return C.getTypeSize(QT); 10441 10442 return C.getTypeSize(C.getUIntPtrType()); 10443 } 10444 10445 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10446 // signature of the scalar function, as defined in 3.2.2 of the 10447 // AAVFABI. 10448 static std::tuple<unsigned, unsigned, bool> 10449 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10450 QualType RetType = FD->getReturnType().getCanonicalType(); 10451 10452 ASTContext &C = FD->getASTContext(); 10453 10454 bool OutputBecomesInput = false; 10455 10456 llvm::SmallVector<unsigned, 8> Sizes; 10457 if (!RetType->isVoidType()) { 10458 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10459 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10460 OutputBecomesInput = true; 10461 } 10462 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10463 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10464 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10465 } 10466 10467 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10468 // The LS of a function parameter / return value can only be a power 10469 // of 2, starting from 8 bits, up to 128. 10470 assert(std::all_of(Sizes.begin(), Sizes.end(), 10471 [](unsigned Size) { 10472 return Size == 8 || Size == 16 || Size == 32 || 10473 Size == 64 || Size == 128; 10474 }) && 10475 "Invalid size"); 10476 10477 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10478 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10479 OutputBecomesInput); 10480 } 10481 10482 /// Mangle the parameter part of the vector function name according to 10483 /// their OpenMP classification. The mangling function is defined in 10484 /// section 3.5 of the AAVFABI. 10485 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10486 SmallString<256> Buffer; 10487 llvm::raw_svector_ostream Out(Buffer); 10488 for (const auto &ParamAttr : ParamAttrs) { 10489 switch (ParamAttr.Kind) { 10490 case LinearWithVarStride: 10491 Out << "ls" << ParamAttr.StrideOrArg; 10492 break; 10493 case Linear: 10494 Out << 'l'; 10495 // Don't print the step value if it is not present or if it is 10496 // equal to 1. 10497 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10498 Out << ParamAttr.StrideOrArg; 10499 break; 10500 case Uniform: 10501 Out << 'u'; 10502 break; 10503 case Vector: 10504 Out << 'v'; 10505 break; 10506 } 10507 10508 if (!!ParamAttr.Alignment) 10509 Out << 'a' << ParamAttr.Alignment; 10510 } 10511 10512 return Out.str(); 10513 } 10514 10515 // Function used to add the attribute. The parameter `VLEN` is 10516 // templated to allow the use of "x" when targeting scalable functions 10517 // for SVE. 10518 template <typename T> 10519 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10520 char ISA, StringRef ParSeq, 10521 StringRef MangledName, bool OutputBecomesInput, 10522 llvm::Function *Fn) { 10523 SmallString<256> Buffer; 10524 llvm::raw_svector_ostream Out(Buffer); 10525 Out << Prefix << ISA << LMask << VLEN; 10526 if (OutputBecomesInput) 10527 Out << "v"; 10528 Out << ParSeq << "_" << MangledName; 10529 Fn->addFnAttr(Out.str()); 10530 } 10531 10532 // Helper function to generate the Advanced SIMD names depending on 10533 // the value of the NDS when simdlen is not present. 10534 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10535 StringRef Prefix, char ISA, 10536 StringRef ParSeq, StringRef MangledName, 10537 bool OutputBecomesInput, 10538 llvm::Function *Fn) { 10539 switch (NDS) { 10540 case 8: 10541 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10542 OutputBecomesInput, Fn); 10543 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10544 OutputBecomesInput, Fn); 10545 break; 10546 case 16: 10547 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10548 OutputBecomesInput, Fn); 10549 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10550 OutputBecomesInput, Fn); 10551 break; 10552 case 32: 10553 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10554 OutputBecomesInput, Fn); 10555 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10556 OutputBecomesInput, Fn); 10557 break; 10558 case 64: 10559 case 128: 10560 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10561 OutputBecomesInput, Fn); 10562 break; 10563 default: 10564 llvm_unreachable("Scalar type is too wide."); 10565 } 10566 } 10567 10568 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10569 static void emitAArch64DeclareSimdFunction( 10570 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10571 ArrayRef<ParamAttrTy> ParamAttrs, 10572 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10573 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10574 10575 // Get basic data for building the vector signature. 10576 const auto Data = getNDSWDS(FD, ParamAttrs); 10577 const unsigned NDS = std::get<0>(Data); 10578 const unsigned WDS = std::get<1>(Data); 10579 const bool OutputBecomesInput = std::get<2>(Data); 10580 10581 // Check the values provided via `simdlen` by the user. 10582 // 1. A `simdlen(1)` doesn't produce vector signatures, 10583 if (UserVLEN == 1) { 10584 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10585 DiagnosticsEngine::Warning, 10586 "The clause simdlen(1) has no effect when targeting aarch64."); 10587 CGM.getDiags().Report(SLoc, DiagID); 10588 return; 10589 } 10590 10591 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10592 // Advanced SIMD output. 10593 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10594 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10595 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10596 "power of 2 when targeting Advanced SIMD."); 10597 CGM.getDiags().Report(SLoc, DiagID); 10598 return; 10599 } 10600 10601 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10602 // limits. 10603 if (ISA == 's' && UserVLEN != 0) { 10604 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10605 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10606 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10607 "lanes in the architectural constraints " 10608 "for SVE (min is 128-bit, max is " 10609 "2048-bit, by steps of 128-bit)"); 10610 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10611 return; 10612 } 10613 } 10614 10615 // Sort out parameter sequence. 10616 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10617 StringRef Prefix = "_ZGV"; 10618 // Generate simdlen from user input (if any). 10619 if (UserVLEN) { 10620 if (ISA == 's') { 10621 // SVE generates only a masked function. 10622 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10623 OutputBecomesInput, Fn); 10624 } else { 10625 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10626 // Advanced SIMD generates one or two functions, depending on 10627 // the `[not]inbranch` clause. 10628 switch (State) { 10629 case OMPDeclareSimdDeclAttr::BS_Undefined: 10630 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10631 OutputBecomesInput, Fn); 10632 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10633 OutputBecomesInput, Fn); 10634 break; 10635 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10636 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10637 OutputBecomesInput, Fn); 10638 break; 10639 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10640 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10641 OutputBecomesInput, Fn); 10642 break; 10643 } 10644 } 10645 } else { 10646 // If no user simdlen is provided, follow the AAVFABI rules for 10647 // generating the vector length. 10648 if (ISA == 's') { 10649 // SVE, section 3.4.1, item 1. 10650 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10651 OutputBecomesInput, Fn); 10652 } else { 10653 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10654 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10655 // two vector names depending on the use of the clause 10656 // `[not]inbranch`. 10657 switch (State) { 10658 case OMPDeclareSimdDeclAttr::BS_Undefined: 10659 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10660 OutputBecomesInput, Fn); 10661 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10662 OutputBecomesInput, Fn); 10663 break; 10664 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10665 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10666 OutputBecomesInput, Fn); 10667 break; 10668 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10669 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10670 OutputBecomesInput, Fn); 10671 break; 10672 } 10673 } 10674 } 10675 } 10676 10677 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10678 llvm::Function *Fn) { 10679 ASTContext &C = CGM.getContext(); 10680 FD = FD->getMostRecentDecl(); 10681 // Map params to their positions in function decl. 10682 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10683 if (isa<CXXMethodDecl>(FD)) 10684 ParamPositions.try_emplace(FD, 0); 10685 unsigned ParamPos = ParamPositions.size(); 10686 for (const ParmVarDecl *P : FD->parameters()) { 10687 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10688 ++ParamPos; 10689 } 10690 while (FD) { 10691 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10692 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10693 // Mark uniform parameters. 10694 for (const Expr *E : Attr->uniforms()) { 10695 E = E->IgnoreParenImpCasts(); 10696 unsigned Pos; 10697 if (isa<CXXThisExpr>(E)) { 10698 Pos = ParamPositions[FD]; 10699 } else { 10700 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10701 ->getCanonicalDecl(); 10702 Pos = ParamPositions[PVD]; 10703 } 10704 ParamAttrs[Pos].Kind = Uniform; 10705 } 10706 // Get alignment info. 10707 auto NI = Attr->alignments_begin(); 10708 for (const Expr *E : Attr->aligneds()) { 10709 E = E->IgnoreParenImpCasts(); 10710 unsigned Pos; 10711 QualType ParmTy; 10712 if (isa<CXXThisExpr>(E)) { 10713 Pos = ParamPositions[FD]; 10714 ParmTy = E->getType(); 10715 } else { 10716 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10717 ->getCanonicalDecl(); 10718 Pos = ParamPositions[PVD]; 10719 ParmTy = PVD->getType(); 10720 } 10721 ParamAttrs[Pos].Alignment = 10722 (*NI) 10723 ? (*NI)->EvaluateKnownConstInt(C) 10724 : llvm::APSInt::getUnsigned( 10725 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10726 .getQuantity()); 10727 ++NI; 10728 } 10729 // Mark linear parameters. 10730 auto SI = Attr->steps_begin(); 10731 auto MI = Attr->modifiers_begin(); 10732 for (const Expr *E : Attr->linears()) { 10733 E = E->IgnoreParenImpCasts(); 10734 unsigned Pos; 10735 if (isa<CXXThisExpr>(E)) { 10736 Pos = ParamPositions[FD]; 10737 } else { 10738 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10739 ->getCanonicalDecl(); 10740 Pos = ParamPositions[PVD]; 10741 } 10742 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10743 ParamAttr.Kind = Linear; 10744 if (*SI) { 10745 Expr::EvalResult Result; 10746 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10747 if (const auto *DRE = 10748 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10749 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10750 ParamAttr.Kind = LinearWithVarStride; 10751 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10752 ParamPositions[StridePVD->getCanonicalDecl()]); 10753 } 10754 } 10755 } else { 10756 ParamAttr.StrideOrArg = Result.Val.getInt(); 10757 } 10758 } 10759 ++SI; 10760 ++MI; 10761 } 10762 llvm::APSInt VLENVal; 10763 SourceLocation ExprLoc; 10764 const Expr *VLENExpr = Attr->getSimdlen(); 10765 if (VLENExpr) { 10766 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10767 ExprLoc = VLENExpr->getExprLoc(); 10768 } 10769 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10770 if (CGM.getTriple().getArch() == llvm::Triple::x86 || 10771 CGM.getTriple().getArch() == llvm::Triple::x86_64) { 10772 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10773 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10774 unsigned VLEN = VLENVal.getExtValue(); 10775 StringRef MangledName = Fn->getName(); 10776 if (CGM.getTarget().hasFeature("sve")) 10777 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10778 MangledName, 's', 128, Fn, ExprLoc); 10779 if (CGM.getTarget().hasFeature("neon")) 10780 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10781 MangledName, 'n', 128, Fn, ExprLoc); 10782 } 10783 } 10784 FD = FD->getPreviousDecl(); 10785 } 10786 } 10787 10788 namespace { 10789 /// Cleanup action for doacross support. 10790 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10791 public: 10792 static const int DoacrossFinArgs = 2; 10793 10794 private: 10795 llvm::FunctionCallee RTLFn; 10796 llvm::Value *Args[DoacrossFinArgs]; 10797 10798 public: 10799 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10800 ArrayRef<llvm::Value *> CallArgs) 10801 : RTLFn(RTLFn) { 10802 assert(CallArgs.size() == DoacrossFinArgs); 10803 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10804 } 10805 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10806 if (!CGF.HaveInsertPoint()) 10807 return; 10808 CGF.EmitRuntimeCall(RTLFn, Args); 10809 } 10810 }; 10811 } // namespace 10812 10813 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10814 const OMPLoopDirective &D, 10815 ArrayRef<Expr *> NumIterations) { 10816 if (!CGF.HaveInsertPoint()) 10817 return; 10818 10819 ASTContext &C = CGM.getContext(); 10820 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10821 RecordDecl *RD; 10822 if (KmpDimTy.isNull()) { 10823 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10824 // kmp_int64 lo; // lower 10825 // kmp_int64 up; // upper 10826 // kmp_int64 st; // stride 10827 // }; 10828 RD = C.buildImplicitRecord("kmp_dim"); 10829 RD->startDefinition(); 10830 addFieldToRecordDecl(C, RD, Int64Ty); 10831 addFieldToRecordDecl(C, RD, Int64Ty); 10832 addFieldToRecordDecl(C, RD, Int64Ty); 10833 RD->completeDefinition(); 10834 KmpDimTy = C.getRecordType(RD); 10835 } else { 10836 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10837 } 10838 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10839 QualType ArrayTy = 10840 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 10841 10842 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10843 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10844 enum { LowerFD = 0, UpperFD, StrideFD }; 10845 // Fill dims with data. 10846 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10847 LValue DimsLVal = CGF.MakeAddrLValue( 10848 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10849 // dims.upper = num_iterations; 10850 LValue UpperLVal = CGF.EmitLValueForField( 10851 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10852 llvm::Value *NumIterVal = 10853 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10854 D.getNumIterations()->getType(), Int64Ty, 10855 D.getNumIterations()->getExprLoc()); 10856 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10857 // dims.stride = 1; 10858 LValue StrideLVal = CGF.EmitLValueForField( 10859 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10860 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10861 StrideLVal); 10862 } 10863 10864 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10865 // kmp_int32 num_dims, struct kmp_dim * dims); 10866 llvm::Value *Args[] = { 10867 emitUpdateLocation(CGF, D.getBeginLoc()), 10868 getThreadID(CGF, D.getBeginLoc()), 10869 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10870 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10871 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10872 CGM.VoidPtrTy)}; 10873 10874 llvm::FunctionCallee RTLFn = 10875 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 10876 CGF.EmitRuntimeCall(RTLFn, Args); 10877 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10878 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10879 llvm::FunctionCallee FiniRTLFn = 10880 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 10881 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10882 llvm::makeArrayRef(FiniArgs)); 10883 } 10884 10885 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10886 const OMPDependClause *C) { 10887 QualType Int64Ty = 10888 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10889 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10890 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10891 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 10892 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10893 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10894 const Expr *CounterVal = C->getLoopData(I); 10895 assert(CounterVal); 10896 llvm::Value *CntVal = CGF.EmitScalarConversion( 10897 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10898 CounterVal->getExprLoc()); 10899 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10900 /*Volatile=*/false, Int64Ty); 10901 } 10902 llvm::Value *Args[] = { 10903 emitUpdateLocation(CGF, C->getBeginLoc()), 10904 getThreadID(CGF, C->getBeginLoc()), 10905 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10906 llvm::FunctionCallee RTLFn; 10907 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10908 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 10909 } else { 10910 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10911 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 10912 } 10913 CGF.EmitRuntimeCall(RTLFn, Args); 10914 } 10915 10916 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10917 llvm::FunctionCallee Callee, 10918 ArrayRef<llvm::Value *> Args) const { 10919 assert(Loc.isValid() && "Outlined function call location must be valid."); 10920 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10921 10922 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10923 if (Fn->doesNotThrow()) { 10924 CGF.EmitNounwindRuntimeCall(Fn, Args); 10925 return; 10926 } 10927 } 10928 CGF.EmitRuntimeCall(Callee, Args); 10929 } 10930 10931 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10932 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10933 ArrayRef<llvm::Value *> Args) const { 10934 emitCall(CGF, Loc, OutlinedFn, Args); 10935 } 10936 10937 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10938 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 10939 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 10940 HasEmittedDeclareTargetRegion = true; 10941 } 10942 10943 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 10944 const VarDecl *NativeParam, 10945 const VarDecl *TargetParam) const { 10946 return CGF.GetAddrOfLocalVar(NativeParam); 10947 } 10948 10949 namespace { 10950 /// Cleanup action for allocate support. 10951 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 10952 public: 10953 static const int CleanupArgs = 3; 10954 10955 private: 10956 llvm::FunctionCallee RTLFn; 10957 llvm::Value *Args[CleanupArgs]; 10958 10959 public: 10960 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 10961 ArrayRef<llvm::Value *> CallArgs) 10962 : RTLFn(RTLFn) { 10963 assert(CallArgs.size() == CleanupArgs && 10964 "Size of arguments does not match."); 10965 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10966 } 10967 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10968 if (!CGF.HaveInsertPoint()) 10969 return; 10970 CGF.EmitRuntimeCall(RTLFn, Args); 10971 } 10972 }; 10973 } // namespace 10974 10975 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 10976 const VarDecl *VD) { 10977 if (!VD) 10978 return Address::invalid(); 10979 const VarDecl *CVD = VD->getCanonicalDecl(); 10980 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 10981 return Address::invalid(); 10982 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 10983 // Use the default allocation. 10984 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 10985 !AA->getAllocator()) 10986 return Address::invalid(); 10987 llvm::Value *Size; 10988 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 10989 if (CVD->getType()->isVariablyModifiedType()) { 10990 Size = CGF.getTypeSize(CVD->getType()); 10991 // Align the size: ((size + align - 1) / align) * align 10992 Size = CGF.Builder.CreateNUWAdd( 10993 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 10994 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 10995 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 10996 } else { 10997 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 10998 Size = CGM.getSize(Sz.alignTo(Align)); 10999 } 11000 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 11001 assert(AA->getAllocator() && 11002 "Expected allocator expression for non-default allocator."); 11003 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 11004 // According to the standard, the original allocator type is a enum (integer). 11005 // Convert to pointer type, if required. 11006 if (Allocator->getType()->isIntegerTy()) 11007 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11008 else if (Allocator->getType()->isPointerTy()) 11009 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11010 CGM.VoidPtrTy); 11011 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11012 11013 llvm::Value *Addr = 11014 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11015 CVD->getName() + ".void.addr"); 11016 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11017 Allocator}; 11018 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11019 11020 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11021 llvm::makeArrayRef(FiniArgs)); 11022 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11023 Addr, 11024 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11025 CVD->getName() + ".addr"); 11026 return Address(Addr, Align); 11027 } 11028 11029 namespace { 11030 using OMPContextSelectorData = 11031 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>; 11032 using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>; 11033 } // anonymous namespace 11034 11035 /// Checks current context and returns true if it matches the context selector. 11036 template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx, 11037 typename... Arguments> 11038 static bool checkContext(const OMPContextSelectorData &Data, 11039 Arguments... Params) { 11040 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown && 11041 "Unknown context selector or context selector set."); 11042 return false; 11043 } 11044 11045 /// Checks for implementation={vendor(<vendor>)} context selector. 11046 /// \returns true iff <vendor>="llvm", false otherwise. 11047 template <> 11048 bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>( 11049 const OMPContextSelectorData &Data) { 11050 return llvm::all_of(Data.Names, 11051 [](StringRef S) { return !S.compare_lower("llvm"); }); 11052 } 11053 11054 /// Checks for device={kind(<kind>)} context selector. 11055 /// \returns true if <kind>="host" and compilation is for host. 11056 /// true if <kind>="nohost" and compilation is for device. 11057 /// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU. 11058 /// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN. 11059 /// false otherwise. 11060 template <> 11061 bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>( 11062 const OMPContextSelectorData &Data, CodeGenModule &CGM) { 11063 for (StringRef Name : Data.Names) { 11064 if (!Name.compare_lower("host")) { 11065 if (CGM.getLangOpts().OpenMPIsDevice) 11066 return false; 11067 continue; 11068 } 11069 if (!Name.compare_lower("nohost")) { 11070 if (!CGM.getLangOpts().OpenMPIsDevice) 11071 return false; 11072 continue; 11073 } 11074 switch (CGM.getTriple().getArch()) { 11075 case llvm::Triple::arm: 11076 case llvm::Triple::armeb: 11077 case llvm::Triple::aarch64: 11078 case llvm::Triple::aarch64_be: 11079 case llvm::Triple::aarch64_32: 11080 case llvm::Triple::ppc: 11081 case llvm::Triple::ppc64: 11082 case llvm::Triple::ppc64le: 11083 case llvm::Triple::x86: 11084 case llvm::Triple::x86_64: 11085 if (Name.compare_lower("cpu")) 11086 return false; 11087 break; 11088 case llvm::Triple::amdgcn: 11089 case llvm::Triple::nvptx: 11090 case llvm::Triple::nvptx64: 11091 if (Name.compare_lower("gpu")) 11092 return false; 11093 break; 11094 case llvm::Triple::UnknownArch: 11095 case llvm::Triple::arc: 11096 case llvm::Triple::avr: 11097 case llvm::Triple::bpfel: 11098 case llvm::Triple::bpfeb: 11099 case llvm::Triple::hexagon: 11100 case llvm::Triple::mips: 11101 case llvm::Triple::mipsel: 11102 case llvm::Triple::mips64: 11103 case llvm::Triple::mips64el: 11104 case llvm::Triple::msp430: 11105 case llvm::Triple::r600: 11106 case llvm::Triple::riscv32: 11107 case llvm::Triple::riscv64: 11108 case llvm::Triple::sparc: 11109 case llvm::Triple::sparcv9: 11110 case llvm::Triple::sparcel: 11111 case llvm::Triple::systemz: 11112 case llvm::Triple::tce: 11113 case llvm::Triple::tcele: 11114 case llvm::Triple::thumb: 11115 case llvm::Triple::thumbeb: 11116 case llvm::Triple::xcore: 11117 case llvm::Triple::le32: 11118 case llvm::Triple::le64: 11119 case llvm::Triple::amdil: 11120 case llvm::Triple::amdil64: 11121 case llvm::Triple::hsail: 11122 case llvm::Triple::hsail64: 11123 case llvm::Triple::spir: 11124 case llvm::Triple::spir64: 11125 case llvm::Triple::kalimba: 11126 case llvm::Triple::shave: 11127 case llvm::Triple::lanai: 11128 case llvm::Triple::wasm32: 11129 case llvm::Triple::wasm64: 11130 case llvm::Triple::renderscript32: 11131 case llvm::Triple::renderscript64: 11132 return false; 11133 } 11134 } 11135 return true; 11136 } 11137 11138 bool matchesContext(CodeGenModule &CGM, 11139 const CompleteOMPContextSelectorData &ContextData) { 11140 for (const OMPContextSelectorData &Data : ContextData) { 11141 switch (Data.Ctx) { 11142 case OMP_CTX_vendor: 11143 assert(Data.CtxSet == OMP_CTX_SET_implementation && 11144 "Expected implementation context selector set."); 11145 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data)) 11146 return false; 11147 break; 11148 case OMP_CTX_kind: 11149 assert(Data.CtxSet == OMP_CTX_SET_device && 11150 "Expected device context selector set."); 11151 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data, 11152 CGM)) 11153 return false; 11154 break; 11155 case OMP_CTX_unknown: 11156 llvm_unreachable("Unknown context selector kind."); 11157 } 11158 } 11159 return true; 11160 } 11161 11162 static CompleteOMPContextSelectorData 11163 translateAttrToContextSelectorData(ASTContext &C, 11164 const OMPDeclareVariantAttr *A) { 11165 CompleteOMPContextSelectorData Data; 11166 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) { 11167 Data.emplace_back(); 11168 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( 11169 *std::next(A->ctxSelectorSets_begin(), I)); 11170 auto Ctx = static_cast<OpenMPContextSelectorKind>( 11171 *std::next(A->ctxSelectors_begin(), I)); 11172 Data.back().CtxSet = CtxSet; 11173 Data.back().Ctx = Ctx; 11174 const Expr *Score = *std::next(A->scores_begin(), I); 11175 Data.back().Score = Score->EvaluateKnownConstInt(C); 11176 switch (Ctx) { 11177 case OMP_CTX_vendor: 11178 assert(CtxSet == OMP_CTX_SET_implementation && 11179 "Expected implementation context selector set."); 11180 Data.back().Names = 11181 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end()); 11182 break; 11183 case OMP_CTX_kind: 11184 assert(CtxSet == OMP_CTX_SET_device && 11185 "Expected device context selector set."); 11186 Data.back().Names = 11187 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end()); 11188 break; 11189 case OMP_CTX_unknown: 11190 llvm_unreachable("Unknown context selector kind."); 11191 } 11192 } 11193 return Data; 11194 } 11195 11196 static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS, 11197 const CompleteOMPContextSelectorData &RHS) { 11198 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData; 11199 for (const OMPContextSelectorData &D : RHS) { 11200 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx)); 11201 Pair.getSecond().insert(D.Names.begin(), D.Names.end()); 11202 } 11203 bool AllSetsAreEqual = true; 11204 for (const OMPContextSelectorData &D : LHS) { 11205 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx)); 11206 if (It == RHSData.end()) 11207 return false; 11208 if (D.Names.size() > It->getSecond().size()) 11209 return false; 11210 if (llvm::set_union(It->getSecond(), D.Names)) 11211 return false; 11212 AllSetsAreEqual = 11213 AllSetsAreEqual && (D.Names.size() == It->getSecond().size()); 11214 } 11215 11216 return LHS.size() != RHS.size() || !AllSetsAreEqual; 11217 } 11218 11219 static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS, 11220 const CompleteOMPContextSelectorData &RHS) { 11221 // Score is calculated as sum of all scores + 1. 11222 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11223 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS); 11224 if (RHSIsSubsetOfLHS) { 11225 LHSScore = llvm::APSInt::get(0); 11226 } else { 11227 for (const OMPContextSelectorData &Data : LHS) { 11228 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) { 11229 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11230 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) { 11231 LHSScore += Data.Score.extend(LHSScore.getBitWidth()); 11232 } else { 11233 LHSScore += Data.Score; 11234 } 11235 } 11236 } 11237 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11238 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) { 11239 RHSScore = llvm::APSInt::get(0); 11240 } else { 11241 for (const OMPContextSelectorData &Data : RHS) { 11242 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) { 11243 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11244 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) { 11245 RHSScore += Data.Score.extend(RHSScore.getBitWidth()); 11246 } else { 11247 RHSScore += Data.Score; 11248 } 11249 } 11250 } 11251 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0; 11252 } 11253 11254 /// Finds the variant function that matches current context with its context 11255 /// selector. 11256 static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, 11257 const FunctionDecl *FD) { 11258 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11259 return FD; 11260 // Iterate through all DeclareVariant attributes and check context selectors. 11261 const OMPDeclareVariantAttr *TopMostAttr = nullptr; 11262 CompleteOMPContextSelectorData TopMostData; 11263 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11264 CompleteOMPContextSelectorData Data = 11265 translateAttrToContextSelectorData(CGM.getContext(), A); 11266 if (!matchesContext(CGM, Data)) 11267 continue; 11268 // If the attribute matches the context, find the attribute with the highest 11269 // score. 11270 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) { 11271 TopMostAttr = A; 11272 TopMostData.swap(Data); 11273 } 11274 } 11275 if (!TopMostAttr) 11276 return FD; 11277 return cast<FunctionDecl>( 11278 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) 11279 ->getDecl()); 11280 } 11281 11282 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11283 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11284 // If the original function is defined already, use its definition. 11285 StringRef MangledName = CGM.getMangledName(GD); 11286 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11287 if (Orig && !Orig->isDeclaration()) 11288 return false; 11289 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D); 11290 // Emit original function if it does not have declare variant attribute or the 11291 // context does not match. 11292 if (NewFD == D) 11293 return false; 11294 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11295 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) { 11296 DeferredVariantFunction.erase(D); 11297 return true; 11298 } 11299 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11300 return true; 11301 } 11302 11303 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11304 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11305 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11306 llvm_unreachable("Not supported in SIMD-only mode"); 11307 } 11308 11309 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11310 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11311 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11312 llvm_unreachable("Not supported in SIMD-only mode"); 11313 } 11314 11315 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11316 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11317 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11318 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11319 bool Tied, unsigned &NumberOfParts) { 11320 llvm_unreachable("Not supported in SIMD-only mode"); 11321 } 11322 11323 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11324 SourceLocation Loc, 11325 llvm::Function *OutlinedFn, 11326 ArrayRef<llvm::Value *> CapturedVars, 11327 const Expr *IfCond) { 11328 llvm_unreachable("Not supported in SIMD-only mode"); 11329 } 11330 11331 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11332 CodeGenFunction &CGF, StringRef CriticalName, 11333 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11334 const Expr *Hint) { 11335 llvm_unreachable("Not supported in SIMD-only mode"); 11336 } 11337 11338 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11339 const RegionCodeGenTy &MasterOpGen, 11340 SourceLocation Loc) { 11341 llvm_unreachable("Not supported in SIMD-only mode"); 11342 } 11343 11344 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11345 SourceLocation Loc) { 11346 llvm_unreachable("Not supported in SIMD-only mode"); 11347 } 11348 11349 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11350 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11351 SourceLocation Loc) { 11352 llvm_unreachable("Not supported in SIMD-only mode"); 11353 } 11354 11355 void CGOpenMPSIMDRuntime::emitSingleRegion( 11356 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11357 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11358 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11359 ArrayRef<const Expr *> AssignmentOps) { 11360 llvm_unreachable("Not supported in SIMD-only mode"); 11361 } 11362 11363 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11364 const RegionCodeGenTy &OrderedOpGen, 11365 SourceLocation Loc, 11366 bool IsThreads) { 11367 llvm_unreachable("Not supported in SIMD-only mode"); 11368 } 11369 11370 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11371 SourceLocation Loc, 11372 OpenMPDirectiveKind Kind, 11373 bool EmitChecks, 11374 bool ForceSimpleCall) { 11375 llvm_unreachable("Not supported in SIMD-only mode"); 11376 } 11377 11378 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11379 CodeGenFunction &CGF, SourceLocation Loc, 11380 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11381 bool Ordered, const DispatchRTInput &DispatchValues) { 11382 llvm_unreachable("Not supported in SIMD-only mode"); 11383 } 11384 11385 void CGOpenMPSIMDRuntime::emitForStaticInit( 11386 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11387 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11388 llvm_unreachable("Not supported in SIMD-only mode"); 11389 } 11390 11391 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11392 CodeGenFunction &CGF, SourceLocation Loc, 11393 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11394 llvm_unreachable("Not supported in SIMD-only mode"); 11395 } 11396 11397 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11398 SourceLocation Loc, 11399 unsigned IVSize, 11400 bool IVSigned) { 11401 llvm_unreachable("Not supported in SIMD-only mode"); 11402 } 11403 11404 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11405 SourceLocation Loc, 11406 OpenMPDirectiveKind DKind) { 11407 llvm_unreachable("Not supported in SIMD-only mode"); 11408 } 11409 11410 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11411 SourceLocation Loc, 11412 unsigned IVSize, bool IVSigned, 11413 Address IL, Address LB, 11414 Address UB, Address ST) { 11415 llvm_unreachable("Not supported in SIMD-only mode"); 11416 } 11417 11418 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11419 llvm::Value *NumThreads, 11420 SourceLocation Loc) { 11421 llvm_unreachable("Not supported in SIMD-only mode"); 11422 } 11423 11424 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11425 OpenMPProcBindClauseKind ProcBind, 11426 SourceLocation Loc) { 11427 llvm_unreachable("Not supported in SIMD-only mode"); 11428 } 11429 11430 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11431 const VarDecl *VD, 11432 Address VDAddr, 11433 SourceLocation Loc) { 11434 llvm_unreachable("Not supported in SIMD-only mode"); 11435 } 11436 11437 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11438 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11439 CodeGenFunction *CGF) { 11440 llvm_unreachable("Not supported in SIMD-only mode"); 11441 } 11442 11443 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11444 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11445 llvm_unreachable("Not supported in SIMD-only mode"); 11446 } 11447 11448 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11449 ArrayRef<const Expr *> Vars, 11450 SourceLocation Loc) { 11451 llvm_unreachable("Not supported in SIMD-only mode"); 11452 } 11453 11454 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11455 const OMPExecutableDirective &D, 11456 llvm::Function *TaskFunction, 11457 QualType SharedsTy, Address Shareds, 11458 const Expr *IfCond, 11459 const OMPTaskDataTy &Data) { 11460 llvm_unreachable("Not supported in SIMD-only mode"); 11461 } 11462 11463 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11464 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11465 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11466 const Expr *IfCond, const OMPTaskDataTy &Data) { 11467 llvm_unreachable("Not supported in SIMD-only mode"); 11468 } 11469 11470 void CGOpenMPSIMDRuntime::emitReduction( 11471 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11472 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11473 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11474 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11475 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 11476 ReductionOps, Options); 11477 } 11478 11479 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 11480 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 11481 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 11482 llvm_unreachable("Not supported in SIMD-only mode"); 11483 } 11484 11485 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 11486 SourceLocation Loc, 11487 ReductionCodeGen &RCG, 11488 unsigned N) { 11489 llvm_unreachable("Not supported in SIMD-only mode"); 11490 } 11491 11492 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 11493 SourceLocation Loc, 11494 llvm::Value *ReductionsPtr, 11495 LValue SharedLVal) { 11496 llvm_unreachable("Not supported in SIMD-only mode"); 11497 } 11498 11499 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 11500 SourceLocation Loc) { 11501 llvm_unreachable("Not supported in SIMD-only mode"); 11502 } 11503 11504 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 11505 CodeGenFunction &CGF, SourceLocation Loc, 11506 OpenMPDirectiveKind CancelRegion) { 11507 llvm_unreachable("Not supported in SIMD-only mode"); 11508 } 11509 11510 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 11511 SourceLocation Loc, const Expr *IfCond, 11512 OpenMPDirectiveKind CancelRegion) { 11513 llvm_unreachable("Not supported in SIMD-only mode"); 11514 } 11515 11516 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 11517 const OMPExecutableDirective &D, StringRef ParentName, 11518 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 11519 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 11520 llvm_unreachable("Not supported in SIMD-only mode"); 11521 } 11522 11523 void CGOpenMPSIMDRuntime::emitTargetCall( 11524 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11525 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 11526 const Expr *Device, 11527 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 11528 const OMPLoopDirective &D)> 11529 SizeEmitter) { 11530 llvm_unreachable("Not supported in SIMD-only mode"); 11531 } 11532 11533 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 11534 llvm_unreachable("Not supported in SIMD-only mode"); 11535 } 11536 11537 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 11538 llvm_unreachable("Not supported in SIMD-only mode"); 11539 } 11540 11541 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 11542 return false; 11543 } 11544 11545 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 11546 const OMPExecutableDirective &D, 11547 SourceLocation Loc, 11548 llvm::Function *OutlinedFn, 11549 ArrayRef<llvm::Value *> CapturedVars) { 11550 llvm_unreachable("Not supported in SIMD-only mode"); 11551 } 11552 11553 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11554 const Expr *NumTeams, 11555 const Expr *ThreadLimit, 11556 SourceLocation Loc) { 11557 llvm_unreachable("Not supported in SIMD-only mode"); 11558 } 11559 11560 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 11561 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11562 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11563 llvm_unreachable("Not supported in SIMD-only mode"); 11564 } 11565 11566 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 11567 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11568 const Expr *Device) { 11569 llvm_unreachable("Not supported in SIMD-only mode"); 11570 } 11571 11572 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11573 const OMPLoopDirective &D, 11574 ArrayRef<Expr *> NumIterations) { 11575 llvm_unreachable("Not supported in SIMD-only mode"); 11576 } 11577 11578 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11579 const OMPDependClause *C) { 11580 llvm_unreachable("Not supported in SIMD-only mode"); 11581 } 11582 11583 const VarDecl * 11584 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 11585 const VarDecl *NativeParam) const { 11586 llvm_unreachable("Not supported in SIMD-only mode"); 11587 } 11588 11589 Address 11590 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 11591 const VarDecl *NativeParam, 11592 const VarDecl *TargetParam) const { 11593 llvm_unreachable("Not supported in SIMD-only mode"); 11594 } 11595