1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides a class for OpenMP runtime code generation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGOpenMPRuntime.h" 14 #include "CGCXXABI.h" 15 #include "CGCleanup.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/AST/Attr.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/OpenMPClause.h" 21 #include "clang/AST/StmtOpenMP.h" 22 #include "clang/AST/StmtVisitor.h" 23 #include "clang/Basic/BitmaskEnum.h" 24 #include "clang/CodeGen/ConstantInitBuilder.h" 25 #include "llvm/ADT/ArrayRef.h" 26 #include "llvm/ADT/SetOperations.h" 27 #include "llvm/ADT/StringExtras.h" 28 #include "llvm/Bitcode/BitcodeReader.h" 29 #include "llvm/Frontend/OpenMP/OMPIRBuilder.h" 30 #include "llvm/IR/DerivedTypes.h" 31 #include "llvm/IR/GlobalValue.h" 32 #include "llvm/IR/Value.h" 33 #include "llvm/Support/Format.h" 34 #include "llvm/Support/raw_ostream.h" 35 #include <cassert> 36 37 using namespace clang; 38 using namespace CodeGen; 39 using namespace llvm::omp; 40 41 namespace { 42 /// Base class for handling code generation inside OpenMP regions. 43 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 44 public: 45 /// Kinds of OpenMP regions used in codegen. 46 enum CGOpenMPRegionKind { 47 /// Region with outlined function for standalone 'parallel' 48 /// directive. 49 ParallelOutlinedRegion, 50 /// Region with outlined function for standalone 'task' directive. 51 TaskOutlinedRegion, 52 /// Region for constructs that do not require function outlining, 53 /// like 'for', 'sections', 'atomic' etc. directives. 54 InlinedRegion, 55 /// Region with outlined function for standalone 'target' directive. 56 TargetRegion, 57 }; 58 59 CGOpenMPRegionInfo(const CapturedStmt &CS, 60 const CGOpenMPRegionKind RegionKind, 61 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 62 bool HasCancel) 63 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 64 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 65 66 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 67 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 68 bool HasCancel) 69 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 70 Kind(Kind), HasCancel(HasCancel) {} 71 72 /// Get a variable or parameter for storing global thread id 73 /// inside OpenMP construct. 74 virtual const VarDecl *getThreadIDVariable() const = 0; 75 76 /// Emit the captured statement body. 77 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 78 79 /// Get an LValue for the current ThreadID variable. 80 /// \return LValue for thread id variable. This LValue always has type int32*. 81 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 82 83 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 84 85 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 86 87 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 88 89 bool hasCancel() const { return HasCancel; } 90 91 static bool classof(const CGCapturedStmtInfo *Info) { 92 return Info->getKind() == CR_OpenMP; 93 } 94 95 ~CGOpenMPRegionInfo() override = default; 96 97 protected: 98 CGOpenMPRegionKind RegionKind; 99 RegionCodeGenTy CodeGen; 100 OpenMPDirectiveKind Kind; 101 bool HasCancel; 102 }; 103 104 /// API for captured statement code generation in OpenMP constructs. 105 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 106 public: 107 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 108 const RegionCodeGenTy &CodeGen, 109 OpenMPDirectiveKind Kind, bool HasCancel, 110 StringRef HelperName) 111 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 112 HasCancel), 113 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 114 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 115 } 116 117 /// Get a variable or parameter for storing global thread id 118 /// inside OpenMP construct. 119 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 120 121 /// Get the name of the capture helper. 122 StringRef getHelperName() const override { return HelperName; } 123 124 static bool classof(const CGCapturedStmtInfo *Info) { 125 return CGOpenMPRegionInfo::classof(Info) && 126 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 127 ParallelOutlinedRegion; 128 } 129 130 private: 131 /// A variable or parameter storing global thread id for OpenMP 132 /// constructs. 133 const VarDecl *ThreadIDVar; 134 StringRef HelperName; 135 }; 136 137 /// API for captured statement code generation in OpenMP constructs. 138 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 139 public: 140 class UntiedTaskActionTy final : public PrePostActionTy { 141 bool Untied; 142 const VarDecl *PartIDVar; 143 const RegionCodeGenTy UntiedCodeGen; 144 llvm::SwitchInst *UntiedSwitch = nullptr; 145 146 public: 147 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 148 const RegionCodeGenTy &UntiedCodeGen) 149 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 150 void Enter(CodeGenFunction &CGF) override { 151 if (Untied) { 152 // Emit task switching point. 153 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 154 CGF.GetAddrOfLocalVar(PartIDVar), 155 PartIDVar->getType()->castAs<PointerType>()); 156 llvm::Value *Res = 157 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 158 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 159 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 160 CGF.EmitBlock(DoneBB); 161 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 162 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 163 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 164 CGF.Builder.GetInsertBlock()); 165 emitUntiedSwitch(CGF); 166 } 167 } 168 void emitUntiedSwitch(CodeGenFunction &CGF) const { 169 if (Untied) { 170 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 171 CGF.GetAddrOfLocalVar(PartIDVar), 172 PartIDVar->getType()->castAs<PointerType>()); 173 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 174 PartIdLVal); 175 UntiedCodeGen(CGF); 176 CodeGenFunction::JumpDest CurPoint = 177 CGF.getJumpDestInCurrentScope(".untied.next."); 178 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 179 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 180 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 181 CGF.Builder.GetInsertBlock()); 182 CGF.EmitBranchThroughCleanup(CurPoint); 183 CGF.EmitBlock(CurPoint.getBlock()); 184 } 185 } 186 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 187 }; 188 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 189 const VarDecl *ThreadIDVar, 190 const RegionCodeGenTy &CodeGen, 191 OpenMPDirectiveKind Kind, bool HasCancel, 192 const UntiedTaskActionTy &Action) 193 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 194 ThreadIDVar(ThreadIDVar), Action(Action) { 195 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 196 } 197 198 /// Get a variable or parameter for storing global thread id 199 /// inside OpenMP construct. 200 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 201 202 /// Get an LValue for the current ThreadID variable. 203 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 204 205 /// Get the name of the capture helper. 206 StringRef getHelperName() const override { return ".omp_outlined."; } 207 208 void emitUntiedSwitch(CodeGenFunction &CGF) override { 209 Action.emitUntiedSwitch(CGF); 210 } 211 212 static bool classof(const CGCapturedStmtInfo *Info) { 213 return CGOpenMPRegionInfo::classof(Info) && 214 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 215 TaskOutlinedRegion; 216 } 217 218 private: 219 /// A variable or parameter storing global thread id for OpenMP 220 /// constructs. 221 const VarDecl *ThreadIDVar; 222 /// Action for emitting code for untied tasks. 223 const UntiedTaskActionTy &Action; 224 }; 225 226 /// API for inlined captured statement code generation in OpenMP 227 /// constructs. 228 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 229 public: 230 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 231 const RegionCodeGenTy &CodeGen, 232 OpenMPDirectiveKind Kind, bool HasCancel) 233 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 234 OldCSI(OldCSI), 235 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 236 237 // Retrieve the value of the context parameter. 238 llvm::Value *getContextValue() const override { 239 if (OuterRegionInfo) 240 return OuterRegionInfo->getContextValue(); 241 llvm_unreachable("No context value for inlined OpenMP region"); 242 } 243 244 void setContextValue(llvm::Value *V) override { 245 if (OuterRegionInfo) { 246 OuterRegionInfo->setContextValue(V); 247 return; 248 } 249 llvm_unreachable("No context value for inlined OpenMP region"); 250 } 251 252 /// Lookup the captured field decl for a variable. 253 const FieldDecl *lookup(const VarDecl *VD) const override { 254 if (OuterRegionInfo) 255 return OuterRegionInfo->lookup(VD); 256 // If there is no outer outlined region,no need to lookup in a list of 257 // captured variables, we can use the original one. 258 return nullptr; 259 } 260 261 FieldDecl *getThisFieldDecl() const override { 262 if (OuterRegionInfo) 263 return OuterRegionInfo->getThisFieldDecl(); 264 return nullptr; 265 } 266 267 /// Get a variable or parameter for storing global thread id 268 /// inside OpenMP construct. 269 const VarDecl *getThreadIDVariable() const override { 270 if (OuterRegionInfo) 271 return OuterRegionInfo->getThreadIDVariable(); 272 return nullptr; 273 } 274 275 /// Get an LValue for the current ThreadID variable. 276 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 277 if (OuterRegionInfo) 278 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 279 llvm_unreachable("No LValue for inlined OpenMP construct"); 280 } 281 282 /// Get the name of the capture helper. 283 StringRef getHelperName() const override { 284 if (auto *OuterRegionInfo = getOldCSI()) 285 return OuterRegionInfo->getHelperName(); 286 llvm_unreachable("No helper name for inlined OpenMP construct"); 287 } 288 289 void emitUntiedSwitch(CodeGenFunction &CGF) override { 290 if (OuterRegionInfo) 291 OuterRegionInfo->emitUntiedSwitch(CGF); 292 } 293 294 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 295 296 static bool classof(const CGCapturedStmtInfo *Info) { 297 return CGOpenMPRegionInfo::classof(Info) && 298 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 299 } 300 301 ~CGOpenMPInlinedRegionInfo() override = default; 302 303 private: 304 /// CodeGen info about outer OpenMP region. 305 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 306 CGOpenMPRegionInfo *OuterRegionInfo; 307 }; 308 309 /// API for captured statement code generation in OpenMP target 310 /// constructs. For this captures, implicit parameters are used instead of the 311 /// captured fields. The name of the target region has to be unique in a given 312 /// application so it is provided by the client, because only the client has 313 /// the information to generate that. 314 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 315 public: 316 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 317 const RegionCodeGenTy &CodeGen, StringRef HelperName) 318 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 319 /*HasCancel=*/false), 320 HelperName(HelperName) {} 321 322 /// This is unused for target regions because each starts executing 323 /// with a single thread. 324 const VarDecl *getThreadIDVariable() const override { return nullptr; } 325 326 /// Get the name of the capture helper. 327 StringRef getHelperName() const override { return HelperName; } 328 329 static bool classof(const CGCapturedStmtInfo *Info) { 330 return CGOpenMPRegionInfo::classof(Info) && 331 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 332 } 333 334 private: 335 StringRef HelperName; 336 }; 337 338 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 339 llvm_unreachable("No codegen for expressions"); 340 } 341 /// API for generation of expressions captured in a innermost OpenMP 342 /// region. 343 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 344 public: 345 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 346 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 347 OMPD_unknown, 348 /*HasCancel=*/false), 349 PrivScope(CGF) { 350 // Make sure the globals captured in the provided statement are local by 351 // using the privatization logic. We assume the same variable is not 352 // captured more than once. 353 for (const auto &C : CS.captures()) { 354 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 355 continue; 356 357 const VarDecl *VD = C.getCapturedVar(); 358 if (VD->isLocalVarDeclOrParm()) 359 continue; 360 361 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 362 /*RefersToEnclosingVariableOrCapture=*/false, 363 VD->getType().getNonReferenceType(), VK_LValue, 364 C.getLocation()); 365 PrivScope.addPrivate( 366 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(CGF); }); 367 } 368 (void)PrivScope.Privatize(); 369 } 370 371 /// Lookup the captured field decl for a variable. 372 const FieldDecl *lookup(const VarDecl *VD) const override { 373 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 374 return FD; 375 return nullptr; 376 } 377 378 /// Emit the captured statement body. 379 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 380 llvm_unreachable("No body for expressions"); 381 } 382 383 /// Get a variable or parameter for storing global thread id 384 /// inside OpenMP construct. 385 const VarDecl *getThreadIDVariable() const override { 386 llvm_unreachable("No thread id for expressions"); 387 } 388 389 /// Get the name of the capture helper. 390 StringRef getHelperName() const override { 391 llvm_unreachable("No helper name for expressions"); 392 } 393 394 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 395 396 private: 397 /// Private scope to capture global variables. 398 CodeGenFunction::OMPPrivateScope PrivScope; 399 }; 400 401 /// RAII for emitting code of OpenMP constructs. 402 class InlinedOpenMPRegionRAII { 403 CodeGenFunction &CGF; 404 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 405 FieldDecl *LambdaThisCaptureField = nullptr; 406 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 407 408 public: 409 /// Constructs region for combined constructs. 410 /// \param CodeGen Code generation sequence for combined directives. Includes 411 /// a list of functions used for code generation of implicitly inlined 412 /// regions. 413 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 414 OpenMPDirectiveKind Kind, bool HasCancel) 415 : CGF(CGF) { 416 // Start emission for the construct. 417 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 418 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 419 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 420 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 421 CGF.LambdaThisCaptureField = nullptr; 422 BlockInfo = CGF.BlockInfo; 423 CGF.BlockInfo = nullptr; 424 } 425 426 ~InlinedOpenMPRegionRAII() { 427 // Restore original CapturedStmtInfo only if we're done with code emission. 428 auto *OldCSI = 429 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 430 delete CGF.CapturedStmtInfo; 431 CGF.CapturedStmtInfo = OldCSI; 432 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 433 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 434 CGF.BlockInfo = BlockInfo; 435 } 436 }; 437 438 /// Values for bit flags used in the ident_t to describe the fields. 439 /// All enumeric elements are named and described in accordance with the code 440 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 441 enum OpenMPLocationFlags : unsigned { 442 /// Use trampoline for internal microtask. 443 OMP_IDENT_IMD = 0x01, 444 /// Use c-style ident structure. 445 OMP_IDENT_KMPC = 0x02, 446 /// Atomic reduction option for kmpc_reduce. 447 OMP_ATOMIC_REDUCE = 0x10, 448 /// Explicit 'barrier' directive. 449 OMP_IDENT_BARRIER_EXPL = 0x20, 450 /// Implicit barrier in code. 451 OMP_IDENT_BARRIER_IMPL = 0x40, 452 /// Implicit barrier in 'for' directive. 453 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 454 /// Implicit barrier in 'sections' directive. 455 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 456 /// Implicit barrier in 'single' directive. 457 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 458 /// Call of __kmp_for_static_init for static loop. 459 OMP_IDENT_WORK_LOOP = 0x200, 460 /// Call of __kmp_for_static_init for sections. 461 OMP_IDENT_WORK_SECTIONS = 0x400, 462 /// Call of __kmp_for_static_init for distribute. 463 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 464 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 465 }; 466 467 namespace { 468 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 469 /// Values for bit flags for marking which requires clauses have been used. 470 enum OpenMPOffloadingRequiresDirFlags : int64_t { 471 /// flag undefined. 472 OMP_REQ_UNDEFINED = 0x000, 473 /// no requires clause present. 474 OMP_REQ_NONE = 0x001, 475 /// reverse_offload clause. 476 OMP_REQ_REVERSE_OFFLOAD = 0x002, 477 /// unified_address clause. 478 OMP_REQ_UNIFIED_ADDRESS = 0x004, 479 /// unified_shared_memory clause. 480 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 481 /// dynamic_allocators clause. 482 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 483 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 484 }; 485 486 enum OpenMPOffloadingReservedDeviceIDs { 487 /// Device ID if the device was not defined, runtime should get it 488 /// from environment variables in the spec. 489 OMP_DEVICEID_UNDEF = -1, 490 }; 491 } // anonymous namespace 492 493 /// Describes ident structure that describes a source location. 494 /// All descriptions are taken from 495 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 496 /// Original structure: 497 /// typedef struct ident { 498 /// kmp_int32 reserved_1; /**< might be used in Fortran; 499 /// see above */ 500 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 501 /// KMP_IDENT_KMPC identifies this union 502 /// member */ 503 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 504 /// see above */ 505 ///#if USE_ITT_BUILD 506 /// /* but currently used for storing 507 /// region-specific ITT */ 508 /// /* contextual information. */ 509 ///#endif /* USE_ITT_BUILD */ 510 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 511 /// C++ */ 512 /// char const *psource; /**< String describing the source location. 513 /// The string is composed of semi-colon separated 514 // fields which describe the source file, 515 /// the function and a pair of line numbers that 516 /// delimit the construct. 517 /// */ 518 /// } ident_t; 519 enum IdentFieldIndex { 520 /// might be used in Fortran 521 IdentField_Reserved_1, 522 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 523 IdentField_Flags, 524 /// Not really used in Fortran any more 525 IdentField_Reserved_2, 526 /// Source[4] in Fortran, do not use for C++ 527 IdentField_Reserved_3, 528 /// String describing the source location. The string is composed of 529 /// semi-colon separated fields which describe the source file, the function 530 /// and a pair of line numbers that delimit the construct. 531 IdentField_PSource 532 }; 533 534 /// Schedule types for 'omp for' loops (these enumerators are taken from 535 /// the enum sched_type in kmp.h). 536 enum OpenMPSchedType { 537 /// Lower bound for default (unordered) versions. 538 OMP_sch_lower = 32, 539 OMP_sch_static_chunked = 33, 540 OMP_sch_static = 34, 541 OMP_sch_dynamic_chunked = 35, 542 OMP_sch_guided_chunked = 36, 543 OMP_sch_runtime = 37, 544 OMP_sch_auto = 38, 545 /// static with chunk adjustment (e.g., simd) 546 OMP_sch_static_balanced_chunked = 45, 547 /// Lower bound for 'ordered' versions. 548 OMP_ord_lower = 64, 549 OMP_ord_static_chunked = 65, 550 OMP_ord_static = 66, 551 OMP_ord_dynamic_chunked = 67, 552 OMP_ord_guided_chunked = 68, 553 OMP_ord_runtime = 69, 554 OMP_ord_auto = 70, 555 OMP_sch_default = OMP_sch_static, 556 /// dist_schedule types 557 OMP_dist_sch_static_chunked = 91, 558 OMP_dist_sch_static = 92, 559 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 560 /// Set if the monotonic schedule modifier was present. 561 OMP_sch_modifier_monotonic = (1 << 29), 562 /// Set if the nonmonotonic schedule modifier was present. 563 OMP_sch_modifier_nonmonotonic = (1 << 30), 564 }; 565 566 enum OpenMPRTLFunction { 567 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 568 /// kmpc_micro microtask, ...); 569 OMPRTL__kmpc_fork_call, 570 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 571 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 572 OMPRTL__kmpc_threadprivate_cached, 573 /// Call to void __kmpc_threadprivate_register( ident_t *, 574 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 575 OMPRTL__kmpc_threadprivate_register, 576 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 577 OMPRTL__kmpc_global_thread_num, 578 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 579 // kmp_critical_name *crit); 580 OMPRTL__kmpc_critical, 581 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 582 // global_tid, kmp_critical_name *crit, uintptr_t hint); 583 OMPRTL__kmpc_critical_with_hint, 584 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 585 // kmp_critical_name *crit); 586 OMPRTL__kmpc_end_critical, 587 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 588 // global_tid); 589 OMPRTL__kmpc_cancel_barrier, 590 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 591 OMPRTL__kmpc_barrier, 592 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 593 OMPRTL__kmpc_for_static_fini, 594 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 595 // global_tid); 596 OMPRTL__kmpc_serialized_parallel, 597 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 598 // global_tid); 599 OMPRTL__kmpc_end_serialized_parallel, 600 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 601 // kmp_int32 num_threads); 602 OMPRTL__kmpc_push_num_threads, 603 // Call to void __kmpc_flush(ident_t *loc); 604 OMPRTL__kmpc_flush, 605 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 606 OMPRTL__kmpc_master, 607 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 608 OMPRTL__kmpc_end_master, 609 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 610 // int end_part); 611 OMPRTL__kmpc_omp_taskyield, 612 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 613 OMPRTL__kmpc_single, 614 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 615 OMPRTL__kmpc_end_single, 616 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 617 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 618 // kmp_routine_entry_t *task_entry); 619 OMPRTL__kmpc_omp_task_alloc, 620 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 621 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 622 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 623 // kmp_int64 device_id); 624 OMPRTL__kmpc_omp_target_task_alloc, 625 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 626 // new_task); 627 OMPRTL__kmpc_omp_task, 628 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 629 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 630 // kmp_int32 didit); 631 OMPRTL__kmpc_copyprivate, 632 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 633 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 634 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 635 OMPRTL__kmpc_reduce, 636 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 637 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 638 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 639 // *lck); 640 OMPRTL__kmpc_reduce_nowait, 641 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 642 // kmp_critical_name *lck); 643 OMPRTL__kmpc_end_reduce, 644 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 645 // kmp_critical_name *lck); 646 OMPRTL__kmpc_end_reduce_nowait, 647 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 648 // kmp_task_t * new_task); 649 OMPRTL__kmpc_omp_task_begin_if0, 650 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 651 // kmp_task_t * new_task); 652 OMPRTL__kmpc_omp_task_complete_if0, 653 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 654 OMPRTL__kmpc_ordered, 655 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 656 OMPRTL__kmpc_end_ordered, 657 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 658 // global_tid); 659 OMPRTL__kmpc_omp_taskwait, 660 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 661 OMPRTL__kmpc_taskgroup, 662 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 663 OMPRTL__kmpc_end_taskgroup, 664 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 665 // int proc_bind); 666 OMPRTL__kmpc_push_proc_bind, 667 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 668 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 669 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 670 OMPRTL__kmpc_omp_task_with_deps, 671 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 672 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 673 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 674 OMPRTL__kmpc_omp_wait_deps, 675 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 676 // global_tid, kmp_int32 cncl_kind); 677 OMPRTL__kmpc_cancellationpoint, 678 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 679 // kmp_int32 cncl_kind); 680 OMPRTL__kmpc_cancel, 681 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 682 // kmp_int32 num_teams, kmp_int32 thread_limit); 683 OMPRTL__kmpc_push_num_teams, 684 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 685 // microtask, ...); 686 OMPRTL__kmpc_fork_teams, 687 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 688 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 689 // sched, kmp_uint64 grainsize, void *task_dup); 690 OMPRTL__kmpc_taskloop, 691 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 692 // num_dims, struct kmp_dim *dims); 693 OMPRTL__kmpc_doacross_init, 694 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 695 OMPRTL__kmpc_doacross_fini, 696 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 697 // *vec); 698 OMPRTL__kmpc_doacross_post, 699 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 700 // *vec); 701 OMPRTL__kmpc_doacross_wait, 702 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 703 // *data); 704 OMPRTL__kmpc_task_reduction_init, 705 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 706 // *d); 707 OMPRTL__kmpc_task_reduction_get_th_data, 708 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 709 OMPRTL__kmpc_alloc, 710 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 711 OMPRTL__kmpc_free, 712 713 // 714 // Offloading related calls 715 // 716 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 717 // size); 718 OMPRTL__kmpc_push_target_tripcount, 719 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 720 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 721 // *arg_types); 722 OMPRTL__tgt_target, 723 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 724 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 725 // *arg_types); 726 OMPRTL__tgt_target_nowait, 727 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 728 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 729 // *arg_types, int32_t num_teams, int32_t thread_limit); 730 OMPRTL__tgt_target_teams, 731 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 732 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 733 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 734 OMPRTL__tgt_target_teams_nowait, 735 // Call to void __tgt_register_requires(int64_t flags); 736 OMPRTL__tgt_register_requires, 737 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 738 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 739 OMPRTL__tgt_target_data_begin, 740 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 741 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 742 // *arg_types); 743 OMPRTL__tgt_target_data_begin_nowait, 744 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 745 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 746 OMPRTL__tgt_target_data_end, 747 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 748 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 749 // *arg_types); 750 OMPRTL__tgt_target_data_end_nowait, 751 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 752 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 753 OMPRTL__tgt_target_data_update, 754 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 755 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 756 // *arg_types); 757 OMPRTL__tgt_target_data_update_nowait, 758 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 759 OMPRTL__tgt_mapper_num_components, 760 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 761 // *base, void *begin, int64_t size, int64_t type); 762 OMPRTL__tgt_push_mapper_component, 763 }; 764 765 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 766 /// region. 767 class CleanupTy final : public EHScopeStack::Cleanup { 768 PrePostActionTy *Action; 769 770 public: 771 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 772 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 773 if (!CGF.HaveInsertPoint()) 774 return; 775 Action->Exit(CGF); 776 } 777 }; 778 779 } // anonymous namespace 780 781 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 782 CodeGenFunction::RunCleanupsScope Scope(CGF); 783 if (PrePostAction) { 784 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 785 Callback(CodeGen, CGF, *PrePostAction); 786 } else { 787 PrePostActionTy Action; 788 Callback(CodeGen, CGF, Action); 789 } 790 } 791 792 /// Check if the combiner is a call to UDR combiner and if it is so return the 793 /// UDR decl used for reduction. 794 static const OMPDeclareReductionDecl * 795 getReductionInit(const Expr *ReductionOp) { 796 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 797 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 798 if (const auto *DRE = 799 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 800 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 801 return DRD; 802 return nullptr; 803 } 804 805 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 806 const OMPDeclareReductionDecl *DRD, 807 const Expr *InitOp, 808 Address Private, Address Original, 809 QualType Ty) { 810 if (DRD->getInitializer()) { 811 std::pair<llvm::Function *, llvm::Function *> Reduction = 812 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 813 const auto *CE = cast<CallExpr>(InitOp); 814 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 815 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 816 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 817 const auto *LHSDRE = 818 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 819 const auto *RHSDRE = 820 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 821 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 822 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 823 [=]() { return Private; }); 824 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 825 [=]() { return Original; }); 826 (void)PrivateScope.Privatize(); 827 RValue Func = RValue::get(Reduction.second); 828 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 829 CGF.EmitIgnoredExpr(InitOp); 830 } else { 831 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 832 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 833 auto *GV = new llvm::GlobalVariable( 834 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 835 llvm::GlobalValue::PrivateLinkage, Init, Name); 836 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 837 RValue InitRVal; 838 switch (CGF.getEvaluationKind(Ty)) { 839 case TEK_Scalar: 840 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 841 break; 842 case TEK_Complex: 843 InitRVal = 844 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 845 break; 846 case TEK_Aggregate: 847 InitRVal = RValue::getAggregate(LV.getAddress(CGF)); 848 break; 849 } 850 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 851 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 852 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 853 /*IsInitializer=*/false); 854 } 855 } 856 857 /// Emit initialization of arrays of complex types. 858 /// \param DestAddr Address of the array. 859 /// \param Type Type of array. 860 /// \param Init Initial expression of array. 861 /// \param SrcAddr Address of the original array. 862 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 863 QualType Type, bool EmitDeclareReductionInit, 864 const Expr *Init, 865 const OMPDeclareReductionDecl *DRD, 866 Address SrcAddr = Address::invalid()) { 867 // Perform element-by-element initialization. 868 QualType ElementTy; 869 870 // Drill down to the base element type on both arrays. 871 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 872 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 873 DestAddr = 874 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 875 if (DRD) 876 SrcAddr = 877 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 878 879 llvm::Value *SrcBegin = nullptr; 880 if (DRD) 881 SrcBegin = SrcAddr.getPointer(); 882 llvm::Value *DestBegin = DestAddr.getPointer(); 883 // Cast from pointer to array type to pointer to single element. 884 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 885 // The basic structure here is a while-do loop. 886 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 887 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 888 llvm::Value *IsEmpty = 889 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 890 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 891 892 // Enter the loop body, making that address the current address. 893 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 894 CGF.EmitBlock(BodyBB); 895 896 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 897 898 llvm::PHINode *SrcElementPHI = nullptr; 899 Address SrcElementCurrent = Address::invalid(); 900 if (DRD) { 901 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 902 "omp.arraycpy.srcElementPast"); 903 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 904 SrcElementCurrent = 905 Address(SrcElementPHI, 906 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 907 } 908 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 909 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 910 DestElementPHI->addIncoming(DestBegin, EntryBB); 911 Address DestElementCurrent = 912 Address(DestElementPHI, 913 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 914 915 // Emit copy. 916 { 917 CodeGenFunction::RunCleanupsScope InitScope(CGF); 918 if (EmitDeclareReductionInit) { 919 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 920 SrcElementCurrent, ElementTy); 921 } else 922 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 923 /*IsInitializer=*/false); 924 } 925 926 if (DRD) { 927 // Shift the address forward by one element. 928 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 929 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 930 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 931 } 932 933 // Shift the address forward by one element. 934 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 935 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 936 // Check whether we've reached the end. 937 llvm::Value *Done = 938 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 939 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 940 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 941 942 // Done. 943 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 944 } 945 946 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 947 return CGF.EmitOMPSharedLValue(E); 948 } 949 950 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 951 const Expr *E) { 952 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 953 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 954 return LValue(); 955 } 956 957 void ReductionCodeGen::emitAggregateInitialization( 958 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 959 const OMPDeclareReductionDecl *DRD) { 960 // Emit VarDecl with copy init for arrays. 961 // Get the address of the original variable captured in current 962 // captured region. 963 const auto *PrivateVD = 964 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 965 bool EmitDeclareReductionInit = 966 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 967 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 968 EmitDeclareReductionInit, 969 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 970 : PrivateVD->getInit(), 971 DRD, SharedLVal.getAddress(CGF)); 972 } 973 974 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 975 ArrayRef<const Expr *> Privates, 976 ArrayRef<const Expr *> ReductionOps) { 977 ClausesData.reserve(Shareds.size()); 978 SharedAddresses.reserve(Shareds.size()); 979 Sizes.reserve(Shareds.size()); 980 BaseDecls.reserve(Shareds.size()); 981 auto IPriv = Privates.begin(); 982 auto IRed = ReductionOps.begin(); 983 for (const Expr *Ref : Shareds) { 984 ClausesData.emplace_back(Ref, *IPriv, *IRed); 985 std::advance(IPriv, 1); 986 std::advance(IRed, 1); 987 } 988 } 989 990 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 991 assert(SharedAddresses.size() == N && 992 "Number of generated lvalues must be exactly N."); 993 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 994 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 995 SharedAddresses.emplace_back(First, Second); 996 } 997 998 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 999 const auto *PrivateVD = 1000 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1001 QualType PrivateType = PrivateVD->getType(); 1002 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1003 if (!PrivateType->isVariablyModifiedType()) { 1004 Sizes.emplace_back( 1005 CGF.getTypeSize( 1006 SharedAddresses[N].first.getType().getNonReferenceType()), 1007 nullptr); 1008 return; 1009 } 1010 llvm::Value *Size; 1011 llvm::Value *SizeInChars; 1012 auto *ElemType = cast<llvm::PointerType>( 1013 SharedAddresses[N].first.getPointer(CGF)->getType()) 1014 ->getElementType(); 1015 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1016 if (AsArraySection) { 1017 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(CGF), 1018 SharedAddresses[N].first.getPointer(CGF)); 1019 Size = CGF.Builder.CreateNUWAdd( 1020 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1021 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1022 } else { 1023 SizeInChars = CGF.getTypeSize( 1024 SharedAddresses[N].first.getType().getNonReferenceType()); 1025 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1026 } 1027 Sizes.emplace_back(SizeInChars, Size); 1028 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1029 CGF, 1030 cast<OpaqueValueExpr>( 1031 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1032 RValue::get(Size)); 1033 CGF.EmitVariablyModifiedType(PrivateType); 1034 } 1035 1036 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1037 llvm::Value *Size) { 1038 const auto *PrivateVD = 1039 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1040 QualType PrivateType = PrivateVD->getType(); 1041 if (!PrivateType->isVariablyModifiedType()) { 1042 assert(!Size && !Sizes[N].second && 1043 "Size should be nullptr for non-variably modified reduction " 1044 "items."); 1045 return; 1046 } 1047 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1048 CGF, 1049 cast<OpaqueValueExpr>( 1050 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1051 RValue::get(Size)); 1052 CGF.EmitVariablyModifiedType(PrivateType); 1053 } 1054 1055 void ReductionCodeGen::emitInitialization( 1056 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1057 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1058 assert(SharedAddresses.size() > N && "No variable was generated"); 1059 const auto *PrivateVD = 1060 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1061 const OMPDeclareReductionDecl *DRD = 1062 getReductionInit(ClausesData[N].ReductionOp); 1063 QualType PrivateType = PrivateVD->getType(); 1064 PrivateAddr = CGF.Builder.CreateElementBitCast( 1065 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1066 QualType SharedType = SharedAddresses[N].first.getType(); 1067 SharedLVal = CGF.MakeAddrLValue( 1068 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(CGF), 1069 CGF.ConvertTypeForMem(SharedType)), 1070 SharedType, SharedAddresses[N].first.getBaseInfo(), 1071 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1072 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1073 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1074 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1075 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1076 PrivateAddr, SharedLVal.getAddress(CGF), 1077 SharedLVal.getType()); 1078 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1079 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1080 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1081 PrivateVD->getType().getQualifiers(), 1082 /*IsInitializer=*/false); 1083 } 1084 } 1085 1086 bool ReductionCodeGen::needCleanups(unsigned N) { 1087 const auto *PrivateVD = 1088 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1089 QualType PrivateType = PrivateVD->getType(); 1090 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1091 return DTorKind != QualType::DK_none; 1092 } 1093 1094 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1095 Address PrivateAddr) { 1096 const auto *PrivateVD = 1097 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1098 QualType PrivateType = PrivateVD->getType(); 1099 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1100 if (needCleanups(N)) { 1101 PrivateAddr = CGF.Builder.CreateElementBitCast( 1102 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1103 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1104 } 1105 } 1106 1107 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1108 LValue BaseLV) { 1109 BaseTy = BaseTy.getNonReferenceType(); 1110 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1111 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1112 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1113 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(CGF), PtrTy); 1114 } else { 1115 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(CGF), BaseTy); 1116 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1117 } 1118 BaseTy = BaseTy->getPointeeType(); 1119 } 1120 return CGF.MakeAddrLValue( 1121 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(CGF), 1122 CGF.ConvertTypeForMem(ElTy)), 1123 BaseLV.getType(), BaseLV.getBaseInfo(), 1124 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1125 } 1126 1127 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1128 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1129 llvm::Value *Addr) { 1130 Address Tmp = Address::invalid(); 1131 Address TopTmp = Address::invalid(); 1132 Address MostTopTmp = Address::invalid(); 1133 BaseTy = BaseTy.getNonReferenceType(); 1134 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1135 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1136 Tmp = CGF.CreateMemTemp(BaseTy); 1137 if (TopTmp.isValid()) 1138 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1139 else 1140 MostTopTmp = Tmp; 1141 TopTmp = Tmp; 1142 BaseTy = BaseTy->getPointeeType(); 1143 } 1144 llvm::Type *Ty = BaseLVType; 1145 if (Tmp.isValid()) 1146 Ty = Tmp.getElementType(); 1147 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1148 if (Tmp.isValid()) { 1149 CGF.Builder.CreateStore(Addr, Tmp); 1150 return MostTopTmp; 1151 } 1152 return Address(Addr, BaseLVAlignment); 1153 } 1154 1155 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1156 const VarDecl *OrigVD = nullptr; 1157 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1158 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1159 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1160 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1161 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1162 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1163 DE = cast<DeclRefExpr>(Base); 1164 OrigVD = cast<VarDecl>(DE->getDecl()); 1165 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1166 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1167 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1168 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1169 DE = cast<DeclRefExpr>(Base); 1170 OrigVD = cast<VarDecl>(DE->getDecl()); 1171 } 1172 return OrigVD; 1173 } 1174 1175 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1176 Address PrivateAddr) { 1177 const DeclRefExpr *DE; 1178 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1179 BaseDecls.emplace_back(OrigVD); 1180 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1181 LValue BaseLValue = 1182 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1183 OriginalBaseLValue); 1184 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1185 BaseLValue.getPointer(CGF), SharedAddresses[N].first.getPointer(CGF)); 1186 llvm::Value *PrivatePointer = 1187 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1188 PrivateAddr.getPointer(), 1189 SharedAddresses[N].first.getAddress(CGF).getType()); 1190 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1191 return castToBase(CGF, OrigVD->getType(), 1192 SharedAddresses[N].first.getType(), 1193 OriginalBaseLValue.getAddress(CGF).getType(), 1194 OriginalBaseLValue.getAlignment(), Ptr); 1195 } 1196 BaseDecls.emplace_back( 1197 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1198 return PrivateAddr; 1199 } 1200 1201 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1202 const OMPDeclareReductionDecl *DRD = 1203 getReductionInit(ClausesData[N].ReductionOp); 1204 return DRD && DRD->getInitializer(); 1205 } 1206 1207 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1208 return CGF.EmitLoadOfPointerLValue( 1209 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1210 getThreadIDVariable()->getType()->castAs<PointerType>()); 1211 } 1212 1213 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1214 if (!CGF.HaveInsertPoint()) 1215 return; 1216 // 1.2.2 OpenMP Language Terminology 1217 // Structured block - An executable statement with a single entry at the 1218 // top and a single exit at the bottom. 1219 // The point of exit cannot be a branch out of the structured block. 1220 // longjmp() and throw() must not violate the entry/exit criteria. 1221 CGF.EHStack.pushTerminate(); 1222 CodeGen(CGF); 1223 CGF.EHStack.popTerminate(); 1224 } 1225 1226 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1227 CodeGenFunction &CGF) { 1228 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1229 getThreadIDVariable()->getType(), 1230 AlignmentSource::Decl); 1231 } 1232 1233 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1234 QualType FieldTy) { 1235 auto *Field = FieldDecl::Create( 1236 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1237 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1238 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1239 Field->setAccess(AS_public); 1240 DC->addDecl(Field); 1241 return Field; 1242 } 1243 1244 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1245 StringRef Separator) 1246 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1247 OffloadEntriesInfoManager(CGM) { 1248 ASTContext &C = CGM.getContext(); 1249 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1250 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1251 RD->startDefinition(); 1252 // reserved_1 1253 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1254 // flags 1255 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1256 // reserved_2 1257 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1258 // reserved_3 1259 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1260 // psource 1261 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1262 RD->completeDefinition(); 1263 IdentQTy = C.getRecordType(RD); 1264 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1265 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1266 1267 loadOffloadInfoMetadata(); 1268 } 1269 1270 bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD, 1271 const GlobalDecl &OldGD, 1272 llvm::GlobalValue *OrigAddr, 1273 bool IsForDefinition) { 1274 // Emit at least a definition for the aliasee if the the address of the 1275 // original function is requested. 1276 if (IsForDefinition || OrigAddr) 1277 (void)CGM.GetAddrOfGlobal(NewGD); 1278 StringRef NewMangledName = CGM.getMangledName(NewGD); 1279 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1280 if (Addr && !Addr->isDeclaration()) { 1281 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1282 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(NewGD); 1283 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1284 1285 // Create a reference to the named value. This ensures that it is emitted 1286 // if a deferred decl. 1287 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1288 1289 // Create the new alias itself, but don't set a name yet. 1290 auto *GA = 1291 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1292 1293 if (OrigAddr) { 1294 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1295 1296 GA->takeName(OrigAddr); 1297 OrigAddr->replaceAllUsesWith( 1298 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1299 OrigAddr->eraseFromParent(); 1300 } else { 1301 GA->setName(CGM.getMangledName(OldGD)); 1302 } 1303 1304 // Set attributes which are particular to an alias; this is a 1305 // specialization of the attributes which may be set on a global function. 1306 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1307 D->isWeakImported()) 1308 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1309 1310 CGM.SetCommonAttributes(OldGD, GA); 1311 return true; 1312 } 1313 return false; 1314 } 1315 1316 void CGOpenMPRuntime::clear() { 1317 InternalVars.clear(); 1318 // Clean non-target variable declarations possibly used only in debug info. 1319 for (const auto &Data : EmittedNonTargetVariables) { 1320 if (!Data.getValue().pointsToAliveValue()) 1321 continue; 1322 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1323 if (!GV) 1324 continue; 1325 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1326 continue; 1327 GV->eraseFromParent(); 1328 } 1329 // Emit aliases for the deferred aliasees. 1330 for (const auto &Pair : DeferredVariantFunction) { 1331 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1332 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1333 // If not able to emit alias, just emit original declaration. 1334 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr, 1335 /*IsForDefinition=*/false); 1336 } 1337 } 1338 1339 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1340 SmallString<128> Buffer; 1341 llvm::raw_svector_ostream OS(Buffer); 1342 StringRef Sep = FirstSeparator; 1343 for (StringRef Part : Parts) { 1344 OS << Sep << Part; 1345 Sep = Separator; 1346 } 1347 return std::string(OS.str()); 1348 } 1349 1350 static llvm::Function * 1351 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1352 const Expr *CombinerInitializer, const VarDecl *In, 1353 const VarDecl *Out, bool IsCombiner) { 1354 // void .omp_combiner.(Ty *in, Ty *out); 1355 ASTContext &C = CGM.getContext(); 1356 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1357 FunctionArgList Args; 1358 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1359 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1360 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1361 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1362 Args.push_back(&OmpOutParm); 1363 Args.push_back(&OmpInParm); 1364 const CGFunctionInfo &FnInfo = 1365 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1366 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1367 std::string Name = CGM.getOpenMPRuntime().getName( 1368 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1369 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1370 Name, &CGM.getModule()); 1371 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1372 if (CGM.getLangOpts().Optimize) { 1373 Fn->removeFnAttr(llvm::Attribute::NoInline); 1374 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1375 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1376 } 1377 CodeGenFunction CGF(CGM); 1378 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1379 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1380 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1381 Out->getLocation()); 1382 CodeGenFunction::OMPPrivateScope Scope(CGF); 1383 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1384 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1385 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1386 .getAddress(CGF); 1387 }); 1388 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1389 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1390 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1391 .getAddress(CGF); 1392 }); 1393 (void)Scope.Privatize(); 1394 if (!IsCombiner && Out->hasInit() && 1395 !CGF.isTrivialInitializer(Out->getInit())) { 1396 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1397 Out->getType().getQualifiers(), 1398 /*IsInitializer=*/true); 1399 } 1400 if (CombinerInitializer) 1401 CGF.EmitIgnoredExpr(CombinerInitializer); 1402 Scope.ForceCleanup(); 1403 CGF.FinishFunction(); 1404 return Fn; 1405 } 1406 1407 void CGOpenMPRuntime::emitUserDefinedReduction( 1408 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1409 if (UDRMap.count(D) > 0) 1410 return; 1411 llvm::Function *Combiner = emitCombinerOrInitializer( 1412 CGM, D->getType(), D->getCombiner(), 1413 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1414 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1415 /*IsCombiner=*/true); 1416 llvm::Function *Initializer = nullptr; 1417 if (const Expr *Init = D->getInitializer()) { 1418 Initializer = emitCombinerOrInitializer( 1419 CGM, D->getType(), 1420 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1421 : nullptr, 1422 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1423 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1424 /*IsCombiner=*/false); 1425 } 1426 UDRMap.try_emplace(D, Combiner, Initializer); 1427 if (CGF) { 1428 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1429 Decls.second.push_back(D); 1430 } 1431 } 1432 1433 std::pair<llvm::Function *, llvm::Function *> 1434 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1435 auto I = UDRMap.find(D); 1436 if (I != UDRMap.end()) 1437 return I->second; 1438 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1439 return UDRMap.lookup(D); 1440 } 1441 1442 namespace { 1443 // Temporary RAII solution to perform a push/pop stack event on the OpenMP IR 1444 // Builder if one is present. 1445 struct PushAndPopStackRAII { 1446 PushAndPopStackRAII(llvm::OpenMPIRBuilder *OMPBuilder, CodeGenFunction &CGF, 1447 bool HasCancel) 1448 : OMPBuilder(OMPBuilder) { 1449 if (!OMPBuilder) 1450 return; 1451 1452 // The following callback is the crucial part of clangs cleanup process. 1453 // 1454 // NOTE: 1455 // Once the OpenMPIRBuilder is used to create parallel regions (and 1456 // similar), the cancellation destination (Dest below) is determined via 1457 // IP. That means if we have variables to finalize we split the block at IP, 1458 // use the new block (=BB) as destination to build a JumpDest (via 1459 // getJumpDestInCurrentScope(BB)) which then is fed to 1460 // EmitBranchThroughCleanup. Furthermore, there will not be the need 1461 // to push & pop an FinalizationInfo object. 1462 // The FiniCB will still be needed but at the point where the 1463 // OpenMPIRBuilder is asked to construct a parallel (or similar) construct. 1464 auto FiniCB = [&CGF](llvm::OpenMPIRBuilder::InsertPointTy IP) { 1465 assert(IP.getBlock()->end() == IP.getPoint() && 1466 "Clang CG should cause non-terminated block!"); 1467 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1468 CGF.Builder.restoreIP(IP); 1469 CodeGenFunction::JumpDest Dest = 1470 CGF.getOMPCancelDestination(OMPD_parallel); 1471 CGF.EmitBranchThroughCleanup(Dest); 1472 }; 1473 1474 // TODO: Remove this once we emit parallel regions through the 1475 // OpenMPIRBuilder as it can do this setup internally. 1476 llvm::OpenMPIRBuilder::FinalizationInfo FI( 1477 {FiniCB, OMPD_parallel, HasCancel}); 1478 OMPBuilder->pushFinalizationCB(std::move(FI)); 1479 } 1480 ~PushAndPopStackRAII() { 1481 if (OMPBuilder) 1482 OMPBuilder->popFinalizationCB(); 1483 } 1484 llvm::OpenMPIRBuilder *OMPBuilder; 1485 }; 1486 } // namespace 1487 1488 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1489 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1490 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1491 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1492 assert(ThreadIDVar->getType()->isPointerType() && 1493 "thread id variable must be of type kmp_int32 *"); 1494 CodeGenFunction CGF(CGM, true); 1495 bool HasCancel = false; 1496 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1497 HasCancel = OPD->hasCancel(); 1498 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1499 HasCancel = OPSD->hasCancel(); 1500 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1501 HasCancel = OPFD->hasCancel(); 1502 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1503 HasCancel = OPFD->hasCancel(); 1504 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1505 HasCancel = OPFD->hasCancel(); 1506 else if (const auto *OPFD = 1507 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1508 HasCancel = OPFD->hasCancel(); 1509 else if (const auto *OPFD = 1510 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1511 HasCancel = OPFD->hasCancel(); 1512 1513 // TODO: Temporarily inform the OpenMPIRBuilder, if any, about the new 1514 // parallel region to make cancellation barriers work properly. 1515 llvm::OpenMPIRBuilder *OMPBuilder = CGM.getOpenMPIRBuilder(); 1516 PushAndPopStackRAII PSR(OMPBuilder, CGF, HasCancel); 1517 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1518 HasCancel, OutlinedHelperName); 1519 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1520 return CGF.GenerateOpenMPCapturedStmtFunction(*CS, D.getBeginLoc()); 1521 } 1522 1523 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1524 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1525 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1526 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1527 return emitParallelOrTeamsOutlinedFunction( 1528 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1529 } 1530 1531 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1532 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1533 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1534 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1535 return emitParallelOrTeamsOutlinedFunction( 1536 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1537 } 1538 1539 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1540 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1541 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1542 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1543 bool Tied, unsigned &NumberOfParts) { 1544 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1545 PrePostActionTy &) { 1546 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1547 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1548 llvm::Value *TaskArgs[] = { 1549 UpLoc, ThreadID, 1550 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1551 TaskTVar->getType()->castAs<PointerType>()) 1552 .getPointer(CGF)}; 1553 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1554 }; 1555 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1556 UntiedCodeGen); 1557 CodeGen.setAction(Action); 1558 assert(!ThreadIDVar->getType()->isPointerType() && 1559 "thread id variable must be of type kmp_int32 for tasks"); 1560 const OpenMPDirectiveKind Region = 1561 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1562 : OMPD_task; 1563 const CapturedStmt *CS = D.getCapturedStmt(Region); 1564 const auto *TD = dyn_cast<OMPTaskDirective>(&D); 1565 CodeGenFunction CGF(CGM, true); 1566 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1567 InnermostKind, 1568 TD ? TD->hasCancel() : false, Action); 1569 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1570 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1571 if (!Tied) 1572 NumberOfParts = Action.getNumberOfParts(); 1573 return Res; 1574 } 1575 1576 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1577 const RecordDecl *RD, const CGRecordLayout &RL, 1578 ArrayRef<llvm::Constant *> Data) { 1579 llvm::StructType *StructTy = RL.getLLVMType(); 1580 unsigned PrevIdx = 0; 1581 ConstantInitBuilder CIBuilder(CGM); 1582 auto DI = Data.begin(); 1583 for (const FieldDecl *FD : RD->fields()) { 1584 unsigned Idx = RL.getLLVMFieldNo(FD); 1585 // Fill the alignment. 1586 for (unsigned I = PrevIdx; I < Idx; ++I) 1587 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1588 PrevIdx = Idx + 1; 1589 Fields.add(*DI); 1590 ++DI; 1591 } 1592 } 1593 1594 template <class... As> 1595 static llvm::GlobalVariable * 1596 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1597 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1598 As &&... Args) { 1599 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1600 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1601 ConstantInitBuilder CIBuilder(CGM); 1602 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1603 buildStructValue(Fields, CGM, RD, RL, Data); 1604 return Fields.finishAndCreateGlobal( 1605 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1606 std::forward<As>(Args)...); 1607 } 1608 1609 template <typename T> 1610 static void 1611 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1612 ArrayRef<llvm::Constant *> Data, 1613 T &Parent) { 1614 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1615 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1616 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1617 buildStructValue(Fields, CGM, RD, RL, Data); 1618 Fields.finishAndAddTo(Parent); 1619 } 1620 1621 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1622 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1623 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1624 FlagsTy FlagsKey(Flags, Reserved2Flags); 1625 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1626 if (!Entry) { 1627 if (!DefaultOpenMPPSource) { 1628 // Initialize default location for psource field of ident_t structure of 1629 // all ident_t objects. Format is ";file;function;line;column;;". 1630 // Taken from 1631 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1632 DefaultOpenMPPSource = 1633 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1634 DefaultOpenMPPSource = 1635 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1636 } 1637 1638 llvm::Constant *Data[] = { 1639 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1640 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1641 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1642 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1643 llvm::GlobalValue *DefaultOpenMPLocation = 1644 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1645 llvm::GlobalValue::PrivateLinkage); 1646 DefaultOpenMPLocation->setUnnamedAddr( 1647 llvm::GlobalValue::UnnamedAddr::Global); 1648 1649 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1650 } 1651 return Address(Entry, Align); 1652 } 1653 1654 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1655 bool AtCurrentPoint) { 1656 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1657 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1658 1659 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1660 if (AtCurrentPoint) { 1661 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1662 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1663 } else { 1664 Elem.second.ServiceInsertPt = 1665 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1666 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1667 } 1668 } 1669 1670 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1671 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1672 if (Elem.second.ServiceInsertPt) { 1673 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1674 Elem.second.ServiceInsertPt = nullptr; 1675 Ptr->eraseFromParent(); 1676 } 1677 } 1678 1679 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1680 SourceLocation Loc, 1681 unsigned Flags) { 1682 Flags |= OMP_IDENT_KMPC; 1683 // If no debug info is generated - return global default location. 1684 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1685 Loc.isInvalid()) 1686 return getOrCreateDefaultLocation(Flags).getPointer(); 1687 1688 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1689 1690 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1691 Address LocValue = Address::invalid(); 1692 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1693 if (I != OpenMPLocThreadIDMap.end()) 1694 LocValue = Address(I->second.DebugLoc, Align); 1695 1696 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1697 // GetOpenMPThreadID was called before this routine. 1698 if (!LocValue.isValid()) { 1699 // Generate "ident_t .kmpc_loc.addr;" 1700 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1701 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1702 Elem.second.DebugLoc = AI.getPointer(); 1703 LocValue = AI; 1704 1705 if (!Elem.second.ServiceInsertPt) 1706 setLocThreadIdInsertPt(CGF); 1707 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1708 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1709 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1710 CGF.getTypeSize(IdentQTy)); 1711 } 1712 1713 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1714 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1715 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1716 LValue PSource = 1717 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1718 1719 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1720 if (OMPDebugLoc == nullptr) { 1721 SmallString<128> Buffer2; 1722 llvm::raw_svector_ostream OS2(Buffer2); 1723 // Build debug location 1724 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1725 OS2 << ";" << PLoc.getFilename() << ";"; 1726 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1727 OS2 << FD->getQualifiedNameAsString(); 1728 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1729 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1730 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1731 } 1732 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1733 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1734 1735 // Our callers always pass this to a runtime function, so for 1736 // convenience, go ahead and return a naked pointer. 1737 return LocValue.getPointer(); 1738 } 1739 1740 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1741 SourceLocation Loc) { 1742 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1743 1744 llvm::Value *ThreadID = nullptr; 1745 // Check whether we've already cached a load of the thread id in this 1746 // function. 1747 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1748 if (I != OpenMPLocThreadIDMap.end()) { 1749 ThreadID = I->second.ThreadID; 1750 if (ThreadID != nullptr) 1751 return ThreadID; 1752 } 1753 // If exceptions are enabled, do not use parameter to avoid possible crash. 1754 if (auto *OMPRegionInfo = 1755 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1756 if (OMPRegionInfo->getThreadIDVariable()) { 1757 // Check if this an outlined function with thread id passed as argument. 1758 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1759 llvm::BasicBlock *TopBlock = CGF.AllocaInsertPt->getParent(); 1760 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1761 !CGF.getLangOpts().CXXExceptions || 1762 CGF.Builder.GetInsertBlock() == TopBlock || 1763 !isa<llvm::Instruction>(LVal.getPointer(CGF)) || 1764 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1765 TopBlock || 1766 cast<llvm::Instruction>(LVal.getPointer(CGF))->getParent() == 1767 CGF.Builder.GetInsertBlock()) { 1768 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1769 // If value loaded in entry block, cache it and use it everywhere in 1770 // function. 1771 if (CGF.Builder.GetInsertBlock() == TopBlock) { 1772 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1773 Elem.second.ThreadID = ThreadID; 1774 } 1775 return ThreadID; 1776 } 1777 } 1778 } 1779 1780 // This is not an outlined function region - need to call __kmpc_int32 1781 // kmpc_global_thread_num(ident_t *loc). 1782 // Generate thread id value and cache this value for use across the 1783 // function. 1784 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1785 if (!Elem.second.ServiceInsertPt) 1786 setLocThreadIdInsertPt(CGF); 1787 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1788 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1789 llvm::CallInst *Call = CGF.Builder.CreateCall( 1790 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1791 emitUpdateLocation(CGF, Loc)); 1792 Call->setCallingConv(CGF.getRuntimeCC()); 1793 Elem.second.ThreadID = Call; 1794 return Call; 1795 } 1796 1797 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1798 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1799 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1800 clearLocThreadIdInsertPt(CGF); 1801 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1802 } 1803 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1804 for(auto *D : FunctionUDRMap[CGF.CurFn]) 1805 UDRMap.erase(D); 1806 FunctionUDRMap.erase(CGF.CurFn); 1807 } 1808 auto I = FunctionUDMMap.find(CGF.CurFn); 1809 if (I != FunctionUDMMap.end()) { 1810 for(auto *D : I->second) 1811 UDMMap.erase(D); 1812 FunctionUDMMap.erase(I); 1813 } 1814 } 1815 1816 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1817 return IdentTy->getPointerTo(); 1818 } 1819 1820 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1821 if (!Kmpc_MicroTy) { 1822 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1823 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1824 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1825 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1826 } 1827 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1828 } 1829 1830 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1831 llvm::FunctionCallee RTLFn = nullptr; 1832 switch (static_cast<OpenMPRTLFunction>(Function)) { 1833 case OMPRTL__kmpc_fork_call: { 1834 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1835 // microtask, ...); 1836 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1837 getKmpc_MicroPointerTy()}; 1838 auto *FnTy = 1839 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1840 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1841 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1842 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1843 llvm::LLVMContext &Ctx = F->getContext(); 1844 llvm::MDBuilder MDB(Ctx); 1845 // Annotate the callback behavior of the __kmpc_fork_call: 1846 // - The callback callee is argument number 2 (microtask). 1847 // - The first two arguments of the callback callee are unknown (-1). 1848 // - All variadic arguments to the __kmpc_fork_call are passed to the 1849 // callback callee. 1850 F->addMetadata( 1851 llvm::LLVMContext::MD_callback, 1852 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1853 2, {-1, -1}, 1854 /* VarArgsArePassed */ true)})); 1855 } 1856 } 1857 break; 1858 } 1859 case OMPRTL__kmpc_global_thread_num: { 1860 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1861 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1862 auto *FnTy = 1863 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1864 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1865 break; 1866 } 1867 case OMPRTL__kmpc_threadprivate_cached: { 1868 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1869 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1870 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1871 CGM.VoidPtrTy, CGM.SizeTy, 1872 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1873 auto *FnTy = 1874 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1875 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1876 break; 1877 } 1878 case OMPRTL__kmpc_critical: { 1879 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1880 // kmp_critical_name *crit); 1881 llvm::Type *TypeParams[] = { 1882 getIdentTyPointerTy(), CGM.Int32Ty, 1883 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1884 auto *FnTy = 1885 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1886 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1887 break; 1888 } 1889 case OMPRTL__kmpc_critical_with_hint: { 1890 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1891 // kmp_critical_name *crit, uintptr_t hint); 1892 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1893 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1894 CGM.IntPtrTy}; 1895 auto *FnTy = 1896 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1897 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1898 break; 1899 } 1900 case OMPRTL__kmpc_threadprivate_register: { 1901 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1902 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1903 // typedef void *(*kmpc_ctor)(void *); 1904 auto *KmpcCtorTy = 1905 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1906 /*isVarArg*/ false)->getPointerTo(); 1907 // typedef void *(*kmpc_cctor)(void *, void *); 1908 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1909 auto *KmpcCopyCtorTy = 1910 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1911 /*isVarArg*/ false) 1912 ->getPointerTo(); 1913 // typedef void (*kmpc_dtor)(void *); 1914 auto *KmpcDtorTy = 1915 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1916 ->getPointerTo(); 1917 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1918 KmpcCopyCtorTy, KmpcDtorTy}; 1919 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1920 /*isVarArg*/ false); 1921 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1922 break; 1923 } 1924 case OMPRTL__kmpc_end_critical: { 1925 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1926 // kmp_critical_name *crit); 1927 llvm::Type *TypeParams[] = { 1928 getIdentTyPointerTy(), CGM.Int32Ty, 1929 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1930 auto *FnTy = 1931 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1932 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1933 break; 1934 } 1935 case OMPRTL__kmpc_cancel_barrier: { 1936 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1937 // global_tid); 1938 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1939 auto *FnTy = 1940 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1941 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1942 break; 1943 } 1944 case OMPRTL__kmpc_barrier: { 1945 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1946 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1947 auto *FnTy = 1948 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1949 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1950 break; 1951 } 1952 case OMPRTL__kmpc_for_static_fini: { 1953 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1954 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1955 auto *FnTy = 1956 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1957 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1958 break; 1959 } 1960 case OMPRTL__kmpc_push_num_threads: { 1961 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1962 // kmp_int32 num_threads) 1963 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1964 CGM.Int32Ty}; 1965 auto *FnTy = 1966 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1967 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1968 break; 1969 } 1970 case OMPRTL__kmpc_serialized_parallel: { 1971 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1972 // global_tid); 1973 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1974 auto *FnTy = 1975 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1976 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1977 break; 1978 } 1979 case OMPRTL__kmpc_end_serialized_parallel: { 1980 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1981 // global_tid); 1982 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1983 auto *FnTy = 1984 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1985 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1986 break; 1987 } 1988 case OMPRTL__kmpc_flush: { 1989 // Build void __kmpc_flush(ident_t *loc); 1990 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1991 auto *FnTy = 1992 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1993 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1994 break; 1995 } 1996 case OMPRTL__kmpc_master: { 1997 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 global_tid); 1998 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1999 auto *FnTy = 2000 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2001 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_master"); 2002 break; 2003 } 2004 case OMPRTL__kmpc_end_master: { 2005 // Build void __kmpc_end_master(ident_t *loc, kmp_int32 global_tid); 2006 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2007 auto *FnTy = 2008 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2009 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_master"); 2010 break; 2011 } 2012 case OMPRTL__kmpc_omp_taskyield: { 2013 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 2014 // int end_part); 2015 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2016 auto *FnTy = 2017 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2018 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 2019 break; 2020 } 2021 case OMPRTL__kmpc_single: { 2022 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 2023 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2024 auto *FnTy = 2025 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2026 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 2027 break; 2028 } 2029 case OMPRTL__kmpc_end_single: { 2030 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 2031 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2032 auto *FnTy = 2033 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2034 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 2035 break; 2036 } 2037 case OMPRTL__kmpc_omp_task_alloc: { 2038 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 2039 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2040 // kmp_routine_entry_t *task_entry); 2041 assert(KmpRoutineEntryPtrTy != nullptr && 2042 "Type kmp_routine_entry_t must be created."); 2043 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2044 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 2045 // Return void * and then cast to particular kmp_task_t type. 2046 auto *FnTy = 2047 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2048 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 2049 break; 2050 } 2051 case OMPRTL__kmpc_omp_target_task_alloc: { 2052 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 2053 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 2054 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 2055 assert(KmpRoutineEntryPtrTy != nullptr && 2056 "Type kmp_routine_entry_t must be created."); 2057 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2058 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 2059 CGM.Int64Ty}; 2060 // Return void * and then cast to particular kmp_task_t type. 2061 auto *FnTy = 2062 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2063 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2064 break; 2065 } 2066 case OMPRTL__kmpc_omp_task: { 2067 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2068 // *new_task); 2069 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2070 CGM.VoidPtrTy}; 2071 auto *FnTy = 2072 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2073 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2074 break; 2075 } 2076 case OMPRTL__kmpc_copyprivate: { 2077 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2078 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2079 // kmp_int32 didit); 2080 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2081 auto *CpyFnTy = 2082 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2083 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2084 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2085 CGM.Int32Ty}; 2086 auto *FnTy = 2087 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2088 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2089 break; 2090 } 2091 case OMPRTL__kmpc_reduce: { 2092 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2093 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2094 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2095 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2096 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2097 /*isVarArg=*/false); 2098 llvm::Type *TypeParams[] = { 2099 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2100 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2101 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2102 auto *FnTy = 2103 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2104 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2105 break; 2106 } 2107 case OMPRTL__kmpc_reduce_nowait: { 2108 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2109 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2110 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2111 // *lck); 2112 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2113 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2114 /*isVarArg=*/false); 2115 llvm::Type *TypeParams[] = { 2116 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2117 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2118 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2119 auto *FnTy = 2120 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2121 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2122 break; 2123 } 2124 case OMPRTL__kmpc_end_reduce: { 2125 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2126 // kmp_critical_name *lck); 2127 llvm::Type *TypeParams[] = { 2128 getIdentTyPointerTy(), CGM.Int32Ty, 2129 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2130 auto *FnTy = 2131 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2132 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2133 break; 2134 } 2135 case OMPRTL__kmpc_end_reduce_nowait: { 2136 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2137 // kmp_critical_name *lck); 2138 llvm::Type *TypeParams[] = { 2139 getIdentTyPointerTy(), CGM.Int32Ty, 2140 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2141 auto *FnTy = 2142 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2143 RTLFn = 2144 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2145 break; 2146 } 2147 case OMPRTL__kmpc_omp_task_begin_if0: { 2148 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2149 // *new_task); 2150 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2151 CGM.VoidPtrTy}; 2152 auto *FnTy = 2153 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2154 RTLFn = 2155 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2156 break; 2157 } 2158 case OMPRTL__kmpc_omp_task_complete_if0: { 2159 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2160 // *new_task); 2161 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2162 CGM.VoidPtrTy}; 2163 auto *FnTy = 2164 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2165 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2166 /*Name=*/"__kmpc_omp_task_complete_if0"); 2167 break; 2168 } 2169 case OMPRTL__kmpc_ordered: { 2170 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2171 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2172 auto *FnTy = 2173 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2174 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2175 break; 2176 } 2177 case OMPRTL__kmpc_end_ordered: { 2178 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2179 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2180 auto *FnTy = 2181 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2182 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2183 break; 2184 } 2185 case OMPRTL__kmpc_omp_taskwait: { 2186 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2187 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2188 auto *FnTy = 2189 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2190 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2191 break; 2192 } 2193 case OMPRTL__kmpc_taskgroup: { 2194 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2195 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2196 auto *FnTy = 2197 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2198 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2199 break; 2200 } 2201 case OMPRTL__kmpc_end_taskgroup: { 2202 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2203 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2204 auto *FnTy = 2205 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2206 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2207 break; 2208 } 2209 case OMPRTL__kmpc_push_proc_bind: { 2210 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2211 // int proc_bind) 2212 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2213 auto *FnTy = 2214 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2215 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2216 break; 2217 } 2218 case OMPRTL__kmpc_omp_task_with_deps: { 2219 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2220 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2221 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2222 llvm::Type *TypeParams[] = { 2223 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2224 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2225 auto *FnTy = 2226 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2227 RTLFn = 2228 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2229 break; 2230 } 2231 case OMPRTL__kmpc_omp_wait_deps: { 2232 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2233 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2234 // kmp_depend_info_t *noalias_dep_list); 2235 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2236 CGM.Int32Ty, CGM.VoidPtrTy, 2237 CGM.Int32Ty, CGM.VoidPtrTy}; 2238 auto *FnTy = 2239 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2240 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2241 break; 2242 } 2243 case OMPRTL__kmpc_cancellationpoint: { 2244 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2245 // global_tid, kmp_int32 cncl_kind) 2246 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2247 auto *FnTy = 2248 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2249 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2250 break; 2251 } 2252 case OMPRTL__kmpc_cancel: { 2253 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2254 // kmp_int32 cncl_kind) 2255 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2256 auto *FnTy = 2257 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2258 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2259 break; 2260 } 2261 case OMPRTL__kmpc_push_num_teams: { 2262 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2263 // kmp_int32 num_teams, kmp_int32 num_threads) 2264 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2265 CGM.Int32Ty}; 2266 auto *FnTy = 2267 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2268 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2269 break; 2270 } 2271 case OMPRTL__kmpc_fork_teams: { 2272 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2273 // microtask, ...); 2274 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2275 getKmpc_MicroPointerTy()}; 2276 auto *FnTy = 2277 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2278 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2279 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2280 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2281 llvm::LLVMContext &Ctx = F->getContext(); 2282 llvm::MDBuilder MDB(Ctx); 2283 // Annotate the callback behavior of the __kmpc_fork_teams: 2284 // - The callback callee is argument number 2 (microtask). 2285 // - The first two arguments of the callback callee are unknown (-1). 2286 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2287 // callback callee. 2288 F->addMetadata( 2289 llvm::LLVMContext::MD_callback, 2290 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2291 2, {-1, -1}, 2292 /* VarArgsArePassed */ true)})); 2293 } 2294 } 2295 break; 2296 } 2297 case OMPRTL__kmpc_taskloop: { 2298 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2299 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2300 // sched, kmp_uint64 grainsize, void *task_dup); 2301 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2302 CGM.IntTy, 2303 CGM.VoidPtrTy, 2304 CGM.IntTy, 2305 CGM.Int64Ty->getPointerTo(), 2306 CGM.Int64Ty->getPointerTo(), 2307 CGM.Int64Ty, 2308 CGM.IntTy, 2309 CGM.IntTy, 2310 CGM.Int64Ty, 2311 CGM.VoidPtrTy}; 2312 auto *FnTy = 2313 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2314 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2315 break; 2316 } 2317 case OMPRTL__kmpc_doacross_init: { 2318 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2319 // num_dims, struct kmp_dim *dims); 2320 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2321 CGM.Int32Ty, 2322 CGM.Int32Ty, 2323 CGM.VoidPtrTy}; 2324 auto *FnTy = 2325 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2326 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2327 break; 2328 } 2329 case OMPRTL__kmpc_doacross_fini: { 2330 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2331 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2332 auto *FnTy = 2333 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2334 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2335 break; 2336 } 2337 case OMPRTL__kmpc_doacross_post: { 2338 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2339 // *vec); 2340 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2341 CGM.Int64Ty->getPointerTo()}; 2342 auto *FnTy = 2343 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2344 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2345 break; 2346 } 2347 case OMPRTL__kmpc_doacross_wait: { 2348 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2349 // *vec); 2350 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2351 CGM.Int64Ty->getPointerTo()}; 2352 auto *FnTy = 2353 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2354 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2355 break; 2356 } 2357 case OMPRTL__kmpc_task_reduction_init: { 2358 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2359 // *data); 2360 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2361 auto *FnTy = 2362 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2363 RTLFn = 2364 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2365 break; 2366 } 2367 case OMPRTL__kmpc_task_reduction_get_th_data: { 2368 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2369 // *d); 2370 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2371 auto *FnTy = 2372 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2373 RTLFn = CGM.CreateRuntimeFunction( 2374 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2375 break; 2376 } 2377 case OMPRTL__kmpc_alloc: { 2378 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2379 // al); omp_allocator_handle_t type is void *. 2380 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2381 auto *FnTy = 2382 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2383 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2384 break; 2385 } 2386 case OMPRTL__kmpc_free: { 2387 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2388 // al); omp_allocator_handle_t type is void *. 2389 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2390 auto *FnTy = 2391 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2392 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2393 break; 2394 } 2395 case OMPRTL__kmpc_push_target_tripcount: { 2396 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2397 // size); 2398 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2399 llvm::FunctionType *FnTy = 2400 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2401 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2402 break; 2403 } 2404 case OMPRTL__tgt_target: { 2405 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2406 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2407 // *arg_types); 2408 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2409 CGM.VoidPtrTy, 2410 CGM.Int32Ty, 2411 CGM.VoidPtrPtrTy, 2412 CGM.VoidPtrPtrTy, 2413 CGM.Int64Ty->getPointerTo(), 2414 CGM.Int64Ty->getPointerTo()}; 2415 auto *FnTy = 2416 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2417 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2418 break; 2419 } 2420 case OMPRTL__tgt_target_nowait: { 2421 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2422 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2423 // int64_t *arg_types); 2424 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2425 CGM.VoidPtrTy, 2426 CGM.Int32Ty, 2427 CGM.VoidPtrPtrTy, 2428 CGM.VoidPtrPtrTy, 2429 CGM.Int64Ty->getPointerTo(), 2430 CGM.Int64Ty->getPointerTo()}; 2431 auto *FnTy = 2432 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2433 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2434 break; 2435 } 2436 case OMPRTL__tgt_target_teams: { 2437 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2438 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2439 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2440 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2441 CGM.VoidPtrTy, 2442 CGM.Int32Ty, 2443 CGM.VoidPtrPtrTy, 2444 CGM.VoidPtrPtrTy, 2445 CGM.Int64Ty->getPointerTo(), 2446 CGM.Int64Ty->getPointerTo(), 2447 CGM.Int32Ty, 2448 CGM.Int32Ty}; 2449 auto *FnTy = 2450 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2451 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2452 break; 2453 } 2454 case OMPRTL__tgt_target_teams_nowait: { 2455 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2456 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2457 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2458 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2459 CGM.VoidPtrTy, 2460 CGM.Int32Ty, 2461 CGM.VoidPtrPtrTy, 2462 CGM.VoidPtrPtrTy, 2463 CGM.Int64Ty->getPointerTo(), 2464 CGM.Int64Ty->getPointerTo(), 2465 CGM.Int32Ty, 2466 CGM.Int32Ty}; 2467 auto *FnTy = 2468 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2469 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2470 break; 2471 } 2472 case OMPRTL__tgt_register_requires: { 2473 // Build void __tgt_register_requires(int64_t flags); 2474 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2475 auto *FnTy = 2476 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2477 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2478 break; 2479 } 2480 case OMPRTL__tgt_target_data_begin: { 2481 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2482 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2483 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2484 CGM.Int32Ty, 2485 CGM.VoidPtrPtrTy, 2486 CGM.VoidPtrPtrTy, 2487 CGM.Int64Ty->getPointerTo(), 2488 CGM.Int64Ty->getPointerTo()}; 2489 auto *FnTy = 2490 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2491 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2492 break; 2493 } 2494 case OMPRTL__tgt_target_data_begin_nowait: { 2495 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2496 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2497 // *arg_types); 2498 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2499 CGM.Int32Ty, 2500 CGM.VoidPtrPtrTy, 2501 CGM.VoidPtrPtrTy, 2502 CGM.Int64Ty->getPointerTo(), 2503 CGM.Int64Ty->getPointerTo()}; 2504 auto *FnTy = 2505 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2506 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2507 break; 2508 } 2509 case OMPRTL__tgt_target_data_end: { 2510 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2511 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2512 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2513 CGM.Int32Ty, 2514 CGM.VoidPtrPtrTy, 2515 CGM.VoidPtrPtrTy, 2516 CGM.Int64Ty->getPointerTo(), 2517 CGM.Int64Ty->getPointerTo()}; 2518 auto *FnTy = 2519 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2520 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2521 break; 2522 } 2523 case OMPRTL__tgt_target_data_end_nowait: { 2524 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2525 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2526 // *arg_types); 2527 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2528 CGM.Int32Ty, 2529 CGM.VoidPtrPtrTy, 2530 CGM.VoidPtrPtrTy, 2531 CGM.Int64Ty->getPointerTo(), 2532 CGM.Int64Ty->getPointerTo()}; 2533 auto *FnTy = 2534 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2535 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2536 break; 2537 } 2538 case OMPRTL__tgt_target_data_update: { 2539 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2540 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2541 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2542 CGM.Int32Ty, 2543 CGM.VoidPtrPtrTy, 2544 CGM.VoidPtrPtrTy, 2545 CGM.Int64Ty->getPointerTo(), 2546 CGM.Int64Ty->getPointerTo()}; 2547 auto *FnTy = 2548 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2549 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2550 break; 2551 } 2552 case OMPRTL__tgt_target_data_update_nowait: { 2553 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2554 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2555 // *arg_types); 2556 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2557 CGM.Int32Ty, 2558 CGM.VoidPtrPtrTy, 2559 CGM.VoidPtrPtrTy, 2560 CGM.Int64Ty->getPointerTo(), 2561 CGM.Int64Ty->getPointerTo()}; 2562 auto *FnTy = 2563 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2564 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2565 break; 2566 } 2567 case OMPRTL__tgt_mapper_num_components: { 2568 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2569 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2570 auto *FnTy = 2571 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2572 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2573 break; 2574 } 2575 case OMPRTL__tgt_push_mapper_component: { 2576 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2577 // *base, void *begin, int64_t size, int64_t type); 2578 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2579 CGM.Int64Ty, CGM.Int64Ty}; 2580 auto *FnTy = 2581 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2582 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2583 break; 2584 } 2585 } 2586 assert(RTLFn && "Unable to find OpenMP runtime function"); 2587 return RTLFn; 2588 } 2589 2590 llvm::FunctionCallee 2591 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2592 assert((IVSize == 32 || IVSize == 64) && 2593 "IV size is not compatible with the omp runtime"); 2594 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2595 : "__kmpc_for_static_init_4u") 2596 : (IVSigned ? "__kmpc_for_static_init_8" 2597 : "__kmpc_for_static_init_8u"); 2598 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2599 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2600 llvm::Type *TypeParams[] = { 2601 getIdentTyPointerTy(), // loc 2602 CGM.Int32Ty, // tid 2603 CGM.Int32Ty, // schedtype 2604 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2605 PtrTy, // p_lower 2606 PtrTy, // p_upper 2607 PtrTy, // p_stride 2608 ITy, // incr 2609 ITy // chunk 2610 }; 2611 auto *FnTy = 2612 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2613 return CGM.CreateRuntimeFunction(FnTy, Name); 2614 } 2615 2616 llvm::FunctionCallee 2617 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2618 assert((IVSize == 32 || IVSize == 64) && 2619 "IV size is not compatible with the omp runtime"); 2620 StringRef Name = 2621 IVSize == 32 2622 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2623 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2624 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2625 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2626 CGM.Int32Ty, // tid 2627 CGM.Int32Ty, // schedtype 2628 ITy, // lower 2629 ITy, // upper 2630 ITy, // stride 2631 ITy // chunk 2632 }; 2633 auto *FnTy = 2634 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2635 return CGM.CreateRuntimeFunction(FnTy, Name); 2636 } 2637 2638 llvm::FunctionCallee 2639 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2640 assert((IVSize == 32 || IVSize == 64) && 2641 "IV size is not compatible with the omp runtime"); 2642 StringRef Name = 2643 IVSize == 32 2644 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2645 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2646 llvm::Type *TypeParams[] = { 2647 getIdentTyPointerTy(), // loc 2648 CGM.Int32Ty, // tid 2649 }; 2650 auto *FnTy = 2651 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2652 return CGM.CreateRuntimeFunction(FnTy, Name); 2653 } 2654 2655 llvm::FunctionCallee 2656 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2657 assert((IVSize == 32 || IVSize == 64) && 2658 "IV size is not compatible with the omp runtime"); 2659 StringRef Name = 2660 IVSize == 32 2661 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2662 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2663 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2664 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2665 llvm::Type *TypeParams[] = { 2666 getIdentTyPointerTy(), // loc 2667 CGM.Int32Ty, // tid 2668 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2669 PtrTy, // p_lower 2670 PtrTy, // p_upper 2671 PtrTy // p_stride 2672 }; 2673 auto *FnTy = 2674 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2675 return CGM.CreateRuntimeFunction(FnTy, Name); 2676 } 2677 2678 /// Obtain information that uniquely identifies a target entry. This 2679 /// consists of the file and device IDs as well as line number associated with 2680 /// the relevant entry source location. 2681 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2682 unsigned &DeviceID, unsigned &FileID, 2683 unsigned &LineNum) { 2684 SourceManager &SM = C.getSourceManager(); 2685 2686 // The loc should be always valid and have a file ID (the user cannot use 2687 // #pragma directives in macros) 2688 2689 assert(Loc.isValid() && "Source location is expected to be always valid."); 2690 2691 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2692 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2693 2694 llvm::sys::fs::UniqueID ID; 2695 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2696 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2697 << PLoc.getFilename() << EC.message(); 2698 2699 DeviceID = ID.getDevice(); 2700 FileID = ID.getFile(); 2701 LineNum = PLoc.getLine(); 2702 } 2703 2704 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2705 if (CGM.getLangOpts().OpenMPSimd) 2706 return Address::invalid(); 2707 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2708 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2709 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2710 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2711 HasRequiresUnifiedSharedMemory))) { 2712 SmallString<64> PtrName; 2713 { 2714 llvm::raw_svector_ostream OS(PtrName); 2715 OS << CGM.getMangledName(GlobalDecl(VD)); 2716 if (!VD->isExternallyVisible()) { 2717 unsigned DeviceID, FileID, Line; 2718 getTargetEntryUniqueInfo(CGM.getContext(), 2719 VD->getCanonicalDecl()->getBeginLoc(), 2720 DeviceID, FileID, Line); 2721 OS << llvm::format("_%x", FileID); 2722 } 2723 OS << "_decl_tgt_ref_ptr"; 2724 } 2725 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2726 if (!Ptr) { 2727 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2728 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2729 PtrName); 2730 2731 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2732 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2733 2734 if (!CGM.getLangOpts().OpenMPIsDevice) 2735 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2736 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2737 } 2738 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2739 } 2740 return Address::invalid(); 2741 } 2742 2743 llvm::Constant * 2744 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2745 assert(!CGM.getLangOpts().OpenMPUseTLS || 2746 !CGM.getContext().getTargetInfo().isTLSSupported()); 2747 // Lookup the entry, lazily creating it if necessary. 2748 std::string Suffix = getName({"cache", ""}); 2749 return getOrCreateInternalVariable( 2750 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2751 } 2752 2753 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2754 const VarDecl *VD, 2755 Address VDAddr, 2756 SourceLocation Loc) { 2757 if (CGM.getLangOpts().OpenMPUseTLS && 2758 CGM.getContext().getTargetInfo().isTLSSupported()) 2759 return VDAddr; 2760 2761 llvm::Type *VarTy = VDAddr.getElementType(); 2762 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2763 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2764 CGM.Int8PtrTy), 2765 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2766 getOrCreateThreadPrivateCache(VD)}; 2767 return Address(CGF.EmitRuntimeCall( 2768 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2769 VDAddr.getAlignment()); 2770 } 2771 2772 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2773 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2774 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2775 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2776 // library. 2777 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2778 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2779 OMPLoc); 2780 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2781 // to register constructor/destructor for variable. 2782 llvm::Value *Args[] = { 2783 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2784 Ctor, CopyCtor, Dtor}; 2785 CGF.EmitRuntimeCall( 2786 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2787 } 2788 2789 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2790 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2791 bool PerformInit, CodeGenFunction *CGF) { 2792 if (CGM.getLangOpts().OpenMPUseTLS && 2793 CGM.getContext().getTargetInfo().isTLSSupported()) 2794 return nullptr; 2795 2796 VD = VD->getDefinition(CGM.getContext()); 2797 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2798 QualType ASTTy = VD->getType(); 2799 2800 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2801 const Expr *Init = VD->getAnyInitializer(); 2802 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2803 // Generate function that re-emits the declaration's initializer into the 2804 // threadprivate copy of the variable VD 2805 CodeGenFunction CtorCGF(CGM); 2806 FunctionArgList Args; 2807 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2808 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2809 ImplicitParamDecl::Other); 2810 Args.push_back(&Dst); 2811 2812 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2813 CGM.getContext().VoidPtrTy, Args); 2814 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2815 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2816 llvm::Function *Fn = 2817 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2818 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2819 Args, Loc, Loc); 2820 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2821 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2822 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2823 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2824 Arg = CtorCGF.Builder.CreateElementBitCast( 2825 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2826 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2827 /*IsInitializer=*/true); 2828 ArgVal = CtorCGF.EmitLoadOfScalar( 2829 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2830 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2831 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2832 CtorCGF.FinishFunction(); 2833 Ctor = Fn; 2834 } 2835 if (VD->getType().isDestructedType() != QualType::DK_none) { 2836 // Generate function that emits destructor call for the threadprivate copy 2837 // of the variable VD 2838 CodeGenFunction DtorCGF(CGM); 2839 FunctionArgList Args; 2840 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2841 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2842 ImplicitParamDecl::Other); 2843 Args.push_back(&Dst); 2844 2845 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2846 CGM.getContext().VoidTy, Args); 2847 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2848 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2849 llvm::Function *Fn = 2850 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2851 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2852 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2853 Loc, Loc); 2854 // Create a scope with an artificial location for the body of this function. 2855 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2856 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2857 DtorCGF.GetAddrOfLocalVar(&Dst), 2858 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2859 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2860 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2861 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2862 DtorCGF.FinishFunction(); 2863 Dtor = Fn; 2864 } 2865 // Do not emit init function if it is not required. 2866 if (!Ctor && !Dtor) 2867 return nullptr; 2868 2869 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2870 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2871 /*isVarArg=*/false) 2872 ->getPointerTo(); 2873 // Copying constructor for the threadprivate variable. 2874 // Must be NULL - reserved by runtime, but currently it requires that this 2875 // parameter is always NULL. Otherwise it fires assertion. 2876 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2877 if (Ctor == nullptr) { 2878 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2879 /*isVarArg=*/false) 2880 ->getPointerTo(); 2881 Ctor = llvm::Constant::getNullValue(CtorTy); 2882 } 2883 if (Dtor == nullptr) { 2884 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2885 /*isVarArg=*/false) 2886 ->getPointerTo(); 2887 Dtor = llvm::Constant::getNullValue(DtorTy); 2888 } 2889 if (!CGF) { 2890 auto *InitFunctionTy = 2891 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2892 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2893 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2894 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2895 CodeGenFunction InitCGF(CGM); 2896 FunctionArgList ArgList; 2897 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2898 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2899 Loc, Loc); 2900 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2901 InitCGF.FinishFunction(); 2902 return InitFunction; 2903 } 2904 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2905 } 2906 return nullptr; 2907 } 2908 2909 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2910 llvm::GlobalVariable *Addr, 2911 bool PerformInit) { 2912 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2913 !CGM.getLangOpts().OpenMPIsDevice) 2914 return false; 2915 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2916 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2917 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2918 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2919 HasRequiresUnifiedSharedMemory)) 2920 return CGM.getLangOpts().OpenMPIsDevice; 2921 VD = VD->getDefinition(CGM.getContext()); 2922 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2923 return CGM.getLangOpts().OpenMPIsDevice; 2924 2925 QualType ASTTy = VD->getType(); 2926 2927 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2928 // Produce the unique prefix to identify the new target regions. We use 2929 // the source location of the variable declaration which we know to not 2930 // conflict with any target region. 2931 unsigned DeviceID; 2932 unsigned FileID; 2933 unsigned Line; 2934 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2935 SmallString<128> Buffer, Out; 2936 { 2937 llvm::raw_svector_ostream OS(Buffer); 2938 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2939 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2940 } 2941 2942 const Expr *Init = VD->getAnyInitializer(); 2943 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2944 llvm::Constant *Ctor; 2945 llvm::Constant *ID; 2946 if (CGM.getLangOpts().OpenMPIsDevice) { 2947 // Generate function that re-emits the declaration's initializer into 2948 // the threadprivate copy of the variable VD 2949 CodeGenFunction CtorCGF(CGM); 2950 2951 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2952 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2953 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2954 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2955 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2956 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2957 FunctionArgList(), Loc, Loc); 2958 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2959 CtorCGF.EmitAnyExprToMem(Init, 2960 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2961 Init->getType().getQualifiers(), 2962 /*IsInitializer=*/true); 2963 CtorCGF.FinishFunction(); 2964 Ctor = Fn; 2965 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2966 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2967 } else { 2968 Ctor = new llvm::GlobalVariable( 2969 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2970 llvm::GlobalValue::PrivateLinkage, 2971 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2972 ID = Ctor; 2973 } 2974 2975 // Register the information for the entry associated with the constructor. 2976 Out.clear(); 2977 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2978 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2979 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2980 } 2981 if (VD->getType().isDestructedType() != QualType::DK_none) { 2982 llvm::Constant *Dtor; 2983 llvm::Constant *ID; 2984 if (CGM.getLangOpts().OpenMPIsDevice) { 2985 // Generate function that emits destructor call for the threadprivate 2986 // copy of the variable VD 2987 CodeGenFunction DtorCGF(CGM); 2988 2989 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2990 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2991 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2992 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2993 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2994 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2995 FunctionArgList(), Loc, Loc); 2996 // Create a scope with an artificial location for the body of this 2997 // function. 2998 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2999 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 3000 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 3001 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 3002 DtorCGF.FinishFunction(); 3003 Dtor = Fn; 3004 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 3005 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 3006 } else { 3007 Dtor = new llvm::GlobalVariable( 3008 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 3009 llvm::GlobalValue::PrivateLinkage, 3010 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 3011 ID = Dtor; 3012 } 3013 // Register the information for the entry associated with the destructor. 3014 Out.clear(); 3015 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 3016 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 3017 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 3018 } 3019 return CGM.getLangOpts().OpenMPIsDevice; 3020 } 3021 3022 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 3023 QualType VarType, 3024 StringRef Name) { 3025 std::string Suffix = getName({"artificial", ""}); 3026 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 3027 llvm::Value *GAddr = 3028 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 3029 if (CGM.getLangOpts().OpenMP && CGM.getLangOpts().OpenMPUseTLS && 3030 CGM.getTarget().isTLSSupported()) { 3031 cast<llvm::GlobalVariable>(GAddr)->setThreadLocal(/*Val=*/true); 3032 return Address(GAddr, CGM.getContext().getTypeAlignInChars(VarType)); 3033 } 3034 std::string CacheSuffix = getName({"cache", ""}); 3035 llvm::Value *Args[] = { 3036 emitUpdateLocation(CGF, SourceLocation()), 3037 getThreadID(CGF, SourceLocation()), 3038 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 3039 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 3040 /*isSigned=*/false), 3041 getOrCreateInternalVariable( 3042 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 3043 return Address( 3044 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3045 CGF.EmitRuntimeCall( 3046 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3047 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3048 CGM.getContext().getTypeAlignInChars(VarType)); 3049 } 3050 3051 void CGOpenMPRuntime::emitIfClause(CodeGenFunction &CGF, const Expr *Cond, 3052 const RegionCodeGenTy &ThenGen, 3053 const RegionCodeGenTy &ElseGen) { 3054 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3055 3056 // If the condition constant folds and can be elided, try to avoid emitting 3057 // the condition and the dead arm of the if/else. 3058 bool CondConstant; 3059 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3060 if (CondConstant) 3061 ThenGen(CGF); 3062 else 3063 ElseGen(CGF); 3064 return; 3065 } 3066 3067 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3068 // emit the conditional branch. 3069 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3070 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3071 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3072 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3073 3074 // Emit the 'then' code. 3075 CGF.EmitBlock(ThenBlock); 3076 ThenGen(CGF); 3077 CGF.EmitBranch(ContBlock); 3078 // Emit the 'else' code if present. 3079 // There is no need to emit line number for unconditional branch. 3080 (void)ApplyDebugLocation::CreateEmpty(CGF); 3081 CGF.EmitBlock(ElseBlock); 3082 ElseGen(CGF); 3083 // There is no need to emit line number for unconditional branch. 3084 (void)ApplyDebugLocation::CreateEmpty(CGF); 3085 CGF.EmitBranch(ContBlock); 3086 // Emit the continuation block for code after the if. 3087 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3088 } 3089 3090 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3091 llvm::Function *OutlinedFn, 3092 ArrayRef<llvm::Value *> CapturedVars, 3093 const Expr *IfCond) { 3094 if (!CGF.HaveInsertPoint()) 3095 return; 3096 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3097 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3098 PrePostActionTy &) { 3099 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3100 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3101 llvm::Value *Args[] = { 3102 RTLoc, 3103 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3104 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3105 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3106 RealArgs.append(std::begin(Args), std::end(Args)); 3107 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3108 3109 llvm::FunctionCallee RTLFn = 3110 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3111 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3112 }; 3113 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3114 PrePostActionTy &) { 3115 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3116 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3117 // Build calls: 3118 // __kmpc_serialized_parallel(&Loc, GTid); 3119 llvm::Value *Args[] = {RTLoc, ThreadID}; 3120 CGF.EmitRuntimeCall( 3121 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3122 3123 // OutlinedFn(>id, &zero_bound, CapturedStruct); 3124 Address ThreadIDAddr = RT.emitThreadIDAddress(CGF, Loc); 3125 Address ZeroAddrBound = 3126 CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3127 /*Name=*/".bound.zero.addr"); 3128 CGF.InitTempAlloca(ZeroAddrBound, CGF.Builder.getInt32(/*C*/ 0)); 3129 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3130 // ThreadId for serialized parallels is 0. 3131 OutlinedFnArgs.push_back(ThreadIDAddr.getPointer()); 3132 OutlinedFnArgs.push_back(ZeroAddrBound.getPointer()); 3133 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3134 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3135 3136 // __kmpc_end_serialized_parallel(&Loc, GTid); 3137 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3138 CGF.EmitRuntimeCall( 3139 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3140 EndArgs); 3141 }; 3142 if (IfCond) { 3143 emitIfClause(CGF, IfCond, ThenGen, ElseGen); 3144 } else { 3145 RegionCodeGenTy ThenRCG(ThenGen); 3146 ThenRCG(CGF); 3147 } 3148 } 3149 3150 // If we're inside an (outlined) parallel region, use the region info's 3151 // thread-ID variable (it is passed in a first argument of the outlined function 3152 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3153 // regular serial code region, get thread ID by calling kmp_int32 3154 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3155 // return the address of that temp. 3156 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3157 SourceLocation Loc) { 3158 if (auto *OMPRegionInfo = 3159 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3160 if (OMPRegionInfo->getThreadIDVariable()) 3161 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(CGF); 3162 3163 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3164 QualType Int32Ty = 3165 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3166 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3167 CGF.EmitStoreOfScalar(ThreadID, 3168 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3169 3170 return ThreadIDTemp; 3171 } 3172 3173 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3174 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3175 SmallString<256> Buffer; 3176 llvm::raw_svector_ostream Out(Buffer); 3177 Out << Name; 3178 StringRef RuntimeName = Out.str(); 3179 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3180 if (Elem.second) { 3181 assert(Elem.second->getType()->getPointerElementType() == Ty && 3182 "OMP internal variable has different type than requested"); 3183 return &*Elem.second; 3184 } 3185 3186 return Elem.second = new llvm::GlobalVariable( 3187 CGM.getModule(), Ty, /*IsConstant*/ false, 3188 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3189 Elem.first(), /*InsertBefore=*/nullptr, 3190 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3191 } 3192 3193 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3194 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3195 std::string Name = getName({Prefix, "var"}); 3196 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3197 } 3198 3199 namespace { 3200 /// Common pre(post)-action for different OpenMP constructs. 3201 class CommonActionTy final : public PrePostActionTy { 3202 llvm::FunctionCallee EnterCallee; 3203 ArrayRef<llvm::Value *> EnterArgs; 3204 llvm::FunctionCallee ExitCallee; 3205 ArrayRef<llvm::Value *> ExitArgs; 3206 bool Conditional; 3207 llvm::BasicBlock *ContBlock = nullptr; 3208 3209 public: 3210 CommonActionTy(llvm::FunctionCallee EnterCallee, 3211 ArrayRef<llvm::Value *> EnterArgs, 3212 llvm::FunctionCallee ExitCallee, 3213 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3214 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3215 ExitArgs(ExitArgs), Conditional(Conditional) {} 3216 void Enter(CodeGenFunction &CGF) override { 3217 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3218 if (Conditional) { 3219 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3220 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3221 ContBlock = CGF.createBasicBlock("omp_if.end"); 3222 // Generate the branch (If-stmt) 3223 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3224 CGF.EmitBlock(ThenBlock); 3225 } 3226 } 3227 void Done(CodeGenFunction &CGF) { 3228 // Emit the rest of blocks/branches 3229 CGF.EmitBranch(ContBlock); 3230 CGF.EmitBlock(ContBlock, true); 3231 } 3232 void Exit(CodeGenFunction &CGF) override { 3233 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3234 } 3235 }; 3236 } // anonymous namespace 3237 3238 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3239 StringRef CriticalName, 3240 const RegionCodeGenTy &CriticalOpGen, 3241 SourceLocation Loc, const Expr *Hint) { 3242 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3243 // CriticalOpGen(); 3244 // __kmpc_end_critical(ident_t *, gtid, Lock); 3245 // Prepare arguments and build a call to __kmpc_critical 3246 if (!CGF.HaveInsertPoint()) 3247 return; 3248 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3249 getCriticalRegionLock(CriticalName)}; 3250 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3251 std::end(Args)); 3252 if (Hint) { 3253 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3254 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3255 } 3256 CommonActionTy Action( 3257 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3258 : OMPRTL__kmpc_critical), 3259 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3260 CriticalOpGen.setAction(Action); 3261 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3262 } 3263 3264 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3265 const RegionCodeGenTy &MasterOpGen, 3266 SourceLocation Loc) { 3267 if (!CGF.HaveInsertPoint()) 3268 return; 3269 // if(__kmpc_master(ident_t *, gtid)) { 3270 // MasterOpGen(); 3271 // __kmpc_end_master(ident_t *, gtid); 3272 // } 3273 // Prepare arguments and build a call to __kmpc_master 3274 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3275 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3276 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3277 /*Conditional=*/true); 3278 MasterOpGen.setAction(Action); 3279 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3280 Action.Done(CGF); 3281 } 3282 3283 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3284 SourceLocation Loc) { 3285 if (!CGF.HaveInsertPoint()) 3286 return; 3287 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3288 llvm::Value *Args[] = { 3289 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3290 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3291 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3292 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3293 Region->emitUntiedSwitch(CGF); 3294 } 3295 3296 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3297 const RegionCodeGenTy &TaskgroupOpGen, 3298 SourceLocation Loc) { 3299 if (!CGF.HaveInsertPoint()) 3300 return; 3301 // __kmpc_taskgroup(ident_t *, gtid); 3302 // TaskgroupOpGen(); 3303 // __kmpc_end_taskgroup(ident_t *, gtid); 3304 // Prepare arguments and build a call to __kmpc_taskgroup 3305 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3306 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3307 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3308 Args); 3309 TaskgroupOpGen.setAction(Action); 3310 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3311 } 3312 3313 /// Given an array of pointers to variables, project the address of a 3314 /// given variable. 3315 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3316 unsigned Index, const VarDecl *Var) { 3317 // Pull out the pointer to the variable. 3318 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3319 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3320 3321 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3322 Addr = CGF.Builder.CreateElementBitCast( 3323 Addr, CGF.ConvertTypeForMem(Var->getType())); 3324 return Addr; 3325 } 3326 3327 static llvm::Value *emitCopyprivateCopyFunction( 3328 CodeGenModule &CGM, llvm::Type *ArgsType, 3329 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3330 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3331 SourceLocation Loc) { 3332 ASTContext &C = CGM.getContext(); 3333 // void copy_func(void *LHSArg, void *RHSArg); 3334 FunctionArgList Args; 3335 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3336 ImplicitParamDecl::Other); 3337 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3338 ImplicitParamDecl::Other); 3339 Args.push_back(&LHSArg); 3340 Args.push_back(&RHSArg); 3341 const auto &CGFI = 3342 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3343 std::string Name = 3344 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3345 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3346 llvm::GlobalValue::InternalLinkage, Name, 3347 &CGM.getModule()); 3348 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3349 Fn->setDoesNotRecurse(); 3350 CodeGenFunction CGF(CGM); 3351 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3352 // Dest = (void*[n])(LHSArg); 3353 // Src = (void*[n])(RHSArg); 3354 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3355 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3356 ArgsType), CGF.getPointerAlign()); 3357 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3358 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3359 ArgsType), CGF.getPointerAlign()); 3360 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3361 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3362 // ... 3363 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3364 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3365 const auto *DestVar = 3366 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3367 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3368 3369 const auto *SrcVar = 3370 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3371 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3372 3373 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3374 QualType Type = VD->getType(); 3375 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3376 } 3377 CGF.FinishFunction(); 3378 return Fn; 3379 } 3380 3381 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3382 const RegionCodeGenTy &SingleOpGen, 3383 SourceLocation Loc, 3384 ArrayRef<const Expr *> CopyprivateVars, 3385 ArrayRef<const Expr *> SrcExprs, 3386 ArrayRef<const Expr *> DstExprs, 3387 ArrayRef<const Expr *> AssignmentOps) { 3388 if (!CGF.HaveInsertPoint()) 3389 return; 3390 assert(CopyprivateVars.size() == SrcExprs.size() && 3391 CopyprivateVars.size() == DstExprs.size() && 3392 CopyprivateVars.size() == AssignmentOps.size()); 3393 ASTContext &C = CGM.getContext(); 3394 // int32 did_it = 0; 3395 // if(__kmpc_single(ident_t *, gtid)) { 3396 // SingleOpGen(); 3397 // __kmpc_end_single(ident_t *, gtid); 3398 // did_it = 1; 3399 // } 3400 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3401 // <copy_func>, did_it); 3402 3403 Address DidIt = Address::invalid(); 3404 if (!CopyprivateVars.empty()) { 3405 // int32 did_it = 0; 3406 QualType KmpInt32Ty = 3407 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3408 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3409 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3410 } 3411 // Prepare arguments and build a call to __kmpc_single 3412 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3413 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3414 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3415 /*Conditional=*/true); 3416 SingleOpGen.setAction(Action); 3417 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3418 if (DidIt.isValid()) { 3419 // did_it = 1; 3420 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3421 } 3422 Action.Done(CGF); 3423 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3424 // <copy_func>, did_it); 3425 if (DidIt.isValid()) { 3426 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3427 QualType CopyprivateArrayTy = C.getConstantArrayType( 3428 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3429 /*IndexTypeQuals=*/0); 3430 // Create a list of all private variables for copyprivate. 3431 Address CopyprivateList = 3432 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3433 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3434 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3435 CGF.Builder.CreateStore( 3436 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3437 CGF.EmitLValue(CopyprivateVars[I]).getPointer(CGF), 3438 CGF.VoidPtrTy), 3439 Elem); 3440 } 3441 // Build function that copies private values from single region to all other 3442 // threads in the corresponding parallel region. 3443 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3444 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3445 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3446 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3447 Address CL = 3448 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3449 CGF.VoidPtrTy); 3450 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3451 llvm::Value *Args[] = { 3452 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3453 getThreadID(CGF, Loc), // i32 <gtid> 3454 BufSize, // size_t <buf_size> 3455 CL.getPointer(), // void *<copyprivate list> 3456 CpyFn, // void (*) (void *, void *) <copy_func> 3457 DidItVal // i32 did_it 3458 }; 3459 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3460 } 3461 } 3462 3463 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3464 const RegionCodeGenTy &OrderedOpGen, 3465 SourceLocation Loc, bool IsThreads) { 3466 if (!CGF.HaveInsertPoint()) 3467 return; 3468 // __kmpc_ordered(ident_t *, gtid); 3469 // OrderedOpGen(); 3470 // __kmpc_end_ordered(ident_t *, gtid); 3471 // Prepare arguments and build a call to __kmpc_ordered 3472 if (IsThreads) { 3473 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3474 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3475 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3476 Args); 3477 OrderedOpGen.setAction(Action); 3478 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3479 return; 3480 } 3481 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3482 } 3483 3484 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3485 unsigned Flags; 3486 if (Kind == OMPD_for) 3487 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3488 else if (Kind == OMPD_sections) 3489 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3490 else if (Kind == OMPD_single) 3491 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3492 else if (Kind == OMPD_barrier) 3493 Flags = OMP_IDENT_BARRIER_EXPL; 3494 else 3495 Flags = OMP_IDENT_BARRIER_IMPL; 3496 return Flags; 3497 } 3498 3499 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3500 CodeGenFunction &CGF, const OMPLoopDirective &S, 3501 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3502 // Check if the loop directive is actually a doacross loop directive. In this 3503 // case choose static, 1 schedule. 3504 if (llvm::any_of( 3505 S.getClausesOfKind<OMPOrderedClause>(), 3506 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3507 ScheduleKind = OMPC_SCHEDULE_static; 3508 // Chunk size is 1 in this case. 3509 llvm::APInt ChunkSize(32, 1); 3510 ChunkExpr = IntegerLiteral::Create( 3511 CGF.getContext(), ChunkSize, 3512 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3513 SourceLocation()); 3514 } 3515 } 3516 3517 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3518 OpenMPDirectiveKind Kind, bool EmitChecks, 3519 bool ForceSimpleCall) { 3520 // Check if we should use the OMPBuilder 3521 auto *OMPRegionInfo = 3522 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo); 3523 llvm::OpenMPIRBuilder *OMPBuilder = CGF.CGM.getOpenMPIRBuilder(); 3524 if (OMPBuilder) { 3525 CGF.Builder.restoreIP(OMPBuilder->CreateBarrier( 3526 CGF.Builder, Kind, ForceSimpleCall, EmitChecks)); 3527 return; 3528 } 3529 3530 if (!CGF.HaveInsertPoint()) 3531 return; 3532 // Build call __kmpc_cancel_barrier(loc, thread_id); 3533 // Build call __kmpc_barrier(loc, thread_id); 3534 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3535 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3536 // thread_id); 3537 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3538 getThreadID(CGF, Loc)}; 3539 if (OMPRegionInfo) { 3540 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3541 llvm::Value *Result = CGF.EmitRuntimeCall( 3542 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3543 if (EmitChecks) { 3544 // if (__kmpc_cancel_barrier()) { 3545 // exit from construct; 3546 // } 3547 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3548 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3549 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3550 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3551 CGF.EmitBlock(ExitBB); 3552 // exit from construct; 3553 CodeGenFunction::JumpDest CancelDestination = 3554 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3555 CGF.EmitBranchThroughCleanup(CancelDestination); 3556 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3557 } 3558 return; 3559 } 3560 } 3561 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3562 } 3563 3564 /// Map the OpenMP loop schedule to the runtime enumeration. 3565 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3566 bool Chunked, bool Ordered) { 3567 switch (ScheduleKind) { 3568 case OMPC_SCHEDULE_static: 3569 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3570 : (Ordered ? OMP_ord_static : OMP_sch_static); 3571 case OMPC_SCHEDULE_dynamic: 3572 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3573 case OMPC_SCHEDULE_guided: 3574 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3575 case OMPC_SCHEDULE_runtime: 3576 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3577 case OMPC_SCHEDULE_auto: 3578 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3579 case OMPC_SCHEDULE_unknown: 3580 assert(!Chunked && "chunk was specified but schedule kind not known"); 3581 return Ordered ? OMP_ord_static : OMP_sch_static; 3582 } 3583 llvm_unreachable("Unexpected runtime schedule"); 3584 } 3585 3586 /// Map the OpenMP distribute schedule to the runtime enumeration. 3587 static OpenMPSchedType 3588 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3589 // only static is allowed for dist_schedule 3590 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3591 } 3592 3593 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3594 bool Chunked) const { 3595 OpenMPSchedType Schedule = 3596 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3597 return Schedule == OMP_sch_static; 3598 } 3599 3600 bool CGOpenMPRuntime::isStaticNonchunked( 3601 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3602 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3603 return Schedule == OMP_dist_sch_static; 3604 } 3605 3606 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3607 bool Chunked) const { 3608 OpenMPSchedType Schedule = 3609 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3610 return Schedule == OMP_sch_static_chunked; 3611 } 3612 3613 bool CGOpenMPRuntime::isStaticChunked( 3614 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3615 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3616 return Schedule == OMP_dist_sch_static_chunked; 3617 } 3618 3619 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3620 OpenMPSchedType Schedule = 3621 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3622 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3623 return Schedule != OMP_sch_static; 3624 } 3625 3626 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3627 OpenMPScheduleClauseModifier M1, 3628 OpenMPScheduleClauseModifier M2) { 3629 int Modifier = 0; 3630 switch (M1) { 3631 case OMPC_SCHEDULE_MODIFIER_monotonic: 3632 Modifier = OMP_sch_modifier_monotonic; 3633 break; 3634 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3635 Modifier = OMP_sch_modifier_nonmonotonic; 3636 break; 3637 case OMPC_SCHEDULE_MODIFIER_simd: 3638 if (Schedule == OMP_sch_static_chunked) 3639 Schedule = OMP_sch_static_balanced_chunked; 3640 break; 3641 case OMPC_SCHEDULE_MODIFIER_last: 3642 case OMPC_SCHEDULE_MODIFIER_unknown: 3643 break; 3644 } 3645 switch (M2) { 3646 case OMPC_SCHEDULE_MODIFIER_monotonic: 3647 Modifier = OMP_sch_modifier_monotonic; 3648 break; 3649 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3650 Modifier = OMP_sch_modifier_nonmonotonic; 3651 break; 3652 case OMPC_SCHEDULE_MODIFIER_simd: 3653 if (Schedule == OMP_sch_static_chunked) 3654 Schedule = OMP_sch_static_balanced_chunked; 3655 break; 3656 case OMPC_SCHEDULE_MODIFIER_last: 3657 case OMPC_SCHEDULE_MODIFIER_unknown: 3658 break; 3659 } 3660 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3661 // If the static schedule kind is specified or if the ordered clause is 3662 // specified, and if the nonmonotonic modifier is not specified, the effect is 3663 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3664 // modifier is specified, the effect is as if the nonmonotonic modifier is 3665 // specified. 3666 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3667 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3668 Schedule == OMP_sch_static_balanced_chunked || 3669 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static || 3670 Schedule == OMP_dist_sch_static_chunked || 3671 Schedule == OMP_dist_sch_static)) 3672 Modifier = OMP_sch_modifier_nonmonotonic; 3673 } 3674 return Schedule | Modifier; 3675 } 3676 3677 void CGOpenMPRuntime::emitForDispatchInit( 3678 CodeGenFunction &CGF, SourceLocation Loc, 3679 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3680 bool Ordered, const DispatchRTInput &DispatchValues) { 3681 if (!CGF.HaveInsertPoint()) 3682 return; 3683 OpenMPSchedType Schedule = getRuntimeSchedule( 3684 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3685 assert(Ordered || 3686 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3687 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3688 Schedule != OMP_sch_static_balanced_chunked)); 3689 // Call __kmpc_dispatch_init( 3690 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3691 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3692 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3693 3694 // If the Chunk was not specified in the clause - use default value 1. 3695 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3696 : CGF.Builder.getIntN(IVSize, 1); 3697 llvm::Value *Args[] = { 3698 emitUpdateLocation(CGF, Loc), 3699 getThreadID(CGF, Loc), 3700 CGF.Builder.getInt32(addMonoNonMonoModifier( 3701 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3702 DispatchValues.LB, // Lower 3703 DispatchValues.UB, // Upper 3704 CGF.Builder.getIntN(IVSize, 1), // Stride 3705 Chunk // Chunk 3706 }; 3707 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3708 } 3709 3710 static void emitForStaticInitCall( 3711 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3712 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3713 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3714 const CGOpenMPRuntime::StaticRTInput &Values) { 3715 if (!CGF.HaveInsertPoint()) 3716 return; 3717 3718 assert(!Values.Ordered); 3719 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3720 Schedule == OMP_sch_static_balanced_chunked || 3721 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3722 Schedule == OMP_dist_sch_static || 3723 Schedule == OMP_dist_sch_static_chunked); 3724 3725 // Call __kmpc_for_static_init( 3726 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3727 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3728 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3729 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3730 llvm::Value *Chunk = Values.Chunk; 3731 if (Chunk == nullptr) { 3732 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3733 Schedule == OMP_dist_sch_static) && 3734 "expected static non-chunked schedule"); 3735 // If the Chunk was not specified in the clause - use default value 1. 3736 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3737 } else { 3738 assert((Schedule == OMP_sch_static_chunked || 3739 Schedule == OMP_sch_static_balanced_chunked || 3740 Schedule == OMP_ord_static_chunked || 3741 Schedule == OMP_dist_sch_static_chunked) && 3742 "expected static chunked schedule"); 3743 } 3744 llvm::Value *Args[] = { 3745 UpdateLocation, 3746 ThreadId, 3747 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3748 M2)), // Schedule type 3749 Values.IL.getPointer(), // &isLastIter 3750 Values.LB.getPointer(), // &LB 3751 Values.UB.getPointer(), // &UB 3752 Values.ST.getPointer(), // &Stride 3753 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3754 Chunk // Chunk 3755 }; 3756 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3757 } 3758 3759 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3760 SourceLocation Loc, 3761 OpenMPDirectiveKind DKind, 3762 const OpenMPScheduleTy &ScheduleKind, 3763 const StaticRTInput &Values) { 3764 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3765 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3766 assert(isOpenMPWorksharingDirective(DKind) && 3767 "Expected loop-based or sections-based directive."); 3768 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3769 isOpenMPLoopDirective(DKind) 3770 ? OMP_IDENT_WORK_LOOP 3771 : OMP_IDENT_WORK_SECTIONS); 3772 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3773 llvm::FunctionCallee StaticInitFunction = 3774 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3775 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3776 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3777 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3778 } 3779 3780 void CGOpenMPRuntime::emitDistributeStaticInit( 3781 CodeGenFunction &CGF, SourceLocation Loc, 3782 OpenMPDistScheduleClauseKind SchedKind, 3783 const CGOpenMPRuntime::StaticRTInput &Values) { 3784 OpenMPSchedType ScheduleNum = 3785 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3786 llvm::Value *UpdatedLocation = 3787 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3788 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3789 llvm::FunctionCallee StaticInitFunction = 3790 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3791 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3792 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3793 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3794 } 3795 3796 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3797 SourceLocation Loc, 3798 OpenMPDirectiveKind DKind) { 3799 if (!CGF.HaveInsertPoint()) 3800 return; 3801 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3802 llvm::Value *Args[] = { 3803 emitUpdateLocation(CGF, Loc, 3804 isOpenMPDistributeDirective(DKind) 3805 ? OMP_IDENT_WORK_DISTRIBUTE 3806 : isOpenMPLoopDirective(DKind) 3807 ? OMP_IDENT_WORK_LOOP 3808 : OMP_IDENT_WORK_SECTIONS), 3809 getThreadID(CGF, Loc)}; 3810 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 3811 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3812 Args); 3813 } 3814 3815 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3816 SourceLocation Loc, 3817 unsigned IVSize, 3818 bool IVSigned) { 3819 if (!CGF.HaveInsertPoint()) 3820 return; 3821 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3822 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3823 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3824 } 3825 3826 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3827 SourceLocation Loc, unsigned IVSize, 3828 bool IVSigned, Address IL, 3829 Address LB, Address UB, 3830 Address ST) { 3831 // Call __kmpc_dispatch_next( 3832 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3833 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3834 // kmp_int[32|64] *p_stride); 3835 llvm::Value *Args[] = { 3836 emitUpdateLocation(CGF, Loc), 3837 getThreadID(CGF, Loc), 3838 IL.getPointer(), // &isLastIter 3839 LB.getPointer(), // &Lower 3840 UB.getPointer(), // &Upper 3841 ST.getPointer() // &Stride 3842 }; 3843 llvm::Value *Call = 3844 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3845 return CGF.EmitScalarConversion( 3846 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3847 CGF.getContext().BoolTy, Loc); 3848 } 3849 3850 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3851 llvm::Value *NumThreads, 3852 SourceLocation Loc) { 3853 if (!CGF.HaveInsertPoint()) 3854 return; 3855 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3856 llvm::Value *Args[] = { 3857 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3858 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3859 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3860 Args); 3861 } 3862 3863 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3864 ProcBindKind ProcBind, 3865 SourceLocation Loc) { 3866 if (!CGF.HaveInsertPoint()) 3867 return; 3868 assert(ProcBind != OMP_PROC_BIND_unknown && "Unsupported proc_bind value."); 3869 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3870 llvm::Value *Args[] = { 3871 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3872 llvm::ConstantInt::get(CGM.IntTy, unsigned(ProcBind), /*isSigned=*/true)}; 3873 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3874 } 3875 3876 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3877 SourceLocation Loc) { 3878 if (!CGF.HaveInsertPoint()) 3879 return; 3880 // Build call void __kmpc_flush(ident_t *loc) 3881 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3882 emitUpdateLocation(CGF, Loc)); 3883 } 3884 3885 namespace { 3886 /// Indexes of fields for type kmp_task_t. 3887 enum KmpTaskTFields { 3888 /// List of shared variables. 3889 KmpTaskTShareds, 3890 /// Task routine. 3891 KmpTaskTRoutine, 3892 /// Partition id for the untied tasks. 3893 KmpTaskTPartId, 3894 /// Function with call of destructors for private variables. 3895 Data1, 3896 /// Task priority. 3897 Data2, 3898 /// (Taskloops only) Lower bound. 3899 KmpTaskTLowerBound, 3900 /// (Taskloops only) Upper bound. 3901 KmpTaskTUpperBound, 3902 /// (Taskloops only) Stride. 3903 KmpTaskTStride, 3904 /// (Taskloops only) Is last iteration flag. 3905 KmpTaskTLastIter, 3906 /// (Taskloops only) Reduction data. 3907 KmpTaskTReductions, 3908 }; 3909 } // anonymous namespace 3910 3911 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3912 return OffloadEntriesTargetRegion.empty() && 3913 OffloadEntriesDeviceGlobalVar.empty(); 3914 } 3915 3916 /// Initialize target region entry. 3917 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3918 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3919 StringRef ParentName, unsigned LineNum, 3920 unsigned Order) { 3921 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3922 "only required for the device " 3923 "code generation."); 3924 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3925 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3926 OMPTargetRegionEntryTargetRegion); 3927 ++OffloadingEntriesNum; 3928 } 3929 3930 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3931 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3932 StringRef ParentName, unsigned LineNum, 3933 llvm::Constant *Addr, llvm::Constant *ID, 3934 OMPTargetRegionEntryKind Flags) { 3935 // If we are emitting code for a target, the entry is already initialized, 3936 // only has to be registered. 3937 if (CGM.getLangOpts().OpenMPIsDevice) { 3938 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3939 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3940 DiagnosticsEngine::Error, 3941 "Unable to find target region on line '%0' in the device code."); 3942 CGM.getDiags().Report(DiagID) << LineNum; 3943 return; 3944 } 3945 auto &Entry = 3946 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3947 assert(Entry.isValid() && "Entry not initialized!"); 3948 Entry.setAddress(Addr); 3949 Entry.setID(ID); 3950 Entry.setFlags(Flags); 3951 } else { 3952 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3953 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3954 ++OffloadingEntriesNum; 3955 } 3956 } 3957 3958 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3959 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3960 unsigned LineNum) const { 3961 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3962 if (PerDevice == OffloadEntriesTargetRegion.end()) 3963 return false; 3964 auto PerFile = PerDevice->second.find(FileID); 3965 if (PerFile == PerDevice->second.end()) 3966 return false; 3967 auto PerParentName = PerFile->second.find(ParentName); 3968 if (PerParentName == PerFile->second.end()) 3969 return false; 3970 auto PerLine = PerParentName->second.find(LineNum); 3971 if (PerLine == PerParentName->second.end()) 3972 return false; 3973 // Fail if this entry is already registered. 3974 if (PerLine->second.getAddress() || PerLine->second.getID()) 3975 return false; 3976 return true; 3977 } 3978 3979 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3980 const OffloadTargetRegionEntryInfoActTy &Action) { 3981 // Scan all target region entries and perform the provided action. 3982 for (const auto &D : OffloadEntriesTargetRegion) 3983 for (const auto &F : D.second) 3984 for (const auto &P : F.second) 3985 for (const auto &L : P.second) 3986 Action(D.first, F.first, P.first(), L.first, L.second); 3987 } 3988 3989 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3990 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3991 OMPTargetGlobalVarEntryKind Flags, 3992 unsigned Order) { 3993 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3994 "only required for the device " 3995 "code generation."); 3996 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3997 ++OffloadingEntriesNum; 3998 } 3999 4000 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4001 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 4002 CharUnits VarSize, 4003 OMPTargetGlobalVarEntryKind Flags, 4004 llvm::GlobalValue::LinkageTypes Linkage) { 4005 if (CGM.getLangOpts().OpenMPIsDevice) { 4006 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4007 assert(Entry.isValid() && Entry.getFlags() == Flags && 4008 "Entry not initialized!"); 4009 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4010 "Resetting with the new address."); 4011 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 4012 if (Entry.getVarSize().isZero()) { 4013 Entry.setVarSize(VarSize); 4014 Entry.setLinkage(Linkage); 4015 } 4016 return; 4017 } 4018 Entry.setVarSize(VarSize); 4019 Entry.setLinkage(Linkage); 4020 Entry.setAddress(Addr); 4021 } else { 4022 if (hasDeviceGlobalVarEntryInfo(VarName)) { 4023 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 4024 assert(Entry.isValid() && Entry.getFlags() == Flags && 4025 "Entry not initialized!"); 4026 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 4027 "Resetting with the new address."); 4028 if (Entry.getVarSize().isZero()) { 4029 Entry.setVarSize(VarSize); 4030 Entry.setLinkage(Linkage); 4031 } 4032 return; 4033 } 4034 OffloadEntriesDeviceGlobalVar.try_emplace( 4035 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 4036 ++OffloadingEntriesNum; 4037 } 4038 } 4039 4040 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4041 actOnDeviceGlobalVarEntriesInfo( 4042 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4043 // Scan all target region entries and perform the provided action. 4044 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4045 Action(E.getKey(), E.getValue()); 4046 } 4047 4048 void CGOpenMPRuntime::createOffloadEntry( 4049 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4050 llvm::GlobalValue::LinkageTypes Linkage) { 4051 StringRef Name = Addr->getName(); 4052 llvm::Module &M = CGM.getModule(); 4053 llvm::LLVMContext &C = M.getContext(); 4054 4055 // Create constant string with the name. 4056 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4057 4058 std::string StringName = getName({"omp_offloading", "entry_name"}); 4059 auto *Str = new llvm::GlobalVariable( 4060 M, StrPtrInit->getType(), /*isConstant=*/true, 4061 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4062 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4063 4064 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4065 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4066 llvm::ConstantInt::get(CGM.SizeTy, Size), 4067 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4068 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4069 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4070 llvm::GlobalVariable *Entry = createGlobalStruct( 4071 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4072 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4073 4074 // The entry has to be created in the section the linker expects it to be. 4075 Entry->setSection("omp_offloading_entries"); 4076 } 4077 4078 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4079 // Emit the offloading entries and metadata so that the device codegen side 4080 // can easily figure out what to emit. The produced metadata looks like 4081 // this: 4082 // 4083 // !omp_offload.info = !{!1, ...} 4084 // 4085 // Right now we only generate metadata for function that contain target 4086 // regions. 4087 4088 // If we are in simd mode or there are no entries, we don't need to do 4089 // anything. 4090 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4091 return; 4092 4093 llvm::Module &M = CGM.getModule(); 4094 llvm::LLVMContext &C = M.getContext(); 4095 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4096 SourceLocation, StringRef>, 4097 16> 4098 OrderedEntries(OffloadEntriesInfoManager.size()); 4099 llvm::SmallVector<StringRef, 16> ParentFunctions( 4100 OffloadEntriesInfoManager.size()); 4101 4102 // Auxiliary methods to create metadata values and strings. 4103 auto &&GetMDInt = [this](unsigned V) { 4104 return llvm::ConstantAsMetadata::get( 4105 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4106 }; 4107 4108 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4109 4110 // Create the offloading info metadata node. 4111 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4112 4113 // Create function that emits metadata for each target region entry; 4114 auto &&TargetRegionMetadataEmitter = 4115 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4116 &GetMDString]( 4117 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4118 unsigned Line, 4119 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4120 // Generate metadata for target regions. Each entry of this metadata 4121 // contains: 4122 // - Entry 0 -> Kind of this type of metadata (0). 4123 // - Entry 1 -> Device ID of the file where the entry was identified. 4124 // - Entry 2 -> File ID of the file where the entry was identified. 4125 // - Entry 3 -> Mangled name of the function where the entry was 4126 // identified. 4127 // - Entry 4 -> Line in the file where the entry was identified. 4128 // - Entry 5 -> Order the entry was created. 4129 // The first element of the metadata node is the kind. 4130 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4131 GetMDInt(FileID), GetMDString(ParentName), 4132 GetMDInt(Line), GetMDInt(E.getOrder())}; 4133 4134 SourceLocation Loc; 4135 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4136 E = CGM.getContext().getSourceManager().fileinfo_end(); 4137 I != E; ++I) { 4138 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4139 I->getFirst()->getUniqueID().getFile() == FileID) { 4140 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4141 I->getFirst(), Line, 1); 4142 break; 4143 } 4144 } 4145 // Save this entry in the right position of the ordered entries array. 4146 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4147 ParentFunctions[E.getOrder()] = ParentName; 4148 4149 // Add metadata to the named metadata node. 4150 MD->addOperand(llvm::MDNode::get(C, Ops)); 4151 }; 4152 4153 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4154 TargetRegionMetadataEmitter); 4155 4156 // Create function that emits metadata for each device global variable entry; 4157 auto &&DeviceGlobalVarMetadataEmitter = 4158 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4159 MD](StringRef MangledName, 4160 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4161 &E) { 4162 // Generate metadata for global variables. Each entry of this metadata 4163 // contains: 4164 // - Entry 0 -> Kind of this type of metadata (1). 4165 // - Entry 1 -> Mangled name of the variable. 4166 // - Entry 2 -> Declare target kind. 4167 // - Entry 3 -> Order the entry was created. 4168 // The first element of the metadata node is the kind. 4169 llvm::Metadata *Ops[] = { 4170 GetMDInt(E.getKind()), GetMDString(MangledName), 4171 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4172 4173 // Save this entry in the right position of the ordered entries array. 4174 OrderedEntries[E.getOrder()] = 4175 std::make_tuple(&E, SourceLocation(), MangledName); 4176 4177 // Add metadata to the named metadata node. 4178 MD->addOperand(llvm::MDNode::get(C, Ops)); 4179 }; 4180 4181 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4182 DeviceGlobalVarMetadataEmitter); 4183 4184 for (const auto &E : OrderedEntries) { 4185 assert(std::get<0>(E) && "All ordered entries must exist!"); 4186 if (const auto *CE = 4187 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4188 std::get<0>(E))) { 4189 if (!CE->getID() || !CE->getAddress()) { 4190 // Do not blame the entry if the parent funtion is not emitted. 4191 StringRef FnName = ParentFunctions[CE->getOrder()]; 4192 if (!CGM.GetGlobalValue(FnName)) 4193 continue; 4194 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4195 DiagnosticsEngine::Error, 4196 "Offloading entry for target region in %0 is incorrect: either the " 4197 "address or the ID is invalid."); 4198 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4199 continue; 4200 } 4201 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4202 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4203 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4204 OffloadEntryInfoDeviceGlobalVar>( 4205 std::get<0>(E))) { 4206 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4207 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4208 CE->getFlags()); 4209 switch (Flags) { 4210 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4211 if (CGM.getLangOpts().OpenMPIsDevice && 4212 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4213 continue; 4214 if (!CE->getAddress()) { 4215 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4216 DiagnosticsEngine::Error, "Offloading entry for declare target " 4217 "variable %0 is incorrect: the " 4218 "address is invalid."); 4219 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4220 continue; 4221 } 4222 // The vaiable has no definition - no need to add the entry. 4223 if (CE->getVarSize().isZero()) 4224 continue; 4225 break; 4226 } 4227 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4228 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4229 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4230 "Declaret target link address is set."); 4231 if (CGM.getLangOpts().OpenMPIsDevice) 4232 continue; 4233 if (!CE->getAddress()) { 4234 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4235 DiagnosticsEngine::Error, 4236 "Offloading entry for declare target variable is incorrect: the " 4237 "address is invalid."); 4238 CGM.getDiags().Report(DiagID); 4239 continue; 4240 } 4241 break; 4242 } 4243 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4244 CE->getVarSize().getQuantity(), Flags, 4245 CE->getLinkage()); 4246 } else { 4247 llvm_unreachable("Unsupported entry kind."); 4248 } 4249 } 4250 } 4251 4252 /// Loads all the offload entries information from the host IR 4253 /// metadata. 4254 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4255 // If we are in target mode, load the metadata from the host IR. This code has 4256 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4257 4258 if (!CGM.getLangOpts().OpenMPIsDevice) 4259 return; 4260 4261 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4262 return; 4263 4264 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4265 if (auto EC = Buf.getError()) { 4266 CGM.getDiags().Report(diag::err_cannot_open_file) 4267 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4268 return; 4269 } 4270 4271 llvm::LLVMContext C; 4272 auto ME = expectedToErrorOrAndEmitErrors( 4273 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4274 4275 if (auto EC = ME.getError()) { 4276 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4277 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4278 CGM.getDiags().Report(DiagID) 4279 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4280 return; 4281 } 4282 4283 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4284 if (!MD) 4285 return; 4286 4287 for (llvm::MDNode *MN : MD->operands()) { 4288 auto &&GetMDInt = [MN](unsigned Idx) { 4289 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4290 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4291 }; 4292 4293 auto &&GetMDString = [MN](unsigned Idx) { 4294 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4295 return V->getString(); 4296 }; 4297 4298 switch (GetMDInt(0)) { 4299 default: 4300 llvm_unreachable("Unexpected metadata!"); 4301 break; 4302 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4303 OffloadingEntryInfoTargetRegion: 4304 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4305 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4306 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4307 /*Order=*/GetMDInt(5)); 4308 break; 4309 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4310 OffloadingEntryInfoDeviceGlobalVar: 4311 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4312 /*MangledName=*/GetMDString(1), 4313 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4314 /*Flags=*/GetMDInt(2)), 4315 /*Order=*/GetMDInt(3)); 4316 break; 4317 } 4318 } 4319 } 4320 4321 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4322 if (!KmpRoutineEntryPtrTy) { 4323 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4324 ASTContext &C = CGM.getContext(); 4325 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4326 FunctionProtoType::ExtProtoInfo EPI; 4327 KmpRoutineEntryPtrQTy = C.getPointerType( 4328 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4329 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4330 } 4331 } 4332 4333 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4334 // Make sure the type of the entry is already created. This is the type we 4335 // have to create: 4336 // struct __tgt_offload_entry{ 4337 // void *addr; // Pointer to the offload entry info. 4338 // // (function or global) 4339 // char *name; // Name of the function or global. 4340 // size_t size; // Size of the entry info (0 if it a function). 4341 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4342 // int32_t reserved; // Reserved, to use by the runtime library. 4343 // }; 4344 if (TgtOffloadEntryQTy.isNull()) { 4345 ASTContext &C = CGM.getContext(); 4346 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4347 RD->startDefinition(); 4348 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4349 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4350 addFieldToRecordDecl(C, RD, C.getSizeType()); 4351 addFieldToRecordDecl( 4352 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4353 addFieldToRecordDecl( 4354 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4355 RD->completeDefinition(); 4356 RD->addAttr(PackedAttr::CreateImplicit(C)); 4357 TgtOffloadEntryQTy = C.getRecordType(RD); 4358 } 4359 return TgtOffloadEntryQTy; 4360 } 4361 4362 namespace { 4363 struct PrivateHelpersTy { 4364 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4365 const VarDecl *PrivateElemInit) 4366 : Original(Original), PrivateCopy(PrivateCopy), 4367 PrivateElemInit(PrivateElemInit) {} 4368 const VarDecl *Original; 4369 const VarDecl *PrivateCopy; 4370 const VarDecl *PrivateElemInit; 4371 }; 4372 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4373 } // anonymous namespace 4374 4375 static RecordDecl * 4376 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4377 if (!Privates.empty()) { 4378 ASTContext &C = CGM.getContext(); 4379 // Build struct .kmp_privates_t. { 4380 // /* private vars */ 4381 // }; 4382 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4383 RD->startDefinition(); 4384 for (const auto &Pair : Privates) { 4385 const VarDecl *VD = Pair.second.Original; 4386 QualType Type = VD->getType().getNonReferenceType(); 4387 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4388 if (VD->hasAttrs()) { 4389 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4390 E(VD->getAttrs().end()); 4391 I != E; ++I) 4392 FD->addAttr(*I); 4393 } 4394 } 4395 RD->completeDefinition(); 4396 return RD; 4397 } 4398 return nullptr; 4399 } 4400 4401 static RecordDecl * 4402 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4403 QualType KmpInt32Ty, 4404 QualType KmpRoutineEntryPointerQTy) { 4405 ASTContext &C = CGM.getContext(); 4406 // Build struct kmp_task_t { 4407 // void * shareds; 4408 // kmp_routine_entry_t routine; 4409 // kmp_int32 part_id; 4410 // kmp_cmplrdata_t data1; 4411 // kmp_cmplrdata_t data2; 4412 // For taskloops additional fields: 4413 // kmp_uint64 lb; 4414 // kmp_uint64 ub; 4415 // kmp_int64 st; 4416 // kmp_int32 liter; 4417 // void * reductions; 4418 // }; 4419 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4420 UD->startDefinition(); 4421 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4422 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4423 UD->completeDefinition(); 4424 QualType KmpCmplrdataTy = C.getRecordType(UD); 4425 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4426 RD->startDefinition(); 4427 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4428 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4429 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4430 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4431 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4432 if (isOpenMPTaskLoopDirective(Kind)) { 4433 QualType KmpUInt64Ty = 4434 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4435 QualType KmpInt64Ty = 4436 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4437 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4438 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4439 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4440 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4441 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4442 } 4443 RD->completeDefinition(); 4444 return RD; 4445 } 4446 4447 static RecordDecl * 4448 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4449 ArrayRef<PrivateDataTy> Privates) { 4450 ASTContext &C = CGM.getContext(); 4451 // Build struct kmp_task_t_with_privates { 4452 // kmp_task_t task_data; 4453 // .kmp_privates_t. privates; 4454 // }; 4455 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4456 RD->startDefinition(); 4457 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4458 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4459 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4460 RD->completeDefinition(); 4461 return RD; 4462 } 4463 4464 /// Emit a proxy function which accepts kmp_task_t as the second 4465 /// argument. 4466 /// \code 4467 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4468 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4469 /// For taskloops: 4470 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4471 /// tt->reductions, tt->shareds); 4472 /// return 0; 4473 /// } 4474 /// \endcode 4475 static llvm::Function * 4476 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4477 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4478 QualType KmpTaskTWithPrivatesPtrQTy, 4479 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4480 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4481 llvm::Value *TaskPrivatesMap) { 4482 ASTContext &C = CGM.getContext(); 4483 FunctionArgList Args; 4484 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4485 ImplicitParamDecl::Other); 4486 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4487 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4488 ImplicitParamDecl::Other); 4489 Args.push_back(&GtidArg); 4490 Args.push_back(&TaskTypeArg); 4491 const auto &TaskEntryFnInfo = 4492 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4493 llvm::FunctionType *TaskEntryTy = 4494 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4495 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4496 auto *TaskEntry = llvm::Function::Create( 4497 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4498 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4499 TaskEntry->setDoesNotRecurse(); 4500 CodeGenFunction CGF(CGM); 4501 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4502 Loc, Loc); 4503 4504 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4505 // tt, 4506 // For taskloops: 4507 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4508 // tt->task_data.shareds); 4509 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4510 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4511 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4512 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4513 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4514 const auto *KmpTaskTWithPrivatesQTyRD = 4515 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4516 LValue Base = 4517 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4518 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4519 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4520 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4521 llvm::Value *PartidParam = PartIdLVal.getPointer(CGF); 4522 4523 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4524 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4525 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4526 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4527 CGF.ConvertTypeForMem(SharedsPtrTy)); 4528 4529 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4530 llvm::Value *PrivatesParam; 4531 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4532 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4533 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4534 PrivatesLVal.getPointer(CGF), CGF.VoidPtrTy); 4535 } else { 4536 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4537 } 4538 4539 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4540 TaskPrivatesMap, 4541 CGF.Builder 4542 .CreatePointerBitCastOrAddrSpaceCast( 4543 TDBase.getAddress(CGF), CGF.VoidPtrTy) 4544 .getPointer()}; 4545 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4546 std::end(CommonArgs)); 4547 if (isOpenMPTaskLoopDirective(Kind)) { 4548 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4549 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4550 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4551 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4552 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4553 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4554 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4555 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4556 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4557 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4558 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4559 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4560 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4561 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4562 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4563 CallArgs.push_back(LBParam); 4564 CallArgs.push_back(UBParam); 4565 CallArgs.push_back(StParam); 4566 CallArgs.push_back(LIParam); 4567 CallArgs.push_back(RParam); 4568 } 4569 CallArgs.push_back(SharedsParam); 4570 4571 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4572 CallArgs); 4573 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4574 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4575 CGF.FinishFunction(); 4576 return TaskEntry; 4577 } 4578 4579 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4580 SourceLocation Loc, 4581 QualType KmpInt32Ty, 4582 QualType KmpTaskTWithPrivatesPtrQTy, 4583 QualType KmpTaskTWithPrivatesQTy) { 4584 ASTContext &C = CGM.getContext(); 4585 FunctionArgList Args; 4586 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4587 ImplicitParamDecl::Other); 4588 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4589 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4590 ImplicitParamDecl::Other); 4591 Args.push_back(&GtidArg); 4592 Args.push_back(&TaskTypeArg); 4593 const auto &DestructorFnInfo = 4594 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4595 llvm::FunctionType *DestructorFnTy = 4596 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4597 std::string Name = 4598 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4599 auto *DestructorFn = 4600 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4601 Name, &CGM.getModule()); 4602 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4603 DestructorFnInfo); 4604 DestructorFn->setDoesNotRecurse(); 4605 CodeGenFunction CGF(CGM); 4606 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4607 Args, Loc, Loc); 4608 4609 LValue Base = CGF.EmitLoadOfPointerLValue( 4610 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4611 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4612 const auto *KmpTaskTWithPrivatesQTyRD = 4613 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4614 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4615 Base = CGF.EmitLValueForField(Base, *FI); 4616 for (const auto *Field : 4617 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4618 if (QualType::DestructionKind DtorKind = 4619 Field->getType().isDestructedType()) { 4620 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4621 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(CGF), Field->getType()); 4622 } 4623 } 4624 CGF.FinishFunction(); 4625 return DestructorFn; 4626 } 4627 4628 /// Emit a privates mapping function for correct handling of private and 4629 /// firstprivate variables. 4630 /// \code 4631 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4632 /// **noalias priv1,..., <tyn> **noalias privn) { 4633 /// *priv1 = &.privates.priv1; 4634 /// ...; 4635 /// *privn = &.privates.privn; 4636 /// } 4637 /// \endcode 4638 static llvm::Value * 4639 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4640 ArrayRef<const Expr *> PrivateVars, 4641 ArrayRef<const Expr *> FirstprivateVars, 4642 ArrayRef<const Expr *> LastprivateVars, 4643 QualType PrivatesQTy, 4644 ArrayRef<PrivateDataTy> Privates) { 4645 ASTContext &C = CGM.getContext(); 4646 FunctionArgList Args; 4647 ImplicitParamDecl TaskPrivatesArg( 4648 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4649 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4650 ImplicitParamDecl::Other); 4651 Args.push_back(&TaskPrivatesArg); 4652 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4653 unsigned Counter = 1; 4654 for (const Expr *E : PrivateVars) { 4655 Args.push_back(ImplicitParamDecl::Create( 4656 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4657 C.getPointerType(C.getPointerType(E->getType())) 4658 .withConst() 4659 .withRestrict(), 4660 ImplicitParamDecl::Other)); 4661 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4662 PrivateVarsPos[VD] = Counter; 4663 ++Counter; 4664 } 4665 for (const Expr *E : FirstprivateVars) { 4666 Args.push_back(ImplicitParamDecl::Create( 4667 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4668 C.getPointerType(C.getPointerType(E->getType())) 4669 .withConst() 4670 .withRestrict(), 4671 ImplicitParamDecl::Other)); 4672 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4673 PrivateVarsPos[VD] = Counter; 4674 ++Counter; 4675 } 4676 for (const Expr *E : LastprivateVars) { 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 const auto &TaskPrivatesMapFnInfo = 4688 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4689 llvm::FunctionType *TaskPrivatesMapTy = 4690 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4691 std::string Name = 4692 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4693 auto *TaskPrivatesMap = llvm::Function::Create( 4694 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4695 &CGM.getModule()); 4696 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4697 TaskPrivatesMapFnInfo); 4698 if (CGM.getLangOpts().Optimize) { 4699 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4700 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4701 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4702 } 4703 CodeGenFunction CGF(CGM); 4704 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4705 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4706 4707 // *privi = &.privates.privi; 4708 LValue Base = CGF.EmitLoadOfPointerLValue( 4709 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4710 TaskPrivatesArg.getType()->castAs<PointerType>()); 4711 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4712 Counter = 0; 4713 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4714 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4715 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4716 LValue RefLVal = 4717 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4718 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4719 RefLVal.getAddress(CGF), RefLVal.getType()->castAs<PointerType>()); 4720 CGF.EmitStoreOfScalar(FieldLVal.getPointer(CGF), RefLoadLVal); 4721 ++Counter; 4722 } 4723 CGF.FinishFunction(); 4724 return TaskPrivatesMap; 4725 } 4726 4727 /// Emit initialization for private variables in task-based directives. 4728 static void emitPrivatesInit(CodeGenFunction &CGF, 4729 const OMPExecutableDirective &D, 4730 Address KmpTaskSharedsPtr, LValue TDBase, 4731 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4732 QualType SharedsTy, QualType SharedsPtrTy, 4733 const OMPTaskDataTy &Data, 4734 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4735 ASTContext &C = CGF.getContext(); 4736 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4737 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4738 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4739 ? OMPD_taskloop 4740 : OMPD_task; 4741 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4742 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4743 LValue SrcBase; 4744 bool IsTargetTask = 4745 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4746 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4747 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4748 // PointersArray and SizesArray. The original variables for these arrays are 4749 // not captured and we get their addresses explicitly. 4750 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4751 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4752 SrcBase = CGF.MakeAddrLValue( 4753 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4754 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4755 SharedsTy); 4756 } 4757 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4758 for (const PrivateDataTy &Pair : Privates) { 4759 const VarDecl *VD = Pair.second.PrivateCopy; 4760 const Expr *Init = VD->getAnyInitializer(); 4761 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4762 !CGF.isTrivialInitializer(Init)))) { 4763 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4764 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4765 const VarDecl *OriginalVD = Pair.second.Original; 4766 // Check if the variable is the target-based BasePointersArray, 4767 // PointersArray or SizesArray. 4768 LValue SharedRefLValue; 4769 QualType Type = PrivateLValue.getType(); 4770 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4771 if (IsTargetTask && !SharedField) { 4772 assert(isa<ImplicitParamDecl>(OriginalVD) && 4773 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4774 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4775 ->getNumParams() == 0 && 4776 isa<TranslationUnitDecl>( 4777 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4778 ->getDeclContext()) && 4779 "Expected artificial target data variable."); 4780 SharedRefLValue = 4781 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4782 } else { 4783 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4784 SharedRefLValue = CGF.MakeAddrLValue( 4785 Address(SharedRefLValue.getPointer(CGF), 4786 C.getDeclAlign(OriginalVD)), 4787 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4788 SharedRefLValue.getTBAAInfo()); 4789 } 4790 if (Type->isArrayType()) { 4791 // Initialize firstprivate array. 4792 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4793 // Perform simple memcpy. 4794 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4795 } else { 4796 // Initialize firstprivate array using element-by-element 4797 // initialization. 4798 CGF.EmitOMPAggregateAssign( 4799 PrivateLValue.getAddress(CGF), SharedRefLValue.getAddress(CGF), 4800 Type, 4801 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4802 Address SrcElement) { 4803 // Clean up any temporaries needed by the initialization. 4804 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4805 InitScope.addPrivate( 4806 Elem, [SrcElement]() -> Address { return SrcElement; }); 4807 (void)InitScope.Privatize(); 4808 // Emit initialization for single element. 4809 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4810 CGF, &CapturesInfo); 4811 CGF.EmitAnyExprToMem(Init, DestElement, 4812 Init->getType().getQualifiers(), 4813 /*IsInitializer=*/false); 4814 }); 4815 } 4816 } else { 4817 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4818 InitScope.addPrivate(Elem, [SharedRefLValue, &CGF]() -> Address { 4819 return SharedRefLValue.getAddress(CGF); 4820 }); 4821 (void)InitScope.Privatize(); 4822 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4823 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4824 /*capturedByInit=*/false); 4825 } 4826 } else { 4827 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4828 } 4829 } 4830 ++FI; 4831 } 4832 } 4833 4834 /// Check if duplication function is required for taskloops. 4835 static bool checkInitIsRequired(CodeGenFunction &CGF, 4836 ArrayRef<PrivateDataTy> Privates) { 4837 bool InitRequired = false; 4838 for (const PrivateDataTy &Pair : Privates) { 4839 const VarDecl *VD = Pair.second.PrivateCopy; 4840 const Expr *Init = VD->getAnyInitializer(); 4841 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4842 !CGF.isTrivialInitializer(Init)); 4843 if (InitRequired) 4844 break; 4845 } 4846 return InitRequired; 4847 } 4848 4849 4850 /// Emit task_dup function (for initialization of 4851 /// private/firstprivate/lastprivate vars and last_iter flag) 4852 /// \code 4853 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4854 /// lastpriv) { 4855 /// // setup lastprivate flag 4856 /// task_dst->last = lastpriv; 4857 /// // could be constructor calls here... 4858 /// } 4859 /// \endcode 4860 static llvm::Value * 4861 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4862 const OMPExecutableDirective &D, 4863 QualType KmpTaskTWithPrivatesPtrQTy, 4864 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4865 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4866 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4867 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4868 ASTContext &C = CGM.getContext(); 4869 FunctionArgList Args; 4870 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4871 KmpTaskTWithPrivatesPtrQTy, 4872 ImplicitParamDecl::Other); 4873 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4874 KmpTaskTWithPrivatesPtrQTy, 4875 ImplicitParamDecl::Other); 4876 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4877 ImplicitParamDecl::Other); 4878 Args.push_back(&DstArg); 4879 Args.push_back(&SrcArg); 4880 Args.push_back(&LastprivArg); 4881 const auto &TaskDupFnInfo = 4882 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4883 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4884 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4885 auto *TaskDup = llvm::Function::Create( 4886 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4887 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4888 TaskDup->setDoesNotRecurse(); 4889 CodeGenFunction CGF(CGM); 4890 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4891 Loc); 4892 4893 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4894 CGF.GetAddrOfLocalVar(&DstArg), 4895 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4896 // task_dst->liter = lastpriv; 4897 if (WithLastIter) { 4898 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4899 LValue Base = CGF.EmitLValueForField( 4900 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4901 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4902 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4903 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4904 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4905 } 4906 4907 // Emit initial values for private copies (if any). 4908 assert(!Privates.empty()); 4909 Address KmpTaskSharedsPtr = Address::invalid(); 4910 if (!Data.FirstprivateVars.empty()) { 4911 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4912 CGF.GetAddrOfLocalVar(&SrcArg), 4913 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4914 LValue Base = CGF.EmitLValueForField( 4915 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4916 KmpTaskSharedsPtr = Address( 4917 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4918 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4919 KmpTaskTShareds)), 4920 Loc), 4921 CGF.getNaturalTypeAlignment(SharedsTy)); 4922 } 4923 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4924 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4925 CGF.FinishFunction(); 4926 return TaskDup; 4927 } 4928 4929 /// Checks if destructor function is required to be generated. 4930 /// \return true if cleanups are required, false otherwise. 4931 static bool 4932 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4933 bool NeedsCleanup = false; 4934 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4935 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4936 for (const FieldDecl *FD : PrivateRD->fields()) { 4937 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4938 if (NeedsCleanup) 4939 break; 4940 } 4941 return NeedsCleanup; 4942 } 4943 4944 CGOpenMPRuntime::TaskResultTy 4945 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4946 const OMPExecutableDirective &D, 4947 llvm::Function *TaskFunction, QualType SharedsTy, 4948 Address Shareds, const OMPTaskDataTy &Data) { 4949 ASTContext &C = CGM.getContext(); 4950 llvm::SmallVector<PrivateDataTy, 4> Privates; 4951 // Aggregate privates and sort them by the alignment. 4952 auto I = Data.PrivateCopies.begin(); 4953 for (const Expr *E : Data.PrivateVars) { 4954 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4955 Privates.emplace_back( 4956 C.getDeclAlign(VD), 4957 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4958 /*PrivateElemInit=*/nullptr)); 4959 ++I; 4960 } 4961 I = Data.FirstprivateCopies.begin(); 4962 auto IElemInitRef = Data.FirstprivateInits.begin(); 4963 for (const Expr *E : Data.FirstprivateVars) { 4964 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4965 Privates.emplace_back( 4966 C.getDeclAlign(VD), 4967 PrivateHelpersTy( 4968 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4969 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4970 ++I; 4971 ++IElemInitRef; 4972 } 4973 I = Data.LastprivateCopies.begin(); 4974 for (const Expr *E : Data.LastprivateVars) { 4975 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4976 Privates.emplace_back( 4977 C.getDeclAlign(VD), 4978 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4979 /*PrivateElemInit=*/nullptr)); 4980 ++I; 4981 } 4982 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 4983 return L.first > R.first; 4984 }); 4985 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4986 // Build type kmp_routine_entry_t (if not built yet). 4987 emitKmpRoutineEntryT(KmpInt32Ty); 4988 // Build type kmp_task_t (if not built yet). 4989 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 4990 if (SavedKmpTaskloopTQTy.isNull()) { 4991 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 4992 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 4993 } 4994 KmpTaskTQTy = SavedKmpTaskloopTQTy; 4995 } else { 4996 assert((D.getDirectiveKind() == OMPD_task || 4997 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 4998 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 4999 "Expected taskloop, task or target directive"); 5000 if (SavedKmpTaskTQTy.isNull()) { 5001 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5002 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5003 } 5004 KmpTaskTQTy = SavedKmpTaskTQTy; 5005 } 5006 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5007 // Build particular struct kmp_task_t for the given task. 5008 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5009 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5010 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5011 QualType KmpTaskTWithPrivatesPtrQTy = 5012 C.getPointerType(KmpTaskTWithPrivatesQTy); 5013 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5014 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5015 KmpTaskTWithPrivatesTy->getPointerTo(); 5016 llvm::Value *KmpTaskTWithPrivatesTySize = 5017 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5018 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5019 5020 // Emit initial values for private copies (if any). 5021 llvm::Value *TaskPrivatesMap = nullptr; 5022 llvm::Type *TaskPrivatesMapTy = 5023 std::next(TaskFunction->arg_begin(), 3)->getType(); 5024 if (!Privates.empty()) { 5025 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5026 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5027 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5028 FI->getType(), Privates); 5029 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5030 TaskPrivatesMap, TaskPrivatesMapTy); 5031 } else { 5032 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5033 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5034 } 5035 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5036 // kmp_task_t *tt); 5037 llvm::Function *TaskEntry = emitProxyTaskFunction( 5038 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5039 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5040 TaskPrivatesMap); 5041 5042 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5043 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5044 // kmp_routine_entry_t *task_entry); 5045 // Task flags. Format is taken from 5046 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5047 // description of kmp_tasking_flags struct. 5048 enum { 5049 TiedFlag = 0x1, 5050 FinalFlag = 0x2, 5051 DestructorsFlag = 0x8, 5052 PriorityFlag = 0x20 5053 }; 5054 unsigned Flags = Data.Tied ? TiedFlag : 0; 5055 bool NeedsCleanup = false; 5056 if (!Privates.empty()) { 5057 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5058 if (NeedsCleanup) 5059 Flags = Flags | DestructorsFlag; 5060 } 5061 if (Data.Priority.getInt()) 5062 Flags = Flags | PriorityFlag; 5063 llvm::Value *TaskFlags = 5064 Data.Final.getPointer() 5065 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5066 CGF.Builder.getInt32(FinalFlag), 5067 CGF.Builder.getInt32(/*C=*/0)) 5068 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5069 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5070 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5071 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5072 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5073 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5074 TaskEntry, KmpRoutineEntryPtrTy)}; 5075 llvm::Value *NewTask; 5076 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5077 // Check if we have any device clause associated with the directive. 5078 const Expr *Device = nullptr; 5079 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5080 Device = C->getDevice(); 5081 // Emit device ID if any otherwise use default value. 5082 llvm::Value *DeviceID; 5083 if (Device) 5084 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5085 CGF.Int64Ty, /*isSigned=*/true); 5086 else 5087 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5088 AllocArgs.push_back(DeviceID); 5089 NewTask = CGF.EmitRuntimeCall( 5090 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5091 } else { 5092 NewTask = CGF.EmitRuntimeCall( 5093 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5094 } 5095 llvm::Value *NewTaskNewTaskTTy = 5096 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5097 NewTask, KmpTaskTWithPrivatesPtrTy); 5098 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5099 KmpTaskTWithPrivatesQTy); 5100 LValue TDBase = 5101 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5102 // Fill the data in the resulting kmp_task_t record. 5103 // Copy shareds if there are any. 5104 Address KmpTaskSharedsPtr = Address::invalid(); 5105 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5106 KmpTaskSharedsPtr = 5107 Address(CGF.EmitLoadOfScalar( 5108 CGF.EmitLValueForField( 5109 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5110 KmpTaskTShareds)), 5111 Loc), 5112 CGF.getNaturalTypeAlignment(SharedsTy)); 5113 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5114 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5115 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5116 } 5117 // Emit initial values for private copies (if any). 5118 TaskResultTy Result; 5119 if (!Privates.empty()) { 5120 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5121 SharedsTy, SharedsPtrTy, Data, Privates, 5122 /*ForDup=*/false); 5123 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5124 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5125 Result.TaskDupFn = emitTaskDupFunction( 5126 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5127 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5128 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5129 } 5130 } 5131 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5132 enum { Priority = 0, Destructors = 1 }; 5133 // Provide pointer to function with destructors for privates. 5134 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5135 const RecordDecl *KmpCmplrdataUD = 5136 (*FI)->getType()->getAsUnionType()->getDecl(); 5137 if (NeedsCleanup) { 5138 llvm::Value *DestructorFn = emitDestructorsFunction( 5139 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5140 KmpTaskTWithPrivatesQTy); 5141 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5142 LValue DestructorsLV = CGF.EmitLValueForField( 5143 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5144 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5145 DestructorFn, KmpRoutineEntryPtrTy), 5146 DestructorsLV); 5147 } 5148 // Set priority. 5149 if (Data.Priority.getInt()) { 5150 LValue Data2LV = CGF.EmitLValueForField( 5151 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5152 LValue PriorityLV = CGF.EmitLValueForField( 5153 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5154 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5155 } 5156 Result.NewTask = NewTask; 5157 Result.TaskEntry = TaskEntry; 5158 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5159 Result.TDBase = TDBase; 5160 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5161 return Result; 5162 } 5163 5164 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5165 const OMPExecutableDirective &D, 5166 llvm::Function *TaskFunction, 5167 QualType SharedsTy, Address Shareds, 5168 const Expr *IfCond, 5169 const OMPTaskDataTy &Data) { 5170 if (!CGF.HaveInsertPoint()) 5171 return; 5172 5173 TaskResultTy Result = 5174 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5175 llvm::Value *NewTask = Result.NewTask; 5176 llvm::Function *TaskEntry = Result.TaskEntry; 5177 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5178 LValue TDBase = Result.TDBase; 5179 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5180 ASTContext &C = CGM.getContext(); 5181 // Process list of dependences. 5182 Address DependenciesArray = Address::invalid(); 5183 unsigned NumDependencies = Data.Dependences.size(); 5184 if (NumDependencies) { 5185 // Dependence kind for RTL. 5186 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5187 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5188 RecordDecl *KmpDependInfoRD; 5189 QualType FlagsTy = 5190 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5191 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5192 if (KmpDependInfoTy.isNull()) { 5193 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5194 KmpDependInfoRD->startDefinition(); 5195 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5196 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5197 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5198 KmpDependInfoRD->completeDefinition(); 5199 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5200 } else { 5201 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5202 } 5203 // Define type kmp_depend_info[<Dependences.size()>]; 5204 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5205 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5206 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5207 // kmp_depend_info[<Dependences.size()>] deps; 5208 DependenciesArray = 5209 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5210 for (unsigned I = 0; I < NumDependencies; ++I) { 5211 const Expr *E = Data.Dependences[I].second; 5212 LValue Addr = CGF.EmitLValue(E); 5213 llvm::Value *Size; 5214 QualType Ty = E->getType(); 5215 if (const auto *ASE = 5216 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5217 LValue UpAddrLVal = 5218 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5219 llvm::Value *UpAddr = CGF.Builder.CreateConstGEP1_32( 5220 UpAddrLVal.getPointer(CGF), /*Idx0=*/1); 5221 llvm::Value *LowIntPtr = 5222 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGM.SizeTy); 5223 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5224 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5225 } else { 5226 Size = CGF.getTypeSize(Ty); 5227 } 5228 LValue Base = CGF.MakeAddrLValue( 5229 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5230 KmpDependInfoTy); 5231 // deps[i].base_addr = &<Dependences[i].second>; 5232 LValue BaseAddrLVal = CGF.EmitLValueForField( 5233 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5234 CGF.EmitStoreOfScalar( 5235 CGF.Builder.CreatePtrToInt(Addr.getPointer(CGF), CGF.IntPtrTy), 5236 BaseAddrLVal); 5237 // deps[i].len = sizeof(<Dependences[i].second>); 5238 LValue LenLVal = CGF.EmitLValueForField( 5239 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5240 CGF.EmitStoreOfScalar(Size, LenLVal); 5241 // deps[i].flags = <Dependences[i].first>; 5242 RTLDependenceKindTy DepKind; 5243 switch (Data.Dependences[I].first) { 5244 case OMPC_DEPEND_in: 5245 DepKind = DepIn; 5246 break; 5247 // Out and InOut dependencies must use the same code. 5248 case OMPC_DEPEND_out: 5249 case OMPC_DEPEND_inout: 5250 DepKind = DepInOut; 5251 break; 5252 case OMPC_DEPEND_mutexinoutset: 5253 DepKind = DepMutexInOutSet; 5254 break; 5255 case OMPC_DEPEND_source: 5256 case OMPC_DEPEND_sink: 5257 case OMPC_DEPEND_unknown: 5258 llvm_unreachable("Unknown task dependence type"); 5259 } 5260 LValue FlagsLVal = CGF.EmitLValueForField( 5261 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5262 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5263 FlagsLVal); 5264 } 5265 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5266 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5267 } 5268 5269 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5270 // libcall. 5271 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5272 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5273 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5274 // list is not empty 5275 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5276 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5277 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5278 llvm::Value *DepTaskArgs[7]; 5279 if (NumDependencies) { 5280 DepTaskArgs[0] = UpLoc; 5281 DepTaskArgs[1] = ThreadID; 5282 DepTaskArgs[2] = NewTask; 5283 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5284 DepTaskArgs[4] = DependenciesArray.getPointer(); 5285 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5286 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5287 } 5288 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5289 &TaskArgs, 5290 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5291 if (!Data.Tied) { 5292 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5293 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5294 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5295 } 5296 if (NumDependencies) { 5297 CGF.EmitRuntimeCall( 5298 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5299 } else { 5300 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5301 TaskArgs); 5302 } 5303 // Check if parent region is untied and build return for untied task; 5304 if (auto *Region = 5305 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5306 Region->emitUntiedSwitch(CGF); 5307 }; 5308 5309 llvm::Value *DepWaitTaskArgs[6]; 5310 if (NumDependencies) { 5311 DepWaitTaskArgs[0] = UpLoc; 5312 DepWaitTaskArgs[1] = ThreadID; 5313 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5314 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5315 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5316 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5317 } 5318 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5319 NumDependencies, &DepWaitTaskArgs, 5320 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5321 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5322 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5323 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5324 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5325 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5326 // is specified. 5327 if (NumDependencies) 5328 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5329 DepWaitTaskArgs); 5330 // Call proxy_task_entry(gtid, new_task); 5331 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5332 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5333 Action.Enter(CGF); 5334 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5335 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5336 OutlinedFnArgs); 5337 }; 5338 5339 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5340 // kmp_task_t *new_task); 5341 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5342 // kmp_task_t *new_task); 5343 RegionCodeGenTy RCG(CodeGen); 5344 CommonActionTy Action( 5345 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5346 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5347 RCG.setAction(Action); 5348 RCG(CGF); 5349 }; 5350 5351 if (IfCond) { 5352 emitIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5353 } else { 5354 RegionCodeGenTy ThenRCG(ThenCodeGen); 5355 ThenRCG(CGF); 5356 } 5357 } 5358 5359 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5360 const OMPLoopDirective &D, 5361 llvm::Function *TaskFunction, 5362 QualType SharedsTy, Address Shareds, 5363 const Expr *IfCond, 5364 const OMPTaskDataTy &Data) { 5365 if (!CGF.HaveInsertPoint()) 5366 return; 5367 TaskResultTy Result = 5368 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5369 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5370 // libcall. 5371 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5372 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5373 // sched, kmp_uint64 grainsize, void *task_dup); 5374 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5375 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5376 llvm::Value *IfVal; 5377 if (IfCond) { 5378 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5379 /*isSigned=*/true); 5380 } else { 5381 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5382 } 5383 5384 LValue LBLVal = CGF.EmitLValueForField( 5385 Result.TDBase, 5386 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5387 const auto *LBVar = 5388 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5389 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(CGF), 5390 LBLVal.getQuals(), 5391 /*IsInitializer=*/true); 5392 LValue UBLVal = CGF.EmitLValueForField( 5393 Result.TDBase, 5394 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5395 const auto *UBVar = 5396 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5397 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(CGF), 5398 UBLVal.getQuals(), 5399 /*IsInitializer=*/true); 5400 LValue StLVal = CGF.EmitLValueForField( 5401 Result.TDBase, 5402 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5403 const auto *StVar = 5404 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5405 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(CGF), 5406 StLVal.getQuals(), 5407 /*IsInitializer=*/true); 5408 // Store reductions address. 5409 LValue RedLVal = CGF.EmitLValueForField( 5410 Result.TDBase, 5411 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5412 if (Data.Reductions) { 5413 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5414 } else { 5415 CGF.EmitNullInitialization(RedLVal.getAddress(CGF), 5416 CGF.getContext().VoidPtrTy); 5417 } 5418 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5419 llvm::Value *TaskArgs[] = { 5420 UpLoc, 5421 ThreadID, 5422 Result.NewTask, 5423 IfVal, 5424 LBLVal.getPointer(CGF), 5425 UBLVal.getPointer(CGF), 5426 CGF.EmitLoadOfScalar(StLVal, Loc), 5427 llvm::ConstantInt::getSigned( 5428 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5429 llvm::ConstantInt::getSigned( 5430 CGF.IntTy, Data.Schedule.getPointer() 5431 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5432 : NoSchedule), 5433 Data.Schedule.getPointer() 5434 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5435 /*isSigned=*/false) 5436 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5437 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5438 Result.TaskDupFn, CGF.VoidPtrTy) 5439 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5440 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5441 } 5442 5443 /// Emit reduction operation for each element of array (required for 5444 /// array sections) LHS op = RHS. 5445 /// \param Type Type of array. 5446 /// \param LHSVar Variable on the left side of the reduction operation 5447 /// (references element of array in original variable). 5448 /// \param RHSVar Variable on the right side of the reduction operation 5449 /// (references element of array in original variable). 5450 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5451 /// RHSVar. 5452 static void EmitOMPAggregateReduction( 5453 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5454 const VarDecl *RHSVar, 5455 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5456 const Expr *, const Expr *)> &RedOpGen, 5457 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5458 const Expr *UpExpr = nullptr) { 5459 // Perform element-by-element initialization. 5460 QualType ElementTy; 5461 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5462 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5463 5464 // Drill down to the base element type on both arrays. 5465 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5466 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5467 5468 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5469 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5470 // Cast from pointer to array type to pointer to single element. 5471 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5472 // The basic structure here is a while-do loop. 5473 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5474 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5475 llvm::Value *IsEmpty = 5476 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5477 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5478 5479 // Enter the loop body, making that address the current address. 5480 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5481 CGF.EmitBlock(BodyBB); 5482 5483 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5484 5485 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5486 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5487 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5488 Address RHSElementCurrent = 5489 Address(RHSElementPHI, 5490 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5491 5492 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5493 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5494 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5495 Address LHSElementCurrent = 5496 Address(LHSElementPHI, 5497 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5498 5499 // Emit copy. 5500 CodeGenFunction::OMPPrivateScope Scope(CGF); 5501 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5502 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5503 Scope.Privatize(); 5504 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5505 Scope.ForceCleanup(); 5506 5507 // Shift the address forward by one element. 5508 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5509 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5510 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5511 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5512 // Check whether we've reached the end. 5513 llvm::Value *Done = 5514 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5515 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5516 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5517 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5518 5519 // Done. 5520 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5521 } 5522 5523 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5524 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5525 /// UDR combiner function. 5526 static void emitReductionCombiner(CodeGenFunction &CGF, 5527 const Expr *ReductionOp) { 5528 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5529 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5530 if (const auto *DRE = 5531 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5532 if (const auto *DRD = 5533 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5534 std::pair<llvm::Function *, llvm::Function *> Reduction = 5535 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5536 RValue Func = RValue::get(Reduction.first); 5537 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5538 CGF.EmitIgnoredExpr(ReductionOp); 5539 return; 5540 } 5541 CGF.EmitIgnoredExpr(ReductionOp); 5542 } 5543 5544 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5545 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5546 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5547 ArrayRef<const Expr *> ReductionOps) { 5548 ASTContext &C = CGM.getContext(); 5549 5550 // void reduction_func(void *LHSArg, void *RHSArg); 5551 FunctionArgList Args; 5552 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5553 ImplicitParamDecl::Other); 5554 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5555 ImplicitParamDecl::Other); 5556 Args.push_back(&LHSArg); 5557 Args.push_back(&RHSArg); 5558 const auto &CGFI = 5559 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5560 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5561 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5562 llvm::GlobalValue::InternalLinkage, Name, 5563 &CGM.getModule()); 5564 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5565 Fn->setDoesNotRecurse(); 5566 CodeGenFunction CGF(CGM); 5567 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5568 5569 // Dst = (void*[n])(LHSArg); 5570 // Src = (void*[n])(RHSArg); 5571 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5572 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5573 ArgsType), CGF.getPointerAlign()); 5574 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5575 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5576 ArgsType), CGF.getPointerAlign()); 5577 5578 // ... 5579 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5580 // ... 5581 CodeGenFunction::OMPPrivateScope Scope(CGF); 5582 auto IPriv = Privates.begin(); 5583 unsigned Idx = 0; 5584 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5585 const auto *RHSVar = 5586 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5587 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5588 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5589 }); 5590 const auto *LHSVar = 5591 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5592 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5593 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5594 }); 5595 QualType PrivTy = (*IPriv)->getType(); 5596 if (PrivTy->isVariablyModifiedType()) { 5597 // Get array size and emit VLA type. 5598 ++Idx; 5599 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5600 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5601 const VariableArrayType *VLA = 5602 CGF.getContext().getAsVariableArrayType(PrivTy); 5603 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5604 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5605 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5606 CGF.EmitVariablyModifiedType(PrivTy); 5607 } 5608 } 5609 Scope.Privatize(); 5610 IPriv = Privates.begin(); 5611 auto ILHS = LHSExprs.begin(); 5612 auto IRHS = RHSExprs.begin(); 5613 for (const Expr *E : ReductionOps) { 5614 if ((*IPriv)->getType()->isArrayType()) { 5615 // Emit reduction for array section. 5616 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5617 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5618 EmitOMPAggregateReduction( 5619 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5620 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5621 emitReductionCombiner(CGF, E); 5622 }); 5623 } else { 5624 // Emit reduction for array subscript or single variable. 5625 emitReductionCombiner(CGF, E); 5626 } 5627 ++IPriv; 5628 ++ILHS; 5629 ++IRHS; 5630 } 5631 Scope.ForceCleanup(); 5632 CGF.FinishFunction(); 5633 return Fn; 5634 } 5635 5636 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5637 const Expr *ReductionOp, 5638 const Expr *PrivateRef, 5639 const DeclRefExpr *LHS, 5640 const DeclRefExpr *RHS) { 5641 if (PrivateRef->getType()->isArrayType()) { 5642 // Emit reduction for array section. 5643 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5644 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5645 EmitOMPAggregateReduction( 5646 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5647 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5648 emitReductionCombiner(CGF, ReductionOp); 5649 }); 5650 } else { 5651 // Emit reduction for array subscript or single variable. 5652 emitReductionCombiner(CGF, ReductionOp); 5653 } 5654 } 5655 5656 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5657 ArrayRef<const Expr *> Privates, 5658 ArrayRef<const Expr *> LHSExprs, 5659 ArrayRef<const Expr *> RHSExprs, 5660 ArrayRef<const Expr *> ReductionOps, 5661 ReductionOptionsTy Options) { 5662 if (!CGF.HaveInsertPoint()) 5663 return; 5664 5665 bool WithNowait = Options.WithNowait; 5666 bool SimpleReduction = Options.SimpleReduction; 5667 5668 // Next code should be emitted for reduction: 5669 // 5670 // static kmp_critical_name lock = { 0 }; 5671 // 5672 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5673 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5674 // ... 5675 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5676 // *(Type<n>-1*)rhs[<n>-1]); 5677 // } 5678 // 5679 // ... 5680 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5681 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5682 // RedList, reduce_func, &<lock>)) { 5683 // case 1: 5684 // ... 5685 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5686 // ... 5687 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5688 // break; 5689 // case 2: 5690 // ... 5691 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5692 // ... 5693 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5694 // break; 5695 // default:; 5696 // } 5697 // 5698 // if SimpleReduction is true, only the next code is generated: 5699 // ... 5700 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5701 // ... 5702 5703 ASTContext &C = CGM.getContext(); 5704 5705 if (SimpleReduction) { 5706 CodeGenFunction::RunCleanupsScope Scope(CGF); 5707 auto IPriv = Privates.begin(); 5708 auto ILHS = LHSExprs.begin(); 5709 auto IRHS = RHSExprs.begin(); 5710 for (const Expr *E : ReductionOps) { 5711 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5712 cast<DeclRefExpr>(*IRHS)); 5713 ++IPriv; 5714 ++ILHS; 5715 ++IRHS; 5716 } 5717 return; 5718 } 5719 5720 // 1. Build a list of reduction variables. 5721 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5722 auto Size = RHSExprs.size(); 5723 for (const Expr *E : Privates) { 5724 if (E->getType()->isVariablyModifiedType()) 5725 // Reserve place for array size. 5726 ++Size; 5727 } 5728 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5729 QualType ReductionArrayTy = 5730 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5731 /*IndexTypeQuals=*/0); 5732 Address ReductionList = 5733 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5734 auto IPriv = Privates.begin(); 5735 unsigned Idx = 0; 5736 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5737 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5738 CGF.Builder.CreateStore( 5739 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5740 CGF.EmitLValue(RHSExprs[I]).getPointer(CGF), CGF.VoidPtrTy), 5741 Elem); 5742 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5743 // Store array size. 5744 ++Idx; 5745 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5746 llvm::Value *Size = CGF.Builder.CreateIntCast( 5747 CGF.getVLASize( 5748 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5749 .NumElts, 5750 CGF.SizeTy, /*isSigned=*/false); 5751 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5752 Elem); 5753 } 5754 } 5755 5756 // 2. Emit reduce_func(). 5757 llvm::Function *ReductionFn = emitReductionFunction( 5758 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5759 LHSExprs, RHSExprs, ReductionOps); 5760 5761 // 3. Create static kmp_critical_name lock = { 0 }; 5762 std::string Name = getName({"reduction"}); 5763 llvm::Value *Lock = getCriticalRegionLock(Name); 5764 5765 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5766 // RedList, reduce_func, &<lock>); 5767 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5768 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5769 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5770 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5771 ReductionList.getPointer(), CGF.VoidPtrTy); 5772 llvm::Value *Args[] = { 5773 IdentTLoc, // ident_t *<loc> 5774 ThreadId, // i32 <gtid> 5775 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5776 ReductionArrayTySize, // size_type sizeof(RedList) 5777 RL, // void *RedList 5778 ReductionFn, // void (*) (void *, void *) <reduce_func> 5779 Lock // kmp_critical_name *&<lock> 5780 }; 5781 llvm::Value *Res = CGF.EmitRuntimeCall( 5782 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5783 : OMPRTL__kmpc_reduce), 5784 Args); 5785 5786 // 5. Build switch(res) 5787 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5788 llvm::SwitchInst *SwInst = 5789 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5790 5791 // 6. Build case 1: 5792 // ... 5793 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5794 // ... 5795 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5796 // break; 5797 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5798 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5799 CGF.EmitBlock(Case1BB); 5800 5801 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5802 llvm::Value *EndArgs[] = { 5803 IdentTLoc, // ident_t *<loc> 5804 ThreadId, // i32 <gtid> 5805 Lock // kmp_critical_name *&<lock> 5806 }; 5807 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5808 CodeGenFunction &CGF, PrePostActionTy &Action) { 5809 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5810 auto IPriv = Privates.begin(); 5811 auto ILHS = LHSExprs.begin(); 5812 auto IRHS = RHSExprs.begin(); 5813 for (const Expr *E : ReductionOps) { 5814 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5815 cast<DeclRefExpr>(*IRHS)); 5816 ++IPriv; 5817 ++ILHS; 5818 ++IRHS; 5819 } 5820 }; 5821 RegionCodeGenTy RCG(CodeGen); 5822 CommonActionTy Action( 5823 nullptr, llvm::None, 5824 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5825 : OMPRTL__kmpc_end_reduce), 5826 EndArgs); 5827 RCG.setAction(Action); 5828 RCG(CGF); 5829 5830 CGF.EmitBranch(DefaultBB); 5831 5832 // 7. Build case 2: 5833 // ... 5834 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5835 // ... 5836 // break; 5837 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5838 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5839 CGF.EmitBlock(Case2BB); 5840 5841 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5842 CodeGenFunction &CGF, PrePostActionTy &Action) { 5843 auto ILHS = LHSExprs.begin(); 5844 auto IRHS = RHSExprs.begin(); 5845 auto IPriv = Privates.begin(); 5846 for (const Expr *E : ReductionOps) { 5847 const Expr *XExpr = nullptr; 5848 const Expr *EExpr = nullptr; 5849 const Expr *UpExpr = nullptr; 5850 BinaryOperatorKind BO = BO_Comma; 5851 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5852 if (BO->getOpcode() == BO_Assign) { 5853 XExpr = BO->getLHS(); 5854 UpExpr = BO->getRHS(); 5855 } 5856 } 5857 // Try to emit update expression as a simple atomic. 5858 const Expr *RHSExpr = UpExpr; 5859 if (RHSExpr) { 5860 // Analyze RHS part of the whole expression. 5861 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5862 RHSExpr->IgnoreParenImpCasts())) { 5863 // If this is a conditional operator, analyze its condition for 5864 // min/max reduction operator. 5865 RHSExpr = ACO->getCond(); 5866 } 5867 if (const auto *BORHS = 5868 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5869 EExpr = BORHS->getRHS(); 5870 BO = BORHS->getOpcode(); 5871 } 5872 } 5873 if (XExpr) { 5874 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5875 auto &&AtomicRedGen = [BO, VD, 5876 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5877 const Expr *EExpr, const Expr *UpExpr) { 5878 LValue X = CGF.EmitLValue(XExpr); 5879 RValue E; 5880 if (EExpr) 5881 E = CGF.EmitAnyExpr(EExpr); 5882 CGF.EmitOMPAtomicSimpleUpdateExpr( 5883 X, E, BO, /*IsXLHSInRHSPart=*/true, 5884 llvm::AtomicOrdering::Monotonic, Loc, 5885 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5886 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5887 PrivateScope.addPrivate( 5888 VD, [&CGF, VD, XRValue, Loc]() { 5889 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5890 CGF.emitOMPSimpleStore( 5891 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5892 VD->getType().getNonReferenceType(), Loc); 5893 return LHSTemp; 5894 }); 5895 (void)PrivateScope.Privatize(); 5896 return CGF.EmitAnyExpr(UpExpr); 5897 }); 5898 }; 5899 if ((*IPriv)->getType()->isArrayType()) { 5900 // Emit atomic reduction for array section. 5901 const auto *RHSVar = 5902 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5903 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5904 AtomicRedGen, XExpr, EExpr, UpExpr); 5905 } else { 5906 // Emit atomic reduction for array subscript or single variable. 5907 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5908 } 5909 } else { 5910 // Emit as a critical region. 5911 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5912 const Expr *, const Expr *) { 5913 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5914 std::string Name = RT.getName({"atomic_reduction"}); 5915 RT.emitCriticalRegion( 5916 CGF, Name, 5917 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5918 Action.Enter(CGF); 5919 emitReductionCombiner(CGF, E); 5920 }, 5921 Loc); 5922 }; 5923 if ((*IPriv)->getType()->isArrayType()) { 5924 const auto *LHSVar = 5925 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5926 const auto *RHSVar = 5927 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5928 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5929 CritRedGen); 5930 } else { 5931 CritRedGen(CGF, nullptr, nullptr, nullptr); 5932 } 5933 } 5934 ++ILHS; 5935 ++IRHS; 5936 ++IPriv; 5937 } 5938 }; 5939 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5940 if (!WithNowait) { 5941 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5942 llvm::Value *EndArgs[] = { 5943 IdentTLoc, // ident_t *<loc> 5944 ThreadId, // i32 <gtid> 5945 Lock // kmp_critical_name *&<lock> 5946 }; 5947 CommonActionTy Action(nullptr, llvm::None, 5948 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 5949 EndArgs); 5950 AtomicRCG.setAction(Action); 5951 AtomicRCG(CGF); 5952 } else { 5953 AtomicRCG(CGF); 5954 } 5955 5956 CGF.EmitBranch(DefaultBB); 5957 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5958 } 5959 5960 /// Generates unique name for artificial threadprivate variables. 5961 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5962 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5963 const Expr *Ref) { 5964 SmallString<256> Buffer; 5965 llvm::raw_svector_ostream Out(Buffer); 5966 const clang::DeclRefExpr *DE; 5967 const VarDecl *D = ::getBaseDecl(Ref, DE); 5968 if (!D) 5969 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5970 D = D->getCanonicalDecl(); 5971 std::string Name = CGM.getOpenMPRuntime().getName( 5972 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5973 Out << Prefix << Name << "_" 5974 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5975 return std::string(Out.str()); 5976 } 5977 5978 /// Emits reduction initializer function: 5979 /// \code 5980 /// void @.red_init(void* %arg) { 5981 /// %0 = bitcast void* %arg to <type>* 5982 /// store <type> <init>, <type>* %0 5983 /// ret void 5984 /// } 5985 /// \endcode 5986 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 5987 SourceLocation Loc, 5988 ReductionCodeGen &RCG, unsigned N) { 5989 ASTContext &C = CGM.getContext(); 5990 FunctionArgList Args; 5991 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5992 ImplicitParamDecl::Other); 5993 Args.emplace_back(&Param); 5994 const auto &FnInfo = 5995 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5996 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 5997 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 5998 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 5999 Name, &CGM.getModule()); 6000 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6001 Fn->setDoesNotRecurse(); 6002 CodeGenFunction CGF(CGM); 6003 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6004 Address PrivateAddr = CGF.EmitLoadOfPointer( 6005 CGF.GetAddrOfLocalVar(&Param), 6006 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6007 llvm::Value *Size = nullptr; 6008 // If the size of the reduction item is non-constant, load it from global 6009 // threadprivate variable. 6010 if (RCG.getSizes(N).second) { 6011 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6012 CGF, CGM.getContext().getSizeType(), 6013 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6014 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6015 CGM.getContext().getSizeType(), Loc); 6016 } 6017 RCG.emitAggregateType(CGF, N, Size); 6018 LValue SharedLVal; 6019 // If initializer uses initializer from declare reduction construct, emit a 6020 // pointer to the address of the original reduction item (reuired by reduction 6021 // initializer) 6022 if (RCG.usesReductionInitializer(N)) { 6023 Address SharedAddr = 6024 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6025 CGF, CGM.getContext().VoidPtrTy, 6026 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6027 SharedAddr = CGF.EmitLoadOfPointer( 6028 SharedAddr, 6029 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6030 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6031 } else { 6032 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6033 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6034 CGM.getContext().VoidPtrTy); 6035 } 6036 // Emit the initializer: 6037 // %0 = bitcast void* %arg to <type>* 6038 // store <type> <init>, <type>* %0 6039 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6040 [](CodeGenFunction &) { return false; }); 6041 CGF.FinishFunction(); 6042 return Fn; 6043 } 6044 6045 /// Emits reduction combiner function: 6046 /// \code 6047 /// void @.red_comb(void* %arg0, void* %arg1) { 6048 /// %lhs = bitcast void* %arg0 to <type>* 6049 /// %rhs = bitcast void* %arg1 to <type>* 6050 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6051 /// store <type> %2, <type>* %lhs 6052 /// ret void 6053 /// } 6054 /// \endcode 6055 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6056 SourceLocation Loc, 6057 ReductionCodeGen &RCG, unsigned N, 6058 const Expr *ReductionOp, 6059 const Expr *LHS, const Expr *RHS, 6060 const Expr *PrivateRef) { 6061 ASTContext &C = CGM.getContext(); 6062 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6063 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6064 FunctionArgList Args; 6065 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6066 C.VoidPtrTy, ImplicitParamDecl::Other); 6067 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6068 ImplicitParamDecl::Other); 6069 Args.emplace_back(&ParamInOut); 6070 Args.emplace_back(&ParamIn); 6071 const auto &FnInfo = 6072 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6073 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6074 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6075 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6076 Name, &CGM.getModule()); 6077 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6078 Fn->setDoesNotRecurse(); 6079 CodeGenFunction CGF(CGM); 6080 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6081 llvm::Value *Size = nullptr; 6082 // If the size of the reduction item is non-constant, load it from global 6083 // threadprivate variable. 6084 if (RCG.getSizes(N).second) { 6085 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6086 CGF, CGM.getContext().getSizeType(), 6087 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6088 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6089 CGM.getContext().getSizeType(), Loc); 6090 } 6091 RCG.emitAggregateType(CGF, N, Size); 6092 // Remap lhs and rhs variables to the addresses of the function arguments. 6093 // %lhs = bitcast void* %arg0 to <type>* 6094 // %rhs = bitcast void* %arg1 to <type>* 6095 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6096 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6097 // Pull out the pointer to the variable. 6098 Address PtrAddr = CGF.EmitLoadOfPointer( 6099 CGF.GetAddrOfLocalVar(&ParamInOut), 6100 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6101 return CGF.Builder.CreateElementBitCast( 6102 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6103 }); 6104 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6105 // Pull out the pointer to the variable. 6106 Address PtrAddr = CGF.EmitLoadOfPointer( 6107 CGF.GetAddrOfLocalVar(&ParamIn), 6108 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6109 return CGF.Builder.CreateElementBitCast( 6110 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6111 }); 6112 PrivateScope.Privatize(); 6113 // Emit the combiner body: 6114 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6115 // store <type> %2, <type>* %lhs 6116 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6117 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6118 cast<DeclRefExpr>(RHS)); 6119 CGF.FinishFunction(); 6120 return Fn; 6121 } 6122 6123 /// Emits reduction finalizer function: 6124 /// \code 6125 /// void @.red_fini(void* %arg) { 6126 /// %0 = bitcast void* %arg to <type>* 6127 /// <destroy>(<type>* %0) 6128 /// ret void 6129 /// } 6130 /// \endcode 6131 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6132 SourceLocation Loc, 6133 ReductionCodeGen &RCG, unsigned N) { 6134 if (!RCG.needCleanups(N)) 6135 return nullptr; 6136 ASTContext &C = CGM.getContext(); 6137 FunctionArgList Args; 6138 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6139 ImplicitParamDecl::Other); 6140 Args.emplace_back(&Param); 6141 const auto &FnInfo = 6142 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6143 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6144 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6145 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6146 Name, &CGM.getModule()); 6147 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6148 Fn->setDoesNotRecurse(); 6149 CodeGenFunction CGF(CGM); 6150 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6151 Address PrivateAddr = CGF.EmitLoadOfPointer( 6152 CGF.GetAddrOfLocalVar(&Param), 6153 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6154 llvm::Value *Size = nullptr; 6155 // If the size of the reduction item is non-constant, load it from global 6156 // threadprivate variable. 6157 if (RCG.getSizes(N).second) { 6158 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6159 CGF, CGM.getContext().getSizeType(), 6160 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6161 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6162 CGM.getContext().getSizeType(), Loc); 6163 } 6164 RCG.emitAggregateType(CGF, N, Size); 6165 // Emit the finalizer body: 6166 // <destroy>(<type>* %0) 6167 RCG.emitCleanups(CGF, N, PrivateAddr); 6168 CGF.FinishFunction(Loc); 6169 return Fn; 6170 } 6171 6172 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6173 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6174 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6175 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6176 return nullptr; 6177 6178 // Build typedef struct: 6179 // kmp_task_red_input { 6180 // void *reduce_shar; // shared reduction item 6181 // size_t reduce_size; // size of data item 6182 // void *reduce_init; // data initialization routine 6183 // void *reduce_fini; // data finalization routine 6184 // void *reduce_comb; // data combiner routine 6185 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6186 // } kmp_task_red_input_t; 6187 ASTContext &C = CGM.getContext(); 6188 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6189 RD->startDefinition(); 6190 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6191 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6192 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6193 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6194 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6195 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6196 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6197 RD->completeDefinition(); 6198 QualType RDType = C.getRecordType(RD); 6199 unsigned Size = Data.ReductionVars.size(); 6200 llvm::APInt ArraySize(/*numBits=*/64, Size); 6201 QualType ArrayRDType = C.getConstantArrayType( 6202 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6203 // kmp_task_red_input_t .rd_input.[Size]; 6204 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6205 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6206 Data.ReductionOps); 6207 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6208 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6209 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6210 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6211 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6212 TaskRedInput.getPointer(), Idxs, 6213 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6214 ".rd_input.gep."); 6215 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6216 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6217 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6218 RCG.emitSharedLValue(CGF, Cnt); 6219 llvm::Value *CastedShared = 6220 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer(CGF)); 6221 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6222 RCG.emitAggregateType(CGF, Cnt); 6223 llvm::Value *SizeValInChars; 6224 llvm::Value *SizeVal; 6225 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6226 // We use delayed creation/initialization for VLAs, array sections and 6227 // custom reduction initializations. It is required because runtime does not 6228 // provide the way to pass the sizes of VLAs/array sections to 6229 // initializer/combiner/finalizer functions and does not pass the pointer to 6230 // original reduction item to the initializer. Instead threadprivate global 6231 // variables are used to store these values and use them in the functions. 6232 bool DelayedCreation = !!SizeVal; 6233 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6234 /*isSigned=*/false); 6235 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6236 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6237 // ElemLVal.reduce_init = init; 6238 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6239 llvm::Value *InitAddr = 6240 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6241 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6242 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6243 // ElemLVal.reduce_fini = fini; 6244 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6245 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6246 llvm::Value *FiniAddr = Fini 6247 ? CGF.EmitCastToVoidPtr(Fini) 6248 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6249 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6250 // ElemLVal.reduce_comb = comb; 6251 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6252 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6253 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6254 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6255 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6256 // ElemLVal.flags = 0; 6257 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6258 if (DelayedCreation) { 6259 CGF.EmitStoreOfScalar( 6260 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6261 FlagsLVal); 6262 } else 6263 CGF.EmitNullInitialization(FlagsLVal.getAddress(CGF), 6264 FlagsLVal.getType()); 6265 } 6266 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6267 // *data); 6268 llvm::Value *Args[] = { 6269 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6270 /*isSigned=*/true), 6271 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6272 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6273 CGM.VoidPtrTy)}; 6274 return CGF.EmitRuntimeCall( 6275 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6276 } 6277 6278 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6279 SourceLocation Loc, 6280 ReductionCodeGen &RCG, 6281 unsigned N) { 6282 auto Sizes = RCG.getSizes(N); 6283 // Emit threadprivate global variable if the type is non-constant 6284 // (Sizes.second = nullptr). 6285 if (Sizes.second) { 6286 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6287 /*isSigned=*/false); 6288 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6289 CGF, CGM.getContext().getSizeType(), 6290 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6291 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6292 } 6293 // Store address of the original reduction item if custom initializer is used. 6294 if (RCG.usesReductionInitializer(N)) { 6295 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6296 CGF, CGM.getContext().VoidPtrTy, 6297 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6298 CGF.Builder.CreateStore( 6299 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6300 RCG.getSharedLValue(N).getPointer(CGF), CGM.VoidPtrTy), 6301 SharedAddr, /*IsVolatile=*/false); 6302 } 6303 } 6304 6305 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6306 SourceLocation Loc, 6307 llvm::Value *ReductionsPtr, 6308 LValue SharedLVal) { 6309 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6310 // *d); 6311 llvm::Value *Args[] = {CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), 6312 CGM.IntTy, 6313 /*isSigned=*/true), 6314 ReductionsPtr, 6315 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6316 SharedLVal.getPointer(CGF), CGM.VoidPtrTy)}; 6317 return Address( 6318 CGF.EmitRuntimeCall( 6319 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6320 SharedLVal.getAlignment()); 6321 } 6322 6323 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6324 SourceLocation Loc) { 6325 if (!CGF.HaveInsertPoint()) 6326 return; 6327 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6328 // global_tid); 6329 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6330 // Ignore return result until untied tasks are supported. 6331 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6332 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6333 Region->emitUntiedSwitch(CGF); 6334 } 6335 6336 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6337 OpenMPDirectiveKind InnerKind, 6338 const RegionCodeGenTy &CodeGen, 6339 bool HasCancel) { 6340 if (!CGF.HaveInsertPoint()) 6341 return; 6342 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6343 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6344 } 6345 6346 namespace { 6347 enum RTCancelKind { 6348 CancelNoreq = 0, 6349 CancelParallel = 1, 6350 CancelLoop = 2, 6351 CancelSections = 3, 6352 CancelTaskgroup = 4 6353 }; 6354 } // anonymous namespace 6355 6356 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6357 RTCancelKind CancelKind = CancelNoreq; 6358 if (CancelRegion == OMPD_parallel) 6359 CancelKind = CancelParallel; 6360 else if (CancelRegion == OMPD_for) 6361 CancelKind = CancelLoop; 6362 else if (CancelRegion == OMPD_sections) 6363 CancelKind = CancelSections; 6364 else { 6365 assert(CancelRegion == OMPD_taskgroup); 6366 CancelKind = CancelTaskgroup; 6367 } 6368 return CancelKind; 6369 } 6370 6371 void CGOpenMPRuntime::emitCancellationPointCall( 6372 CodeGenFunction &CGF, SourceLocation Loc, 6373 OpenMPDirectiveKind CancelRegion) { 6374 if (!CGF.HaveInsertPoint()) 6375 return; 6376 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6377 // global_tid, kmp_int32 cncl_kind); 6378 if (auto *OMPRegionInfo = 6379 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6380 // For 'cancellation point taskgroup', the task region info may not have a 6381 // cancel. This may instead happen in another adjacent task. 6382 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6383 llvm::Value *Args[] = { 6384 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6385 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6386 // Ignore return result until untied tasks are supported. 6387 llvm::Value *Result = CGF.EmitRuntimeCall( 6388 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6389 // if (__kmpc_cancellationpoint()) { 6390 // exit from construct; 6391 // } 6392 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6393 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6394 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6395 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6396 CGF.EmitBlock(ExitBB); 6397 // exit from construct; 6398 CodeGenFunction::JumpDest CancelDest = 6399 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6400 CGF.EmitBranchThroughCleanup(CancelDest); 6401 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6402 } 6403 } 6404 } 6405 6406 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6407 const Expr *IfCond, 6408 OpenMPDirectiveKind CancelRegion) { 6409 if (!CGF.HaveInsertPoint()) 6410 return; 6411 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6412 // kmp_int32 cncl_kind); 6413 if (auto *OMPRegionInfo = 6414 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6415 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6416 PrePostActionTy &) { 6417 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6418 llvm::Value *Args[] = { 6419 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6420 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6421 // Ignore return result until untied tasks are supported. 6422 llvm::Value *Result = CGF.EmitRuntimeCall( 6423 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6424 // if (__kmpc_cancel()) { 6425 // exit from construct; 6426 // } 6427 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6428 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6429 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6430 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6431 CGF.EmitBlock(ExitBB); 6432 // exit from construct; 6433 CodeGenFunction::JumpDest CancelDest = 6434 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6435 CGF.EmitBranchThroughCleanup(CancelDest); 6436 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6437 }; 6438 if (IfCond) { 6439 emitIfClause(CGF, IfCond, ThenGen, 6440 [](CodeGenFunction &, PrePostActionTy &) {}); 6441 } else { 6442 RegionCodeGenTy ThenRCG(ThenGen); 6443 ThenRCG(CGF); 6444 } 6445 } 6446 } 6447 6448 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6449 const OMPExecutableDirective &D, StringRef ParentName, 6450 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6451 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6452 assert(!ParentName.empty() && "Invalid target region parent name!"); 6453 HasEmittedTargetRegion = true; 6454 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6455 IsOffloadEntry, CodeGen); 6456 } 6457 6458 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6459 const OMPExecutableDirective &D, StringRef ParentName, 6460 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6461 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6462 // Create a unique name for the entry function using the source location 6463 // information of the current target region. The name will be something like: 6464 // 6465 // __omp_offloading_DD_FFFF_PP_lBB 6466 // 6467 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6468 // mangled name of the function that encloses the target region and BB is the 6469 // line number of the target region. 6470 6471 unsigned DeviceID; 6472 unsigned FileID; 6473 unsigned Line; 6474 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6475 Line); 6476 SmallString<64> EntryFnName; 6477 { 6478 llvm::raw_svector_ostream OS(EntryFnName); 6479 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6480 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6481 } 6482 6483 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6484 6485 CodeGenFunction CGF(CGM, true); 6486 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6487 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6488 6489 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS, D.getBeginLoc()); 6490 6491 // If this target outline function is not an offload entry, we don't need to 6492 // register it. 6493 if (!IsOffloadEntry) 6494 return; 6495 6496 // The target region ID is used by the runtime library to identify the current 6497 // target region, so it only has to be unique and not necessarily point to 6498 // anything. It could be the pointer to the outlined function that implements 6499 // the target region, but we aren't using that so that the compiler doesn't 6500 // need to keep that, and could therefore inline the host function if proven 6501 // worthwhile during optimization. In the other hand, if emitting code for the 6502 // device, the ID has to be the function address so that it can retrieved from 6503 // the offloading entry and launched by the runtime library. We also mark the 6504 // outlined function to have external linkage in case we are emitting code for 6505 // the device, because these functions will be entry points to the device. 6506 6507 if (CGM.getLangOpts().OpenMPIsDevice) { 6508 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6509 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6510 OutlinedFn->setDSOLocal(false); 6511 } else { 6512 std::string Name = getName({EntryFnName, "region_id"}); 6513 OutlinedFnID = new llvm::GlobalVariable( 6514 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6515 llvm::GlobalValue::WeakAnyLinkage, 6516 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6517 } 6518 6519 // Register the information for the entry associated with this target region. 6520 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6521 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6522 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6523 } 6524 6525 /// Checks if the expression is constant or does not have non-trivial function 6526 /// calls. 6527 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6528 // We can skip constant expressions. 6529 // We can skip expressions with trivial calls or simple expressions. 6530 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6531 !E->hasNonTrivialCall(Ctx)) && 6532 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6533 } 6534 6535 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6536 const Stmt *Body) { 6537 const Stmt *Child = Body->IgnoreContainers(); 6538 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6539 Child = nullptr; 6540 for (const Stmt *S : C->body()) { 6541 if (const auto *E = dyn_cast<Expr>(S)) { 6542 if (isTrivial(Ctx, E)) 6543 continue; 6544 } 6545 // Some of the statements can be ignored. 6546 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6547 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6548 continue; 6549 // Analyze declarations. 6550 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6551 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6552 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6553 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6554 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6555 isa<UsingDirectiveDecl>(D) || 6556 isa<OMPDeclareReductionDecl>(D) || 6557 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6558 return true; 6559 const auto *VD = dyn_cast<VarDecl>(D); 6560 if (!VD) 6561 return false; 6562 return VD->isConstexpr() || 6563 ((VD->getType().isTrivialType(Ctx) || 6564 VD->getType()->isReferenceType()) && 6565 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6566 })) 6567 continue; 6568 } 6569 // Found multiple children - cannot get the one child only. 6570 if (Child) 6571 return nullptr; 6572 Child = S; 6573 } 6574 if (Child) 6575 Child = Child->IgnoreContainers(); 6576 } 6577 return Child; 6578 } 6579 6580 /// Emit the number of teams for a target directive. Inspect the num_teams 6581 /// clause associated with a teams construct combined or closely nested 6582 /// with the target directive. 6583 /// 6584 /// Emit a team of size one for directives such as 'target parallel' that 6585 /// have no associated teams construct. 6586 /// 6587 /// Otherwise, return nullptr. 6588 static llvm::Value * 6589 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6590 const OMPExecutableDirective &D) { 6591 assert(!CGF.getLangOpts().OpenMPIsDevice && 6592 "Clauses associated with the teams directive expected to be emitted " 6593 "only for the host!"); 6594 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6595 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6596 "Expected target-based executable directive."); 6597 CGBuilderTy &Bld = CGF.Builder; 6598 switch (DirectiveKind) { 6599 case OMPD_target: { 6600 const auto *CS = D.getInnermostCapturedStmt(); 6601 const auto *Body = 6602 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6603 const Stmt *ChildStmt = 6604 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6605 if (const auto *NestedDir = 6606 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6607 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6608 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6609 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6610 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6611 const Expr *NumTeams = 6612 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6613 llvm::Value *NumTeamsVal = 6614 CGF.EmitScalarExpr(NumTeams, 6615 /*IgnoreResultAssign*/ true); 6616 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6617 /*isSigned=*/true); 6618 } 6619 return Bld.getInt32(0); 6620 } 6621 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6622 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6623 return Bld.getInt32(1); 6624 return Bld.getInt32(0); 6625 } 6626 return nullptr; 6627 } 6628 case OMPD_target_teams: 6629 case OMPD_target_teams_distribute: 6630 case OMPD_target_teams_distribute_simd: 6631 case OMPD_target_teams_distribute_parallel_for: 6632 case OMPD_target_teams_distribute_parallel_for_simd: { 6633 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6634 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6635 const Expr *NumTeams = 6636 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6637 llvm::Value *NumTeamsVal = 6638 CGF.EmitScalarExpr(NumTeams, 6639 /*IgnoreResultAssign*/ true); 6640 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6641 /*isSigned=*/true); 6642 } 6643 return Bld.getInt32(0); 6644 } 6645 case OMPD_target_parallel: 6646 case OMPD_target_parallel_for: 6647 case OMPD_target_parallel_for_simd: 6648 case OMPD_target_simd: 6649 return Bld.getInt32(1); 6650 case OMPD_parallel: 6651 case OMPD_for: 6652 case OMPD_parallel_for: 6653 case OMPD_parallel_master: 6654 case OMPD_parallel_sections: 6655 case OMPD_for_simd: 6656 case OMPD_parallel_for_simd: 6657 case OMPD_cancel: 6658 case OMPD_cancellation_point: 6659 case OMPD_ordered: 6660 case OMPD_threadprivate: 6661 case OMPD_allocate: 6662 case OMPD_task: 6663 case OMPD_simd: 6664 case OMPD_sections: 6665 case OMPD_section: 6666 case OMPD_single: 6667 case OMPD_master: 6668 case OMPD_critical: 6669 case OMPD_taskyield: 6670 case OMPD_barrier: 6671 case OMPD_taskwait: 6672 case OMPD_taskgroup: 6673 case OMPD_atomic: 6674 case OMPD_flush: 6675 case OMPD_teams: 6676 case OMPD_target_data: 6677 case OMPD_target_exit_data: 6678 case OMPD_target_enter_data: 6679 case OMPD_distribute: 6680 case OMPD_distribute_simd: 6681 case OMPD_distribute_parallel_for: 6682 case OMPD_distribute_parallel_for_simd: 6683 case OMPD_teams_distribute: 6684 case OMPD_teams_distribute_simd: 6685 case OMPD_teams_distribute_parallel_for: 6686 case OMPD_teams_distribute_parallel_for_simd: 6687 case OMPD_target_update: 6688 case OMPD_declare_simd: 6689 case OMPD_declare_variant: 6690 case OMPD_declare_target: 6691 case OMPD_end_declare_target: 6692 case OMPD_declare_reduction: 6693 case OMPD_declare_mapper: 6694 case OMPD_taskloop: 6695 case OMPD_taskloop_simd: 6696 case OMPD_master_taskloop: 6697 case OMPD_master_taskloop_simd: 6698 case OMPD_parallel_master_taskloop: 6699 case OMPD_parallel_master_taskloop_simd: 6700 case OMPD_requires: 6701 case OMPD_unknown: 6702 break; 6703 } 6704 llvm_unreachable("Unexpected directive kind."); 6705 } 6706 6707 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6708 llvm::Value *DefaultThreadLimitVal) { 6709 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6710 CGF.getContext(), CS->getCapturedStmt()); 6711 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6712 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6713 llvm::Value *NumThreads = nullptr; 6714 llvm::Value *CondVal = nullptr; 6715 // Handle if clause. If if clause present, the number of threads is 6716 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6717 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6718 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6719 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6720 const OMPIfClause *IfClause = nullptr; 6721 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6722 if (C->getNameModifier() == OMPD_unknown || 6723 C->getNameModifier() == OMPD_parallel) { 6724 IfClause = C; 6725 break; 6726 } 6727 } 6728 if (IfClause) { 6729 const Expr *Cond = IfClause->getCondition(); 6730 bool Result; 6731 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6732 if (!Result) 6733 return CGF.Builder.getInt32(1); 6734 } else { 6735 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6736 if (const auto *PreInit = 6737 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6738 for (const auto *I : PreInit->decls()) { 6739 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6740 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6741 } else { 6742 CodeGenFunction::AutoVarEmission Emission = 6743 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6744 CGF.EmitAutoVarCleanups(Emission); 6745 } 6746 } 6747 } 6748 CondVal = CGF.EvaluateExprAsBool(Cond); 6749 } 6750 } 6751 } 6752 // Check the value of num_threads clause iff if clause was not specified 6753 // or is not evaluated to false. 6754 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6755 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6756 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6757 const auto *NumThreadsClause = 6758 Dir->getSingleClause<OMPNumThreadsClause>(); 6759 CodeGenFunction::LexicalScope Scope( 6760 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6761 if (const auto *PreInit = 6762 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6763 for (const auto *I : PreInit->decls()) { 6764 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6765 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6766 } else { 6767 CodeGenFunction::AutoVarEmission Emission = 6768 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6769 CGF.EmitAutoVarCleanups(Emission); 6770 } 6771 } 6772 } 6773 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6774 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6775 /*isSigned=*/false); 6776 if (DefaultThreadLimitVal) 6777 NumThreads = CGF.Builder.CreateSelect( 6778 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6779 DefaultThreadLimitVal, NumThreads); 6780 } else { 6781 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6782 : CGF.Builder.getInt32(0); 6783 } 6784 // Process condition of the if clause. 6785 if (CondVal) { 6786 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6787 CGF.Builder.getInt32(1)); 6788 } 6789 return NumThreads; 6790 } 6791 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6792 return CGF.Builder.getInt32(1); 6793 return DefaultThreadLimitVal; 6794 } 6795 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6796 : CGF.Builder.getInt32(0); 6797 } 6798 6799 /// Emit the number of threads for a target directive. Inspect the 6800 /// thread_limit clause associated with a teams construct combined or closely 6801 /// nested with the target directive. 6802 /// 6803 /// Emit the num_threads clause for directives such as 'target parallel' that 6804 /// have no associated teams construct. 6805 /// 6806 /// Otherwise, return nullptr. 6807 static llvm::Value * 6808 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6809 const OMPExecutableDirective &D) { 6810 assert(!CGF.getLangOpts().OpenMPIsDevice && 6811 "Clauses associated with the teams directive expected to be emitted " 6812 "only for the host!"); 6813 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6814 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6815 "Expected target-based executable directive."); 6816 CGBuilderTy &Bld = CGF.Builder; 6817 llvm::Value *ThreadLimitVal = nullptr; 6818 llvm::Value *NumThreadsVal = nullptr; 6819 switch (DirectiveKind) { 6820 case OMPD_target: { 6821 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6822 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6823 return NumThreads; 6824 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6825 CGF.getContext(), CS->getCapturedStmt()); 6826 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6827 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6828 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6829 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6830 const auto *ThreadLimitClause = 6831 Dir->getSingleClause<OMPThreadLimitClause>(); 6832 CodeGenFunction::LexicalScope Scope( 6833 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6834 if (const auto *PreInit = 6835 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6836 for (const auto *I : PreInit->decls()) { 6837 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6838 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6839 } else { 6840 CodeGenFunction::AutoVarEmission Emission = 6841 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6842 CGF.EmitAutoVarCleanups(Emission); 6843 } 6844 } 6845 } 6846 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6847 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6848 ThreadLimitVal = 6849 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6850 } 6851 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6852 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6853 CS = Dir->getInnermostCapturedStmt(); 6854 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6855 CGF.getContext(), CS->getCapturedStmt()); 6856 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6857 } 6858 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6859 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6860 CS = Dir->getInnermostCapturedStmt(); 6861 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6862 return NumThreads; 6863 } 6864 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6865 return Bld.getInt32(1); 6866 } 6867 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6868 } 6869 case OMPD_target_teams: { 6870 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6871 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6872 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6873 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6874 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6875 ThreadLimitVal = 6876 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6877 } 6878 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6879 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6880 return NumThreads; 6881 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6882 CGF.getContext(), CS->getCapturedStmt()); 6883 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6884 if (Dir->getDirectiveKind() == OMPD_distribute) { 6885 CS = Dir->getInnermostCapturedStmt(); 6886 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6887 return NumThreads; 6888 } 6889 } 6890 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6891 } 6892 case OMPD_target_teams_distribute: 6893 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6894 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6895 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6896 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6897 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6898 ThreadLimitVal = 6899 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6900 } 6901 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6902 case OMPD_target_parallel: 6903 case OMPD_target_parallel_for: 6904 case OMPD_target_parallel_for_simd: 6905 case OMPD_target_teams_distribute_parallel_for: 6906 case OMPD_target_teams_distribute_parallel_for_simd: { 6907 llvm::Value *CondVal = nullptr; 6908 // Handle if clause. If if clause present, the number of threads is 6909 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6910 if (D.hasClausesOfKind<OMPIfClause>()) { 6911 const OMPIfClause *IfClause = nullptr; 6912 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6913 if (C->getNameModifier() == OMPD_unknown || 6914 C->getNameModifier() == OMPD_parallel) { 6915 IfClause = C; 6916 break; 6917 } 6918 } 6919 if (IfClause) { 6920 const Expr *Cond = IfClause->getCondition(); 6921 bool Result; 6922 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6923 if (!Result) 6924 return Bld.getInt32(1); 6925 } else { 6926 CodeGenFunction::RunCleanupsScope Scope(CGF); 6927 CondVal = CGF.EvaluateExprAsBool(Cond); 6928 } 6929 } 6930 } 6931 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6932 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6933 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6934 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6935 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6936 ThreadLimitVal = 6937 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6938 } 6939 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6940 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6941 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6942 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6943 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6944 NumThreadsVal = 6945 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6946 ThreadLimitVal = ThreadLimitVal 6947 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6948 ThreadLimitVal), 6949 NumThreadsVal, ThreadLimitVal) 6950 : NumThreadsVal; 6951 } 6952 if (!ThreadLimitVal) 6953 ThreadLimitVal = Bld.getInt32(0); 6954 if (CondVal) 6955 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6956 return ThreadLimitVal; 6957 } 6958 case OMPD_target_teams_distribute_simd: 6959 case OMPD_target_simd: 6960 return Bld.getInt32(1); 6961 case OMPD_parallel: 6962 case OMPD_for: 6963 case OMPD_parallel_for: 6964 case OMPD_parallel_master: 6965 case OMPD_parallel_sections: 6966 case OMPD_for_simd: 6967 case OMPD_parallel_for_simd: 6968 case OMPD_cancel: 6969 case OMPD_cancellation_point: 6970 case OMPD_ordered: 6971 case OMPD_threadprivate: 6972 case OMPD_allocate: 6973 case OMPD_task: 6974 case OMPD_simd: 6975 case OMPD_sections: 6976 case OMPD_section: 6977 case OMPD_single: 6978 case OMPD_master: 6979 case OMPD_critical: 6980 case OMPD_taskyield: 6981 case OMPD_barrier: 6982 case OMPD_taskwait: 6983 case OMPD_taskgroup: 6984 case OMPD_atomic: 6985 case OMPD_flush: 6986 case OMPD_teams: 6987 case OMPD_target_data: 6988 case OMPD_target_exit_data: 6989 case OMPD_target_enter_data: 6990 case OMPD_distribute: 6991 case OMPD_distribute_simd: 6992 case OMPD_distribute_parallel_for: 6993 case OMPD_distribute_parallel_for_simd: 6994 case OMPD_teams_distribute: 6995 case OMPD_teams_distribute_simd: 6996 case OMPD_teams_distribute_parallel_for: 6997 case OMPD_teams_distribute_parallel_for_simd: 6998 case OMPD_target_update: 6999 case OMPD_declare_simd: 7000 case OMPD_declare_variant: 7001 case OMPD_declare_target: 7002 case OMPD_end_declare_target: 7003 case OMPD_declare_reduction: 7004 case OMPD_declare_mapper: 7005 case OMPD_taskloop: 7006 case OMPD_taskloop_simd: 7007 case OMPD_master_taskloop: 7008 case OMPD_master_taskloop_simd: 7009 case OMPD_parallel_master_taskloop: 7010 case OMPD_parallel_master_taskloop_simd: 7011 case OMPD_requires: 7012 case OMPD_unknown: 7013 break; 7014 } 7015 llvm_unreachable("Unsupported directive kind."); 7016 } 7017 7018 namespace { 7019 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 7020 7021 // Utility to handle information from clauses associated with a given 7022 // construct that use mappable expressions (e.g. 'map' clause, 'to' clause). 7023 // It provides a convenient interface to obtain the information and generate 7024 // code for that information. 7025 class MappableExprsHandler { 7026 public: 7027 /// Values for bit flags used to specify the mapping type for 7028 /// offloading. 7029 enum OpenMPOffloadMappingFlags : uint64_t { 7030 /// No flags 7031 OMP_MAP_NONE = 0x0, 7032 /// Allocate memory on the device and move data from host to device. 7033 OMP_MAP_TO = 0x01, 7034 /// Allocate memory on the device and move data from device to host. 7035 OMP_MAP_FROM = 0x02, 7036 /// Always perform the requested mapping action on the element, even 7037 /// if it was already mapped before. 7038 OMP_MAP_ALWAYS = 0x04, 7039 /// Delete the element from the device environment, ignoring the 7040 /// current reference count associated with the element. 7041 OMP_MAP_DELETE = 0x08, 7042 /// The element being mapped is a pointer-pointee pair; both the 7043 /// pointer and the pointee should be mapped. 7044 OMP_MAP_PTR_AND_OBJ = 0x10, 7045 /// This flags signals that the base address of an entry should be 7046 /// passed to the target kernel as an argument. 7047 OMP_MAP_TARGET_PARAM = 0x20, 7048 /// Signal that the runtime library has to return the device pointer 7049 /// in the current position for the data being mapped. Used when we have the 7050 /// use_device_ptr clause. 7051 OMP_MAP_RETURN_PARAM = 0x40, 7052 /// This flag signals that the reference being passed is a pointer to 7053 /// private data. 7054 OMP_MAP_PRIVATE = 0x80, 7055 /// Pass the element to the device by value. 7056 OMP_MAP_LITERAL = 0x100, 7057 /// Implicit map 7058 OMP_MAP_IMPLICIT = 0x200, 7059 /// Close is a hint to the runtime to allocate memory close to 7060 /// the target device. 7061 OMP_MAP_CLOSE = 0x400, 7062 /// The 16 MSBs of the flags indicate whether the entry is member of some 7063 /// struct/class. 7064 OMP_MAP_MEMBER_OF = 0xffff000000000000, 7065 LLVM_MARK_AS_BITMASK_ENUM(/* LargestFlag = */ OMP_MAP_MEMBER_OF), 7066 }; 7067 7068 /// Get the offset of the OMP_MAP_MEMBER_OF field. 7069 static unsigned getFlagMemberOffset() { 7070 unsigned Offset = 0; 7071 for (uint64_t Remain = OMP_MAP_MEMBER_OF; !(Remain & 1); 7072 Remain = Remain >> 1) 7073 Offset++; 7074 return Offset; 7075 } 7076 7077 /// Class that associates information with a base pointer to be passed to the 7078 /// runtime library. 7079 class BasePointerInfo { 7080 /// The base pointer. 7081 llvm::Value *Ptr = nullptr; 7082 /// The base declaration that refers to this device pointer, or null if 7083 /// there is none. 7084 const ValueDecl *DevPtrDecl = nullptr; 7085 7086 public: 7087 BasePointerInfo(llvm::Value *Ptr, const ValueDecl *DevPtrDecl = nullptr) 7088 : Ptr(Ptr), DevPtrDecl(DevPtrDecl) {} 7089 llvm::Value *operator*() const { return Ptr; } 7090 const ValueDecl *getDevicePtrDecl() const { return DevPtrDecl; } 7091 void setDevicePtrDecl(const ValueDecl *D) { DevPtrDecl = D; } 7092 }; 7093 7094 using MapBaseValuesArrayTy = SmallVector<BasePointerInfo, 4>; 7095 using MapValuesArrayTy = SmallVector<llvm::Value *, 4>; 7096 using MapFlagsArrayTy = SmallVector<OpenMPOffloadMappingFlags, 4>; 7097 7098 /// Map between a struct and the its lowest & highest elements which have been 7099 /// mapped. 7100 /// [ValueDecl *] --> {LE(FieldIndex, Pointer), 7101 /// HE(FieldIndex, Pointer)} 7102 struct StructRangeInfoTy { 7103 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> LowestElem = { 7104 0, Address::invalid()}; 7105 std::pair<unsigned /*FieldIndex*/, Address /*Pointer*/> HighestElem = { 7106 0, Address::invalid()}; 7107 Address Base = Address::invalid(); 7108 }; 7109 7110 private: 7111 /// Kind that defines how a device pointer has to be returned. 7112 struct MapInfo { 7113 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 7114 OpenMPMapClauseKind MapType = OMPC_MAP_unknown; 7115 ArrayRef<OpenMPMapModifierKind> MapModifiers; 7116 bool ReturnDevicePointer = false; 7117 bool IsImplicit = false; 7118 7119 MapInfo() = default; 7120 MapInfo( 7121 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7122 OpenMPMapClauseKind MapType, 7123 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7124 bool ReturnDevicePointer, bool IsImplicit) 7125 : Components(Components), MapType(MapType), MapModifiers(MapModifiers), 7126 ReturnDevicePointer(ReturnDevicePointer), IsImplicit(IsImplicit) {} 7127 }; 7128 7129 /// If use_device_ptr is used on a pointer which is a struct member and there 7130 /// is no map information about it, then emission of that entry is deferred 7131 /// until the whole struct has been processed. 7132 struct DeferredDevicePtrEntryTy { 7133 const Expr *IE = nullptr; 7134 const ValueDecl *VD = nullptr; 7135 7136 DeferredDevicePtrEntryTy(const Expr *IE, const ValueDecl *VD) 7137 : IE(IE), VD(VD) {} 7138 }; 7139 7140 /// The target directive from where the mappable clauses were extracted. It 7141 /// is either a executable directive or a user-defined mapper directive. 7142 llvm::PointerUnion<const OMPExecutableDirective *, 7143 const OMPDeclareMapperDecl *> 7144 CurDir; 7145 7146 /// Function the directive is being generated for. 7147 CodeGenFunction &CGF; 7148 7149 /// Set of all first private variables in the current directive. 7150 /// bool data is set to true if the variable is implicitly marked as 7151 /// firstprivate, false otherwise. 7152 llvm::DenseMap<CanonicalDeclPtr<const VarDecl>, bool> FirstPrivateDecls; 7153 7154 /// Map between device pointer declarations and their expression components. 7155 /// The key value for declarations in 'this' is null. 7156 llvm::DenseMap< 7157 const ValueDecl *, 7158 SmallVector<OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>> 7159 DevPointersMap; 7160 7161 llvm::Value *getExprTypeSize(const Expr *E) const { 7162 QualType ExprTy = E->getType().getCanonicalType(); 7163 7164 // Reference types are ignored for mapping purposes. 7165 if (const auto *RefTy = ExprTy->getAs<ReferenceType>()) 7166 ExprTy = RefTy->getPointeeType().getCanonicalType(); 7167 7168 // Given that an array section is considered a built-in type, we need to 7169 // do the calculation based on the length of the section instead of relying 7170 // on CGF.getTypeSize(E->getType()). 7171 if (const auto *OAE = dyn_cast<OMPArraySectionExpr>(E)) { 7172 QualType BaseTy = OMPArraySectionExpr::getBaseOriginalType( 7173 OAE->getBase()->IgnoreParenImpCasts()) 7174 .getCanonicalType(); 7175 7176 // If there is no length associated with the expression and lower bound is 7177 // not specified too, that means we are using the whole length of the 7178 // base. 7179 if (!OAE->getLength() && OAE->getColonLoc().isValid() && 7180 !OAE->getLowerBound()) 7181 return CGF.getTypeSize(BaseTy); 7182 7183 llvm::Value *ElemSize; 7184 if (const auto *PTy = BaseTy->getAs<PointerType>()) { 7185 ElemSize = CGF.getTypeSize(PTy->getPointeeType().getCanonicalType()); 7186 } else { 7187 const auto *ATy = cast<ArrayType>(BaseTy.getTypePtr()); 7188 assert(ATy && "Expecting array type if not a pointer type."); 7189 ElemSize = CGF.getTypeSize(ATy->getElementType().getCanonicalType()); 7190 } 7191 7192 // If we don't have a length at this point, that is because we have an 7193 // array section with a single element. 7194 if (!OAE->getLength() && OAE->getColonLoc().isInvalid()) 7195 return ElemSize; 7196 7197 if (const Expr *LenExpr = OAE->getLength()) { 7198 llvm::Value *LengthVal = CGF.EmitScalarExpr(LenExpr); 7199 LengthVal = CGF.EmitScalarConversion(LengthVal, LenExpr->getType(), 7200 CGF.getContext().getSizeType(), 7201 LenExpr->getExprLoc()); 7202 return CGF.Builder.CreateNUWMul(LengthVal, ElemSize); 7203 } 7204 assert(!OAE->getLength() && OAE->getColonLoc().isValid() && 7205 OAE->getLowerBound() && "expected array_section[lb:]."); 7206 // Size = sizetype - lb * elemtype; 7207 llvm::Value *LengthVal = CGF.getTypeSize(BaseTy); 7208 llvm::Value *LBVal = CGF.EmitScalarExpr(OAE->getLowerBound()); 7209 LBVal = CGF.EmitScalarConversion(LBVal, OAE->getLowerBound()->getType(), 7210 CGF.getContext().getSizeType(), 7211 OAE->getLowerBound()->getExprLoc()); 7212 LBVal = CGF.Builder.CreateNUWMul(LBVal, ElemSize); 7213 llvm::Value *Cmp = CGF.Builder.CreateICmpUGT(LengthVal, LBVal); 7214 llvm::Value *TrueVal = CGF.Builder.CreateNUWSub(LengthVal, LBVal); 7215 LengthVal = CGF.Builder.CreateSelect( 7216 Cmp, TrueVal, llvm::ConstantInt::get(CGF.SizeTy, 0)); 7217 return LengthVal; 7218 } 7219 return CGF.getTypeSize(ExprTy); 7220 } 7221 7222 /// Return the corresponding bits for a given map clause modifier. Add 7223 /// a flag marking the map as a pointer if requested. Add a flag marking the 7224 /// map as the first one of a series of maps that relate to the same map 7225 /// expression. 7226 OpenMPOffloadMappingFlags getMapTypeBits( 7227 OpenMPMapClauseKind MapType, ArrayRef<OpenMPMapModifierKind> MapModifiers, 7228 bool IsImplicit, bool AddPtrFlag, bool AddIsTargetParamFlag) const { 7229 OpenMPOffloadMappingFlags Bits = 7230 IsImplicit ? OMP_MAP_IMPLICIT : OMP_MAP_NONE; 7231 switch (MapType) { 7232 case OMPC_MAP_alloc: 7233 case OMPC_MAP_release: 7234 // alloc and release is the default behavior in the runtime library, i.e. 7235 // if we don't pass any bits alloc/release that is what the runtime is 7236 // going to do. Therefore, we don't need to signal anything for these two 7237 // type modifiers. 7238 break; 7239 case OMPC_MAP_to: 7240 Bits |= OMP_MAP_TO; 7241 break; 7242 case OMPC_MAP_from: 7243 Bits |= OMP_MAP_FROM; 7244 break; 7245 case OMPC_MAP_tofrom: 7246 Bits |= OMP_MAP_TO | OMP_MAP_FROM; 7247 break; 7248 case OMPC_MAP_delete: 7249 Bits |= OMP_MAP_DELETE; 7250 break; 7251 case OMPC_MAP_unknown: 7252 llvm_unreachable("Unexpected map type!"); 7253 } 7254 if (AddPtrFlag) 7255 Bits |= OMP_MAP_PTR_AND_OBJ; 7256 if (AddIsTargetParamFlag) 7257 Bits |= OMP_MAP_TARGET_PARAM; 7258 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_always) 7259 != MapModifiers.end()) 7260 Bits |= OMP_MAP_ALWAYS; 7261 if (llvm::find(MapModifiers, OMPC_MAP_MODIFIER_close) 7262 != MapModifiers.end()) 7263 Bits |= OMP_MAP_CLOSE; 7264 return Bits; 7265 } 7266 7267 /// Return true if the provided expression is a final array section. A 7268 /// final array section, is one whose length can't be proved to be one. 7269 bool isFinalArraySectionExpression(const Expr *E) const { 7270 const auto *OASE = dyn_cast<OMPArraySectionExpr>(E); 7271 7272 // It is not an array section and therefore not a unity-size one. 7273 if (!OASE) 7274 return false; 7275 7276 // An array section with no colon always refer to a single element. 7277 if (OASE->getColonLoc().isInvalid()) 7278 return false; 7279 7280 const Expr *Length = OASE->getLength(); 7281 7282 // If we don't have a length we have to check if the array has size 1 7283 // for this dimension. Also, we should always expect a length if the 7284 // base type is pointer. 7285 if (!Length) { 7286 QualType BaseQTy = OMPArraySectionExpr::getBaseOriginalType( 7287 OASE->getBase()->IgnoreParenImpCasts()) 7288 .getCanonicalType(); 7289 if (const auto *ATy = dyn_cast<ConstantArrayType>(BaseQTy.getTypePtr())) 7290 return ATy->getSize().getSExtValue() != 1; 7291 // If we don't have a constant dimension length, we have to consider 7292 // the current section as having any size, so it is not necessarily 7293 // unitary. If it happen to be unity size, that's user fault. 7294 return true; 7295 } 7296 7297 // Check if the length evaluates to 1. 7298 Expr::EvalResult Result; 7299 if (!Length->EvaluateAsInt(Result, CGF.getContext())) 7300 return true; // Can have more that size 1. 7301 7302 llvm::APSInt ConstLength = Result.Val.getInt(); 7303 return ConstLength.getSExtValue() != 1; 7304 } 7305 7306 /// Generate the base pointers, section pointers, sizes and map type 7307 /// bits for the provided map type, map modifier, and expression components. 7308 /// \a IsFirstComponent should be set to true if the provided set of 7309 /// components is the first associated with a capture. 7310 void generateInfoForComponentList( 7311 OpenMPMapClauseKind MapType, 7312 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7313 OMPClauseMappableExprCommon::MappableExprComponentListRef Components, 7314 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 7315 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 7316 StructRangeInfoTy &PartialStruct, bool IsFirstComponentList, 7317 bool IsImplicit, 7318 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 7319 OverlappedElements = llvm::None) const { 7320 // The following summarizes what has to be generated for each map and the 7321 // types below. The generated information is expressed in this order: 7322 // base pointer, section pointer, size, flags 7323 // (to add to the ones that come from the map type and modifier). 7324 // 7325 // double d; 7326 // int i[100]; 7327 // float *p; 7328 // 7329 // struct S1 { 7330 // int i; 7331 // float f[50]; 7332 // } 7333 // struct S2 { 7334 // int i; 7335 // float f[50]; 7336 // S1 s; 7337 // double *p; 7338 // struct S2 *ps; 7339 // } 7340 // S2 s; 7341 // S2 *ps; 7342 // 7343 // map(d) 7344 // &d, &d, sizeof(double), TARGET_PARAM | TO | FROM 7345 // 7346 // map(i) 7347 // &i, &i, 100*sizeof(int), TARGET_PARAM | TO | FROM 7348 // 7349 // map(i[1:23]) 7350 // &i(=&i[0]), &i[1], 23*sizeof(int), TARGET_PARAM | TO | FROM 7351 // 7352 // map(p) 7353 // &p, &p, sizeof(float*), TARGET_PARAM | TO | FROM 7354 // 7355 // map(p[1:24]) 7356 // p, &p[1], 24*sizeof(float), TARGET_PARAM | TO | FROM 7357 // 7358 // map(s) 7359 // &s, &s, sizeof(S2), TARGET_PARAM | TO | FROM 7360 // 7361 // map(s.i) 7362 // &s, &(s.i), sizeof(int), TARGET_PARAM | TO | FROM 7363 // 7364 // map(s.s.f) 7365 // &s, &(s.s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7366 // 7367 // map(s.p) 7368 // &s, &(s.p), sizeof(double*), TARGET_PARAM | TO | FROM 7369 // 7370 // map(to: s.p[:22]) 7371 // &s, &(s.p), sizeof(double*), TARGET_PARAM (*) 7372 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) (**) 7373 // &(s.p), &(s.p[0]), 22*sizeof(double), 7374 // MEMBER_OF(1) | PTR_AND_OBJ | TO (***) 7375 // (*) alloc space for struct members, only this is a target parameter 7376 // (**) map the pointer (nothing to be mapped in this example) (the compiler 7377 // optimizes this entry out, same in the examples below) 7378 // (***) map the pointee (map: to) 7379 // 7380 // map(s.ps) 7381 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7382 // 7383 // map(from: s.ps->s.i) 7384 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7385 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7386 // &(s.ps), &(s.ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7387 // 7388 // map(to: s.ps->ps) 7389 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7390 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7391 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | TO 7392 // 7393 // map(s.ps->ps->ps) 7394 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7395 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7396 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7397 // &(s.ps->ps), &(s.ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7398 // 7399 // map(to: s.ps->ps->s.f[:22]) 7400 // &s, &(s.ps), sizeof(S2*), TARGET_PARAM 7401 // &s, &(s.ps), sizeof(S2*), MEMBER_OF(1) 7402 // &(s.ps), &(s.ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7403 // &(s.ps->ps), &(s.ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7404 // 7405 // map(ps) 7406 // &ps, &ps, sizeof(S2*), TARGET_PARAM | TO | FROM 7407 // 7408 // map(ps->i) 7409 // ps, &(ps->i), sizeof(int), TARGET_PARAM | TO | FROM 7410 // 7411 // map(ps->s.f) 7412 // ps, &(ps->s.f[0]), 50*sizeof(float), TARGET_PARAM | TO | FROM 7413 // 7414 // map(from: ps->p) 7415 // ps, &(ps->p), sizeof(double*), TARGET_PARAM | FROM 7416 // 7417 // map(to: ps->p[:22]) 7418 // ps, &(ps->p), sizeof(double*), TARGET_PARAM 7419 // ps, &(ps->p), sizeof(double*), MEMBER_OF(1) 7420 // &(ps->p), &(ps->p[0]), 22*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | TO 7421 // 7422 // map(ps->ps) 7423 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM | TO | FROM 7424 // 7425 // map(from: ps->ps->s.i) 7426 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7427 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7428 // &(ps->ps), &(ps->ps->s.i), sizeof(int), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7429 // 7430 // map(from: ps->ps->ps) 7431 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7432 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7433 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7434 // 7435 // map(ps->ps->ps->ps) 7436 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7437 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7438 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7439 // &(ps->ps->ps), &(ps->ps->ps->ps), sizeof(S2*), PTR_AND_OBJ | TO | FROM 7440 // 7441 // map(to: ps->ps->ps->s.f[:22]) 7442 // ps, &(ps->ps), sizeof(S2*), TARGET_PARAM 7443 // ps, &(ps->ps), sizeof(S2*), MEMBER_OF(1) 7444 // &(ps->ps), &(ps->ps->ps), sizeof(S2*), MEMBER_OF(1) | PTR_AND_OBJ 7445 // &(ps->ps->ps), &(ps->ps->ps->s.f[0]), 22*sizeof(float), PTR_AND_OBJ | TO 7446 // 7447 // map(to: s.f[:22]) map(from: s.p[:33]) 7448 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1) + 7449 // sizeof(double*) (**), TARGET_PARAM 7450 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | TO 7451 // &s, &(s.p), sizeof(double*), MEMBER_OF(1) 7452 // &(s.p), &(s.p[0]), 33*sizeof(double), MEMBER_OF(1) | PTR_AND_OBJ | FROM 7453 // (*) allocate contiguous space needed to fit all mapped members even if 7454 // we allocate space for members not mapped (in this example, 7455 // s.f[22..49] and s.s are not mapped, yet we must allocate space for 7456 // them as well because they fall between &s.f[0] and &s.p) 7457 // 7458 // map(from: s.f[:22]) map(to: ps->p[:33]) 7459 // &s, &(s.f[0]), 22*sizeof(float), TARGET_PARAM | FROM 7460 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7461 // ps, &(ps->p), sizeof(double*), MEMBER_OF(2) (*) 7462 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(2) | PTR_AND_OBJ | TO 7463 // (*) the struct this entry pertains to is the 2nd element in the list of 7464 // arguments, hence MEMBER_OF(2) 7465 // 7466 // map(from: s.f[:22], s.s) map(to: ps->p[:33]) 7467 // &s, &(s.f[0]), 50*sizeof(float) + sizeof(struct S1), TARGET_PARAM 7468 // &s, &(s.f[0]), 22*sizeof(float), MEMBER_OF(1) | FROM 7469 // &s, &(s.s), sizeof(struct S1), MEMBER_OF(1) | FROM 7470 // ps, &(ps->p), sizeof(S2*), TARGET_PARAM 7471 // ps, &(ps->p), sizeof(double*), MEMBER_OF(4) (*) 7472 // &(ps->p), &(ps->p[0]), 33*sizeof(double), MEMBER_OF(4) | PTR_AND_OBJ | TO 7473 // (*) the struct this entry pertains to is the 4th element in the list 7474 // of arguments, hence MEMBER_OF(4) 7475 7476 // Track if the map information being generated is the first for a capture. 7477 bool IsCaptureFirstInfo = IsFirstComponentList; 7478 // When the variable is on a declare target link or in a to clause with 7479 // unified memory, a reference is needed to hold the host/device address 7480 // of the variable. 7481 bool RequiresReference = false; 7482 7483 // Scan the components from the base to the complete expression. 7484 auto CI = Components.rbegin(); 7485 auto CE = Components.rend(); 7486 auto I = CI; 7487 7488 // Track if the map information being generated is the first for a list of 7489 // components. 7490 bool IsExpressionFirstInfo = true; 7491 Address BP = Address::invalid(); 7492 const Expr *AssocExpr = I->getAssociatedExpression(); 7493 const auto *AE = dyn_cast<ArraySubscriptExpr>(AssocExpr); 7494 const auto *OASE = dyn_cast<OMPArraySectionExpr>(AssocExpr); 7495 7496 if (isa<MemberExpr>(AssocExpr)) { 7497 // The base is the 'this' pointer. The content of the pointer is going 7498 // to be the base of the field being mapped. 7499 BP = CGF.LoadCXXThisAddress(); 7500 } else if ((AE && isa<CXXThisExpr>(AE->getBase()->IgnoreParenImpCasts())) || 7501 (OASE && 7502 isa<CXXThisExpr>(OASE->getBase()->IgnoreParenImpCasts()))) { 7503 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7504 } else { 7505 // The base is the reference to the variable. 7506 // BP = &Var. 7507 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(CGF); 7508 if (const auto *VD = 7509 dyn_cast_or_null<VarDecl>(I->getAssociatedDeclaration())) { 7510 if (llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 7511 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { 7512 if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 7513 (*Res == OMPDeclareTargetDeclAttr::MT_To && 7514 CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { 7515 RequiresReference = true; 7516 BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 7517 } 7518 } 7519 } 7520 7521 // If the variable is a pointer and is being dereferenced (i.e. is not 7522 // the last component), the base has to be the pointer itself, not its 7523 // reference. References are ignored for mapping purposes. 7524 QualType Ty = 7525 I->getAssociatedDeclaration()->getType().getNonReferenceType(); 7526 if (Ty->isAnyPointerType() && std::next(I) != CE) { 7527 BP = CGF.EmitLoadOfPointer(BP, Ty->castAs<PointerType>()); 7528 7529 // We do not need to generate individual map information for the 7530 // pointer, it can be associated with the combined storage. 7531 ++I; 7532 } 7533 } 7534 7535 // Track whether a component of the list should be marked as MEMBER_OF some 7536 // combined entry (for partial structs). Only the first PTR_AND_OBJ entry 7537 // in a component list should be marked as MEMBER_OF, all subsequent entries 7538 // do not belong to the base struct. E.g. 7539 // struct S2 s; 7540 // s.ps->ps->ps->f[:] 7541 // (1) (2) (3) (4) 7542 // ps(1) is a member pointer, ps(2) is a pointee of ps(1), so it is a 7543 // PTR_AND_OBJ entry; the PTR is ps(1), so MEMBER_OF the base struct. ps(3) 7544 // is the pointee of ps(2) which is not member of struct s, so it should not 7545 // be marked as such (it is still PTR_AND_OBJ). 7546 // The variable is initialized to false so that PTR_AND_OBJ entries which 7547 // are not struct members are not considered (e.g. array of pointers to 7548 // data). 7549 bool ShouldBeMemberOf = false; 7550 7551 // Variable keeping track of whether or not we have encountered a component 7552 // in the component list which is a member expression. Useful when we have a 7553 // pointer or a final array section, in which case it is the previous 7554 // component in the list which tells us whether we have a member expression. 7555 // E.g. X.f[:] 7556 // While processing the final array section "[:]" it is "f" which tells us 7557 // whether we are dealing with a member of a declared struct. 7558 const MemberExpr *EncounteredME = nullptr; 7559 7560 for (; I != CE; ++I) { 7561 // If the current component is member of a struct (parent struct) mark it. 7562 if (!EncounteredME) { 7563 EncounteredME = dyn_cast<MemberExpr>(I->getAssociatedExpression()); 7564 // If we encounter a PTR_AND_OBJ entry from now on it should be marked 7565 // as MEMBER_OF the parent struct. 7566 if (EncounteredME) 7567 ShouldBeMemberOf = true; 7568 } 7569 7570 auto Next = std::next(I); 7571 7572 // We need to generate the addresses and sizes if this is the last 7573 // component, if the component is a pointer or if it is an array section 7574 // whose length can't be proved to be one. If this is a pointer, it 7575 // becomes the base address for the following components. 7576 7577 // A final array section, is one whose length can't be proved to be one. 7578 bool IsFinalArraySection = 7579 isFinalArraySectionExpression(I->getAssociatedExpression()); 7580 7581 // Get information on whether the element is a pointer. Have to do a 7582 // special treatment for array sections given that they are built-in 7583 // types. 7584 const auto *OASE = 7585 dyn_cast<OMPArraySectionExpr>(I->getAssociatedExpression()); 7586 bool IsPointer = 7587 (OASE && OMPArraySectionExpr::getBaseOriginalType(OASE) 7588 .getCanonicalType() 7589 ->isAnyPointerType()) || 7590 I->getAssociatedExpression()->getType()->isAnyPointerType(); 7591 7592 if (Next == CE || IsPointer || IsFinalArraySection) { 7593 // If this is not the last component, we expect the pointer to be 7594 // associated with an array expression or member expression. 7595 assert((Next == CE || 7596 isa<MemberExpr>(Next->getAssociatedExpression()) || 7597 isa<ArraySubscriptExpr>(Next->getAssociatedExpression()) || 7598 isa<OMPArraySectionExpr>(Next->getAssociatedExpression())) && 7599 "Unexpected expression"); 7600 7601 Address LB = CGF.EmitOMPSharedLValue(I->getAssociatedExpression()) 7602 .getAddress(CGF); 7603 7604 // If this component is a pointer inside the base struct then we don't 7605 // need to create any entry for it - it will be combined with the object 7606 // it is pointing to into a single PTR_AND_OBJ entry. 7607 bool IsMemberPointer = 7608 IsPointer && EncounteredME && 7609 (dyn_cast<MemberExpr>(I->getAssociatedExpression()) == 7610 EncounteredME); 7611 if (!OverlappedElements.empty()) { 7612 // Handle base element with the info for overlapped elements. 7613 assert(!PartialStruct.Base.isValid() && "The base element is set."); 7614 assert(Next == CE && 7615 "Expected last element for the overlapped elements."); 7616 assert(!IsPointer && 7617 "Unexpected base element with the pointer type."); 7618 // Mark the whole struct as the struct that requires allocation on the 7619 // device. 7620 PartialStruct.LowestElem = {0, LB}; 7621 CharUnits TypeSize = CGF.getContext().getTypeSizeInChars( 7622 I->getAssociatedExpression()->getType()); 7623 Address HB = CGF.Builder.CreateConstGEP( 7624 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(LB, 7625 CGF.VoidPtrTy), 7626 TypeSize.getQuantity() - 1); 7627 PartialStruct.HighestElem = { 7628 std::numeric_limits<decltype( 7629 PartialStruct.HighestElem.first)>::max(), 7630 HB}; 7631 PartialStruct.Base = BP; 7632 // Emit data for non-overlapped data. 7633 OpenMPOffloadMappingFlags Flags = 7634 OMP_MAP_MEMBER_OF | 7635 getMapTypeBits(MapType, MapModifiers, IsImplicit, 7636 /*AddPtrFlag=*/false, 7637 /*AddIsTargetParamFlag=*/false); 7638 LB = BP; 7639 llvm::Value *Size = nullptr; 7640 // Do bitcopy of all non-overlapped structure elements. 7641 for (OMPClauseMappableExprCommon::MappableExprComponentListRef 7642 Component : OverlappedElements) { 7643 Address ComponentLB = Address::invalid(); 7644 for (const OMPClauseMappableExprCommon::MappableComponent &MC : 7645 Component) { 7646 if (MC.getAssociatedDeclaration()) { 7647 ComponentLB = 7648 CGF.EmitOMPSharedLValue(MC.getAssociatedExpression()) 7649 .getAddress(CGF); 7650 Size = CGF.Builder.CreatePtrDiff( 7651 CGF.EmitCastToVoidPtr(ComponentLB.getPointer()), 7652 CGF.EmitCastToVoidPtr(LB.getPointer())); 7653 break; 7654 } 7655 } 7656 BasePointers.push_back(BP.getPointer()); 7657 Pointers.push_back(LB.getPointer()); 7658 Sizes.push_back(CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, 7659 /*isSigned=*/true)); 7660 Types.push_back(Flags); 7661 LB = CGF.Builder.CreateConstGEP(ComponentLB, 1); 7662 } 7663 BasePointers.push_back(BP.getPointer()); 7664 Pointers.push_back(LB.getPointer()); 7665 Size = CGF.Builder.CreatePtrDiff( 7666 CGF.EmitCastToVoidPtr( 7667 CGF.Builder.CreateConstGEP(HB, 1).getPointer()), 7668 CGF.EmitCastToVoidPtr(LB.getPointer())); 7669 Sizes.push_back( 7670 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7671 Types.push_back(Flags); 7672 break; 7673 } 7674 llvm::Value *Size = getExprTypeSize(I->getAssociatedExpression()); 7675 if (!IsMemberPointer) { 7676 BasePointers.push_back(BP.getPointer()); 7677 Pointers.push_back(LB.getPointer()); 7678 Sizes.push_back( 7679 CGF.Builder.CreateIntCast(Size, CGF.Int64Ty, /*isSigned=*/true)); 7680 7681 // We need to add a pointer flag for each map that comes from the 7682 // same expression except for the first one. We also need to signal 7683 // this map is the first one that relates with the current capture 7684 // (there is a set of entries for each capture). 7685 OpenMPOffloadMappingFlags Flags = getMapTypeBits( 7686 MapType, MapModifiers, IsImplicit, 7687 !IsExpressionFirstInfo || RequiresReference, 7688 IsCaptureFirstInfo && !RequiresReference); 7689 7690 if (!IsExpressionFirstInfo) { 7691 // If we have a PTR_AND_OBJ pair where the OBJ is a pointer as well, 7692 // then we reset the TO/FROM/ALWAYS/DELETE/CLOSE flags. 7693 if (IsPointer) 7694 Flags &= ~(OMP_MAP_TO | OMP_MAP_FROM | OMP_MAP_ALWAYS | 7695 OMP_MAP_DELETE | OMP_MAP_CLOSE); 7696 7697 if (ShouldBeMemberOf) { 7698 // Set placeholder value MEMBER_OF=FFFF to indicate that the flag 7699 // should be later updated with the correct value of MEMBER_OF. 7700 Flags |= OMP_MAP_MEMBER_OF; 7701 // From now on, all subsequent PTR_AND_OBJ entries should not be 7702 // marked as MEMBER_OF. 7703 ShouldBeMemberOf = false; 7704 } 7705 } 7706 7707 Types.push_back(Flags); 7708 } 7709 7710 // If we have encountered a member expression so far, keep track of the 7711 // mapped member. If the parent is "*this", then the value declaration 7712 // is nullptr. 7713 if (EncounteredME) { 7714 const auto *FD = dyn_cast<FieldDecl>(EncounteredME->getMemberDecl()); 7715 unsigned FieldIndex = FD->getFieldIndex(); 7716 7717 // Update info about the lowest and highest elements for this struct 7718 if (!PartialStruct.Base.isValid()) { 7719 PartialStruct.LowestElem = {FieldIndex, LB}; 7720 PartialStruct.HighestElem = {FieldIndex, LB}; 7721 PartialStruct.Base = BP; 7722 } else if (FieldIndex < PartialStruct.LowestElem.first) { 7723 PartialStruct.LowestElem = {FieldIndex, LB}; 7724 } else if (FieldIndex > PartialStruct.HighestElem.first) { 7725 PartialStruct.HighestElem = {FieldIndex, LB}; 7726 } 7727 } 7728 7729 // If we have a final array section, we are done with this expression. 7730 if (IsFinalArraySection) 7731 break; 7732 7733 // The pointer becomes the base for the next element. 7734 if (Next != CE) 7735 BP = LB; 7736 7737 IsExpressionFirstInfo = false; 7738 IsCaptureFirstInfo = false; 7739 } 7740 } 7741 } 7742 7743 /// Return the adjusted map modifiers if the declaration a capture refers to 7744 /// appears in a first-private clause. This is expected to be used only with 7745 /// directives that start with 'target'. 7746 MappableExprsHandler::OpenMPOffloadMappingFlags 7747 getMapModifiersForPrivateClauses(const CapturedStmt::Capture &Cap) const { 7748 assert(Cap.capturesVariable() && "Expected capture by reference only!"); 7749 7750 // A first private variable captured by reference will use only the 7751 // 'private ptr' and 'map to' flag. Return the right flags if the captured 7752 // declaration is known as first-private in this handler. 7753 if (FirstPrivateDecls.count(Cap.getCapturedVar())) { 7754 if (Cap.getCapturedVar()->getType().isConstant(CGF.getContext()) && 7755 Cap.getCaptureKind() == CapturedStmt::VCK_ByRef) 7756 return MappableExprsHandler::OMP_MAP_ALWAYS | 7757 MappableExprsHandler::OMP_MAP_TO; 7758 if (Cap.getCapturedVar()->getType()->isAnyPointerType()) 7759 return MappableExprsHandler::OMP_MAP_TO | 7760 MappableExprsHandler::OMP_MAP_PTR_AND_OBJ; 7761 return MappableExprsHandler::OMP_MAP_PRIVATE | 7762 MappableExprsHandler::OMP_MAP_TO; 7763 } 7764 return MappableExprsHandler::OMP_MAP_TO | 7765 MappableExprsHandler::OMP_MAP_FROM; 7766 } 7767 7768 static OpenMPOffloadMappingFlags getMemberOfFlag(unsigned Position) { 7769 // Rotate by getFlagMemberOffset() bits. 7770 return static_cast<OpenMPOffloadMappingFlags>(((uint64_t)Position + 1) 7771 << getFlagMemberOffset()); 7772 } 7773 7774 static void setCorrectMemberOfFlag(OpenMPOffloadMappingFlags &Flags, 7775 OpenMPOffloadMappingFlags MemberOfFlag) { 7776 // If the entry is PTR_AND_OBJ but has not been marked with the special 7777 // placeholder value 0xFFFF in the MEMBER_OF field, then it should not be 7778 // marked as MEMBER_OF. 7779 if ((Flags & OMP_MAP_PTR_AND_OBJ) && 7780 ((Flags & OMP_MAP_MEMBER_OF) != OMP_MAP_MEMBER_OF)) 7781 return; 7782 7783 // Reset the placeholder value to prepare the flag for the assignment of the 7784 // proper MEMBER_OF value. 7785 Flags &= ~OMP_MAP_MEMBER_OF; 7786 Flags |= MemberOfFlag; 7787 } 7788 7789 void getPlainLayout(const CXXRecordDecl *RD, 7790 llvm::SmallVectorImpl<const FieldDecl *> &Layout, 7791 bool AsBase) const { 7792 const CGRecordLayout &RL = CGF.getTypes().getCGRecordLayout(RD); 7793 7794 llvm::StructType *St = 7795 AsBase ? RL.getBaseSubobjectLLVMType() : RL.getLLVMType(); 7796 7797 unsigned NumElements = St->getNumElements(); 7798 llvm::SmallVector< 7799 llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *>, 4> 7800 RecordLayout(NumElements); 7801 7802 // Fill bases. 7803 for (const auto &I : RD->bases()) { 7804 if (I.isVirtual()) 7805 continue; 7806 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7807 // Ignore empty bases. 7808 if (Base->isEmpty() || CGF.getContext() 7809 .getASTRecordLayout(Base) 7810 .getNonVirtualSize() 7811 .isZero()) 7812 continue; 7813 7814 unsigned FieldIndex = RL.getNonVirtualBaseLLVMFieldNo(Base); 7815 RecordLayout[FieldIndex] = Base; 7816 } 7817 // Fill in virtual bases. 7818 for (const auto &I : RD->vbases()) { 7819 const auto *Base = I.getType()->getAsCXXRecordDecl(); 7820 // Ignore empty bases. 7821 if (Base->isEmpty()) 7822 continue; 7823 unsigned FieldIndex = RL.getVirtualBaseIndex(Base); 7824 if (RecordLayout[FieldIndex]) 7825 continue; 7826 RecordLayout[FieldIndex] = Base; 7827 } 7828 // Fill in all the fields. 7829 assert(!RD->isUnion() && "Unexpected union."); 7830 for (const auto *Field : RD->fields()) { 7831 // Fill in non-bitfields. (Bitfields always use a zero pattern, which we 7832 // will fill in later.) 7833 if (!Field->isBitField() && !Field->isZeroSize(CGF.getContext())) { 7834 unsigned FieldIndex = RL.getLLVMFieldNo(Field); 7835 RecordLayout[FieldIndex] = Field; 7836 } 7837 } 7838 for (const llvm::PointerUnion<const CXXRecordDecl *, const FieldDecl *> 7839 &Data : RecordLayout) { 7840 if (Data.isNull()) 7841 continue; 7842 if (const auto *Base = Data.dyn_cast<const CXXRecordDecl *>()) 7843 getPlainLayout(Base, Layout, /*AsBase=*/true); 7844 else 7845 Layout.push_back(Data.get<const FieldDecl *>()); 7846 } 7847 } 7848 7849 public: 7850 MappableExprsHandler(const OMPExecutableDirective &Dir, CodeGenFunction &CGF) 7851 : CurDir(&Dir), CGF(CGF) { 7852 // Extract firstprivate clause information. 7853 for (const auto *C : Dir.getClausesOfKind<OMPFirstprivateClause>()) 7854 for (const auto *D : C->varlists()) 7855 FirstPrivateDecls.try_emplace( 7856 cast<VarDecl>(cast<DeclRefExpr>(D)->getDecl()), C->isImplicit()); 7857 // Extract device pointer clause information. 7858 for (const auto *C : Dir.getClausesOfKind<OMPIsDevicePtrClause>()) 7859 for (auto L : C->component_lists()) 7860 DevPointersMap[L.first].push_back(L.second); 7861 } 7862 7863 /// Constructor for the declare mapper directive. 7864 MappableExprsHandler(const OMPDeclareMapperDecl &Dir, CodeGenFunction &CGF) 7865 : CurDir(&Dir), CGF(CGF) {} 7866 7867 /// Generate code for the combined entry if we have a partially mapped struct 7868 /// and take care of the mapping flags of the arguments corresponding to 7869 /// individual struct members. 7870 void emitCombinedEntry(MapBaseValuesArrayTy &BasePointers, 7871 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7872 MapFlagsArrayTy &Types, MapFlagsArrayTy &CurTypes, 7873 const StructRangeInfoTy &PartialStruct) const { 7874 // Base is the base of the struct 7875 BasePointers.push_back(PartialStruct.Base.getPointer()); 7876 // Pointer is the address of the lowest element 7877 llvm::Value *LB = PartialStruct.LowestElem.second.getPointer(); 7878 Pointers.push_back(LB); 7879 // Size is (addr of {highest+1} element) - (addr of lowest element) 7880 llvm::Value *HB = PartialStruct.HighestElem.second.getPointer(); 7881 llvm::Value *HAddr = CGF.Builder.CreateConstGEP1_32(HB, /*Idx0=*/1); 7882 llvm::Value *CLAddr = CGF.Builder.CreatePointerCast(LB, CGF.VoidPtrTy); 7883 llvm::Value *CHAddr = CGF.Builder.CreatePointerCast(HAddr, CGF.VoidPtrTy); 7884 llvm::Value *Diff = CGF.Builder.CreatePtrDiff(CHAddr, CLAddr); 7885 llvm::Value *Size = CGF.Builder.CreateIntCast(Diff, CGF.Int64Ty, 7886 /*isSigned=*/false); 7887 Sizes.push_back(Size); 7888 // Map type is always TARGET_PARAM 7889 Types.push_back(OMP_MAP_TARGET_PARAM); 7890 // Remove TARGET_PARAM flag from the first element 7891 (*CurTypes.begin()) &= ~OMP_MAP_TARGET_PARAM; 7892 7893 // All other current entries will be MEMBER_OF the combined entry 7894 // (except for PTR_AND_OBJ entries which do not have a placeholder value 7895 // 0xFFFF in the MEMBER_OF field). 7896 OpenMPOffloadMappingFlags MemberOfFlag = 7897 getMemberOfFlag(BasePointers.size() - 1); 7898 for (auto &M : CurTypes) 7899 setCorrectMemberOfFlag(M, MemberOfFlag); 7900 } 7901 7902 /// Generate all the base pointers, section pointers, sizes and map 7903 /// types for the extracted mappable expressions. Also, for each item that 7904 /// relates with a device pointer, a pair of the relevant declaration and 7905 /// index where it occurs is appended to the device pointers info array. 7906 void generateAllInfo(MapBaseValuesArrayTy &BasePointers, 7907 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 7908 MapFlagsArrayTy &Types) const { 7909 // We have to process the component lists that relate with the same 7910 // declaration in a single chunk so that we can generate the map flags 7911 // correctly. Therefore, we organize all lists in a map. 7912 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 7913 7914 // Helper function to fill the information map for the different supported 7915 // clauses. 7916 auto &&InfoGen = [&Info]( 7917 const ValueDecl *D, 7918 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 7919 OpenMPMapClauseKind MapType, 7920 ArrayRef<OpenMPMapModifierKind> MapModifiers, 7921 bool ReturnDevicePointer, bool IsImplicit) { 7922 const ValueDecl *VD = 7923 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 7924 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 7925 IsImplicit); 7926 }; 7927 7928 assert(CurDir.is<const OMPExecutableDirective *>() && 7929 "Expect a executable directive"); 7930 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 7931 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) 7932 for (const auto L : C->component_lists()) { 7933 InfoGen(L.first, L.second, C->getMapType(), C->getMapTypeModifiers(), 7934 /*ReturnDevicePointer=*/false, C->isImplicit()); 7935 } 7936 for (const auto *C : CurExecDir->getClausesOfKind<OMPToClause>()) 7937 for (const auto L : C->component_lists()) { 7938 InfoGen(L.first, L.second, OMPC_MAP_to, llvm::None, 7939 /*ReturnDevicePointer=*/false, C->isImplicit()); 7940 } 7941 for (const auto *C : CurExecDir->getClausesOfKind<OMPFromClause>()) 7942 for (const auto L : C->component_lists()) { 7943 InfoGen(L.first, L.second, OMPC_MAP_from, llvm::None, 7944 /*ReturnDevicePointer=*/false, C->isImplicit()); 7945 } 7946 7947 // Look at the use_device_ptr clause information and mark the existing map 7948 // entries as such. If there is no map information for an entry in the 7949 // use_device_ptr list, we create one with map type 'alloc' and zero size 7950 // section. It is the user fault if that was not mapped before. If there is 7951 // no map information and the pointer is a struct member, then we defer the 7952 // emission of that entry until the whole struct has been processed. 7953 llvm::MapVector<const ValueDecl *, SmallVector<DeferredDevicePtrEntryTy, 4>> 7954 DeferredInfo; 7955 7956 for (const auto *C : 7957 CurExecDir->getClausesOfKind<OMPUseDevicePtrClause>()) { 7958 for (const auto L : C->component_lists()) { 7959 assert(!L.second.empty() && "Not expecting empty list of components!"); 7960 const ValueDecl *VD = L.second.back().getAssociatedDeclaration(); 7961 VD = cast<ValueDecl>(VD->getCanonicalDecl()); 7962 const Expr *IE = L.second.back().getAssociatedExpression(); 7963 // If the first component is a member expression, we have to look into 7964 // 'this', which maps to null in the map of map information. Otherwise 7965 // look directly for the information. 7966 auto It = Info.find(isa<MemberExpr>(IE) ? nullptr : VD); 7967 7968 // We potentially have map information for this declaration already. 7969 // Look for the first set of components that refer to it. 7970 if (It != Info.end()) { 7971 auto CI = std::find_if( 7972 It->second.begin(), It->second.end(), [VD](const MapInfo &MI) { 7973 return MI.Components.back().getAssociatedDeclaration() == VD; 7974 }); 7975 // If we found a map entry, signal that the pointer has to be returned 7976 // and move on to the next declaration. 7977 if (CI != It->second.end()) { 7978 CI->ReturnDevicePointer = true; 7979 continue; 7980 } 7981 } 7982 7983 // We didn't find any match in our map information - generate a zero 7984 // size array section - if the pointer is a struct member we defer this 7985 // action until the whole struct has been processed. 7986 if (isa<MemberExpr>(IE)) { 7987 // Insert the pointer into Info to be processed by 7988 // generateInfoForComponentList. Because it is a member pointer 7989 // without a pointee, no entry will be generated for it, therefore 7990 // we need to generate one after the whole struct has been processed. 7991 // Nonetheless, generateInfoForComponentList must be called to take 7992 // the pointer into account for the calculation of the range of the 7993 // partial struct. 7994 InfoGen(nullptr, L.second, OMPC_MAP_unknown, llvm::None, 7995 /*ReturnDevicePointer=*/false, C->isImplicit()); 7996 DeferredInfo[nullptr].emplace_back(IE, VD); 7997 } else { 7998 llvm::Value *Ptr = 7999 CGF.EmitLoadOfScalar(CGF.EmitLValue(IE), IE->getExprLoc()); 8000 BasePointers.emplace_back(Ptr, VD); 8001 Pointers.push_back(Ptr); 8002 Sizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8003 Types.push_back(OMP_MAP_RETURN_PARAM | OMP_MAP_TARGET_PARAM); 8004 } 8005 } 8006 } 8007 8008 for (const auto &M : Info) { 8009 // We need to know when we generate information for the first component 8010 // associated with a capture, because the mapping flags depend on it. 8011 bool IsFirstComponentList = true; 8012 8013 // Temporary versions of arrays 8014 MapBaseValuesArrayTy CurBasePointers; 8015 MapValuesArrayTy CurPointers; 8016 MapValuesArrayTy CurSizes; 8017 MapFlagsArrayTy CurTypes; 8018 StructRangeInfoTy PartialStruct; 8019 8020 for (const MapInfo &L : M.second) { 8021 assert(!L.Components.empty() && 8022 "Not expecting declaration with no component lists."); 8023 8024 // Remember the current base pointer index. 8025 unsigned CurrentBasePointersIdx = CurBasePointers.size(); 8026 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8027 CurBasePointers, CurPointers, CurSizes, 8028 CurTypes, PartialStruct, 8029 IsFirstComponentList, L.IsImplicit); 8030 8031 // If this entry relates with a device pointer, set the relevant 8032 // declaration and add the 'return pointer' flag. 8033 if (L.ReturnDevicePointer) { 8034 assert(CurBasePointers.size() > CurrentBasePointersIdx && 8035 "Unexpected number of mapped base pointers."); 8036 8037 const ValueDecl *RelevantVD = 8038 L.Components.back().getAssociatedDeclaration(); 8039 assert(RelevantVD && 8040 "No relevant declaration related with device pointer??"); 8041 8042 CurBasePointers[CurrentBasePointersIdx].setDevicePtrDecl(RelevantVD); 8043 CurTypes[CurrentBasePointersIdx] |= OMP_MAP_RETURN_PARAM; 8044 } 8045 IsFirstComponentList = false; 8046 } 8047 8048 // Append any pending zero-length pointers which are struct members and 8049 // used with use_device_ptr. 8050 auto CI = DeferredInfo.find(M.first); 8051 if (CI != DeferredInfo.end()) { 8052 for (const DeferredDevicePtrEntryTy &L : CI->second) { 8053 llvm::Value *BasePtr = this->CGF.EmitLValue(L.IE).getPointer(CGF); 8054 llvm::Value *Ptr = this->CGF.EmitLoadOfScalar( 8055 this->CGF.EmitLValue(L.IE), L.IE->getExprLoc()); 8056 CurBasePointers.emplace_back(BasePtr, L.VD); 8057 CurPointers.push_back(Ptr); 8058 CurSizes.push_back(llvm::Constant::getNullValue(this->CGF.Int64Ty)); 8059 // Entry is PTR_AND_OBJ and RETURN_PARAM. Also, set the placeholder 8060 // value MEMBER_OF=FFFF so that the entry is later updated with the 8061 // correct value of MEMBER_OF. 8062 CurTypes.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_RETURN_PARAM | 8063 OMP_MAP_MEMBER_OF); 8064 } 8065 } 8066 8067 // If there is an entry in PartialStruct it means we have a struct with 8068 // individual members mapped. Emit an extra combined entry. 8069 if (PartialStruct.Base.isValid()) 8070 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8071 PartialStruct); 8072 8073 // We need to append the results of this capture to what we already have. 8074 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8075 Pointers.append(CurPointers.begin(), CurPointers.end()); 8076 Sizes.append(CurSizes.begin(), CurSizes.end()); 8077 Types.append(CurTypes.begin(), CurTypes.end()); 8078 } 8079 } 8080 8081 /// Generate all the base pointers, section pointers, sizes and map types for 8082 /// the extracted map clauses of user-defined mapper. 8083 void generateAllInfoForMapper(MapBaseValuesArrayTy &BasePointers, 8084 MapValuesArrayTy &Pointers, 8085 MapValuesArrayTy &Sizes, 8086 MapFlagsArrayTy &Types) const { 8087 assert(CurDir.is<const OMPDeclareMapperDecl *>() && 8088 "Expect a declare mapper directive"); 8089 const auto *CurMapperDir = CurDir.get<const OMPDeclareMapperDecl *>(); 8090 // We have to process the component lists that relate with the same 8091 // declaration in a single chunk so that we can generate the map flags 8092 // correctly. Therefore, we organize all lists in a map. 8093 llvm::MapVector<const ValueDecl *, SmallVector<MapInfo, 8>> Info; 8094 8095 // Helper function to fill the information map for the different supported 8096 // clauses. 8097 auto &&InfoGen = [&Info]( 8098 const ValueDecl *D, 8099 OMPClauseMappableExprCommon::MappableExprComponentListRef L, 8100 OpenMPMapClauseKind MapType, 8101 ArrayRef<OpenMPMapModifierKind> MapModifiers, 8102 bool ReturnDevicePointer, bool IsImplicit) { 8103 const ValueDecl *VD = 8104 D ? cast<ValueDecl>(D->getCanonicalDecl()) : nullptr; 8105 Info[VD].emplace_back(L, MapType, MapModifiers, ReturnDevicePointer, 8106 IsImplicit); 8107 }; 8108 8109 for (const auto *C : CurMapperDir->clauselists()) { 8110 const auto *MC = cast<OMPMapClause>(C); 8111 for (const auto L : MC->component_lists()) { 8112 InfoGen(L.first, L.second, MC->getMapType(), MC->getMapTypeModifiers(), 8113 /*ReturnDevicePointer=*/false, MC->isImplicit()); 8114 } 8115 } 8116 8117 for (const auto &M : Info) { 8118 // We need to know when we generate information for the first component 8119 // associated with a capture, because the mapping flags depend on it. 8120 bool IsFirstComponentList = true; 8121 8122 // Temporary versions of arrays 8123 MapBaseValuesArrayTy CurBasePointers; 8124 MapValuesArrayTy CurPointers; 8125 MapValuesArrayTy CurSizes; 8126 MapFlagsArrayTy CurTypes; 8127 StructRangeInfoTy PartialStruct; 8128 8129 for (const MapInfo &L : M.second) { 8130 assert(!L.Components.empty() && 8131 "Not expecting declaration with no component lists."); 8132 generateInfoForComponentList(L.MapType, L.MapModifiers, L.Components, 8133 CurBasePointers, CurPointers, CurSizes, 8134 CurTypes, PartialStruct, 8135 IsFirstComponentList, L.IsImplicit); 8136 IsFirstComponentList = false; 8137 } 8138 8139 // If there is an entry in PartialStruct it means we have a struct with 8140 // individual members mapped. Emit an extra combined entry. 8141 if (PartialStruct.Base.isValid()) 8142 emitCombinedEntry(BasePointers, Pointers, Sizes, Types, CurTypes, 8143 PartialStruct); 8144 8145 // We need to append the results of this capture to what we already have. 8146 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 8147 Pointers.append(CurPointers.begin(), CurPointers.end()); 8148 Sizes.append(CurSizes.begin(), CurSizes.end()); 8149 Types.append(CurTypes.begin(), CurTypes.end()); 8150 } 8151 } 8152 8153 /// Emit capture info for lambdas for variables captured by reference. 8154 void generateInfoForLambdaCaptures( 8155 const ValueDecl *VD, llvm::Value *Arg, MapBaseValuesArrayTy &BasePointers, 8156 MapValuesArrayTy &Pointers, MapValuesArrayTy &Sizes, 8157 MapFlagsArrayTy &Types, 8158 llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers) const { 8159 const auto *RD = VD->getType() 8160 .getCanonicalType() 8161 .getNonReferenceType() 8162 ->getAsCXXRecordDecl(); 8163 if (!RD || !RD->isLambda()) 8164 return; 8165 Address VDAddr = Address(Arg, CGF.getContext().getDeclAlign(VD)); 8166 LValue VDLVal = CGF.MakeAddrLValue( 8167 VDAddr, VD->getType().getCanonicalType().getNonReferenceType()); 8168 llvm::DenseMap<const VarDecl *, FieldDecl *> Captures; 8169 FieldDecl *ThisCapture = nullptr; 8170 RD->getCaptureFields(Captures, ThisCapture); 8171 if (ThisCapture) { 8172 LValue ThisLVal = 8173 CGF.EmitLValueForFieldInitialization(VDLVal, ThisCapture); 8174 LValue ThisLValVal = CGF.EmitLValueForField(VDLVal, ThisCapture); 8175 LambdaPointers.try_emplace(ThisLVal.getPointer(CGF), 8176 VDLVal.getPointer(CGF)); 8177 BasePointers.push_back(ThisLVal.getPointer(CGF)); 8178 Pointers.push_back(ThisLValVal.getPointer(CGF)); 8179 Sizes.push_back( 8180 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8181 CGF.Int64Ty, /*isSigned=*/true)); 8182 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8183 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8184 } 8185 for (const LambdaCapture &LC : RD->captures()) { 8186 if (!LC.capturesVariable()) 8187 continue; 8188 const VarDecl *VD = LC.getCapturedVar(); 8189 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8190 continue; 8191 auto It = Captures.find(VD); 8192 assert(It != Captures.end() && "Found lambda capture without field."); 8193 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8194 if (LC.getCaptureKind() == LCK_ByRef) { 8195 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8196 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8197 VDLVal.getPointer(CGF)); 8198 BasePointers.push_back(VarLVal.getPointer(CGF)); 8199 Pointers.push_back(VarLValVal.getPointer(CGF)); 8200 Sizes.push_back(CGF.Builder.CreateIntCast( 8201 CGF.getTypeSize( 8202 VD->getType().getCanonicalType().getNonReferenceType()), 8203 CGF.Int64Ty, /*isSigned=*/true)); 8204 } else { 8205 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8206 LambdaPointers.try_emplace(VarLVal.getPointer(CGF), 8207 VDLVal.getPointer(CGF)); 8208 BasePointers.push_back(VarLVal.getPointer(CGF)); 8209 Pointers.push_back(VarRVal.getScalarVal()); 8210 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8211 } 8212 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8213 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8214 } 8215 } 8216 8217 /// Set correct indices for lambdas captures. 8218 void adjustMemberOfForLambdaCaptures( 8219 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8220 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8221 MapFlagsArrayTy &Types) const { 8222 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8223 // Set correct member_of idx for all implicit lambda captures. 8224 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8225 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8226 continue; 8227 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8228 assert(BasePtr && "Unable to find base lambda address."); 8229 int TgtIdx = -1; 8230 for (unsigned J = I; J > 0; --J) { 8231 unsigned Idx = J - 1; 8232 if (Pointers[Idx] != BasePtr) 8233 continue; 8234 TgtIdx = Idx; 8235 break; 8236 } 8237 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8238 // All other current entries will be MEMBER_OF the combined entry 8239 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8240 // 0xFFFF in the MEMBER_OF field). 8241 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8242 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8243 } 8244 } 8245 8246 /// Generate the base pointers, section pointers, sizes and map types 8247 /// associated to a given capture. 8248 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8249 llvm::Value *Arg, 8250 MapBaseValuesArrayTy &BasePointers, 8251 MapValuesArrayTy &Pointers, 8252 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8253 StructRangeInfoTy &PartialStruct) const { 8254 assert(!Cap->capturesVariableArrayType() && 8255 "Not expecting to generate map info for a variable array type!"); 8256 8257 // We need to know when we generating information for the first component 8258 const ValueDecl *VD = Cap->capturesThis() 8259 ? nullptr 8260 : Cap->getCapturedVar()->getCanonicalDecl(); 8261 8262 // If this declaration appears in a is_device_ptr clause we just have to 8263 // pass the pointer by value. If it is a reference to a declaration, we just 8264 // pass its value. 8265 if (DevPointersMap.count(VD)) { 8266 BasePointers.emplace_back(Arg, VD); 8267 Pointers.push_back(Arg); 8268 Sizes.push_back( 8269 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8270 CGF.Int64Ty, /*isSigned=*/true)); 8271 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8272 return; 8273 } 8274 8275 using MapData = 8276 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8277 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8278 SmallVector<MapData, 4> DeclComponentLists; 8279 assert(CurDir.is<const OMPExecutableDirective *>() && 8280 "Expect a executable directive"); 8281 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8282 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8283 for (const auto L : C->decl_component_lists(VD)) { 8284 assert(L.first == VD && 8285 "We got information for the wrong declaration??"); 8286 assert(!L.second.empty() && 8287 "Not expecting declaration with no component lists."); 8288 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8289 C->getMapTypeModifiers(), 8290 C->isImplicit()); 8291 } 8292 } 8293 8294 // Find overlapping elements (including the offset from the base element). 8295 llvm::SmallDenseMap< 8296 const MapData *, 8297 llvm::SmallVector< 8298 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8299 4> 8300 OverlappedData; 8301 size_t Count = 0; 8302 for (const MapData &L : DeclComponentLists) { 8303 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8304 OpenMPMapClauseKind MapType; 8305 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8306 bool IsImplicit; 8307 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8308 ++Count; 8309 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8310 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8311 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8312 auto CI = Components.rbegin(); 8313 auto CE = Components.rend(); 8314 auto SI = Components1.rbegin(); 8315 auto SE = Components1.rend(); 8316 for (; CI != CE && SI != SE; ++CI, ++SI) { 8317 if (CI->getAssociatedExpression()->getStmtClass() != 8318 SI->getAssociatedExpression()->getStmtClass()) 8319 break; 8320 // Are we dealing with different variables/fields? 8321 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8322 break; 8323 } 8324 // Found overlapping if, at least for one component, reached the head of 8325 // the components list. 8326 if (CI == CE || SI == SE) { 8327 assert((CI != CE || SI != SE) && 8328 "Unexpected full match of the mapping components."); 8329 const MapData &BaseData = CI == CE ? L : L1; 8330 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8331 SI == SE ? Components : Components1; 8332 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8333 OverlappedElements.getSecond().push_back(SubData); 8334 } 8335 } 8336 } 8337 // Sort the overlapped elements for each item. 8338 llvm::SmallVector<const FieldDecl *, 4> Layout; 8339 if (!OverlappedData.empty()) { 8340 if (const auto *CRD = 8341 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8342 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8343 else { 8344 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8345 Layout.append(RD->field_begin(), RD->field_end()); 8346 } 8347 } 8348 for (auto &Pair : OverlappedData) { 8349 llvm::sort( 8350 Pair.getSecond(), 8351 [&Layout]( 8352 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8353 OMPClauseMappableExprCommon::MappableExprComponentListRef 8354 Second) { 8355 auto CI = First.rbegin(); 8356 auto CE = First.rend(); 8357 auto SI = Second.rbegin(); 8358 auto SE = Second.rend(); 8359 for (; CI != CE && SI != SE; ++CI, ++SI) { 8360 if (CI->getAssociatedExpression()->getStmtClass() != 8361 SI->getAssociatedExpression()->getStmtClass()) 8362 break; 8363 // Are we dealing with different variables/fields? 8364 if (CI->getAssociatedDeclaration() != 8365 SI->getAssociatedDeclaration()) 8366 break; 8367 } 8368 8369 // Lists contain the same elements. 8370 if (CI == CE && SI == SE) 8371 return false; 8372 8373 // List with less elements is less than list with more elements. 8374 if (CI == CE || SI == SE) 8375 return CI == CE; 8376 8377 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8378 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8379 if (FD1->getParent() == FD2->getParent()) 8380 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8381 const auto It = 8382 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8383 return FD == FD1 || FD == FD2; 8384 }); 8385 return *It == FD1; 8386 }); 8387 } 8388 8389 // Associated with a capture, because the mapping flags depend on it. 8390 // Go through all of the elements with the overlapped elements. 8391 for (const auto &Pair : OverlappedData) { 8392 const MapData &L = *Pair.getFirst(); 8393 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8394 OpenMPMapClauseKind MapType; 8395 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8396 bool IsImplicit; 8397 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8398 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8399 OverlappedComponents = Pair.getSecond(); 8400 bool IsFirstComponentList = true; 8401 generateInfoForComponentList(MapType, MapModifiers, Components, 8402 BasePointers, Pointers, Sizes, Types, 8403 PartialStruct, IsFirstComponentList, 8404 IsImplicit, OverlappedComponents); 8405 } 8406 // Go through other elements without overlapped elements. 8407 bool IsFirstComponentList = OverlappedData.empty(); 8408 for (const MapData &L : DeclComponentLists) { 8409 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8410 OpenMPMapClauseKind MapType; 8411 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8412 bool IsImplicit; 8413 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8414 auto It = OverlappedData.find(&L); 8415 if (It == OverlappedData.end()) 8416 generateInfoForComponentList(MapType, MapModifiers, Components, 8417 BasePointers, Pointers, Sizes, Types, 8418 PartialStruct, IsFirstComponentList, 8419 IsImplicit); 8420 IsFirstComponentList = false; 8421 } 8422 } 8423 8424 /// Generate the base pointers, section pointers, sizes and map types 8425 /// associated with the declare target link variables. 8426 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8427 MapValuesArrayTy &Pointers, 8428 MapValuesArrayTy &Sizes, 8429 MapFlagsArrayTy &Types) const { 8430 assert(CurDir.is<const OMPExecutableDirective *>() && 8431 "Expect a executable directive"); 8432 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8433 // Map other list items in the map clause which are not captured variables 8434 // but "declare target link" global variables. 8435 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8436 for (const auto L : C->component_lists()) { 8437 if (!L.first) 8438 continue; 8439 const auto *VD = dyn_cast<VarDecl>(L.first); 8440 if (!VD) 8441 continue; 8442 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8443 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8444 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8445 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8446 continue; 8447 StructRangeInfoTy PartialStruct; 8448 generateInfoForComponentList( 8449 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8450 Pointers, Sizes, Types, PartialStruct, 8451 /*IsFirstComponentList=*/true, C->isImplicit()); 8452 assert(!PartialStruct.Base.isValid() && 8453 "No partial structs for declare target link expected."); 8454 } 8455 } 8456 } 8457 8458 /// Generate the default map information for a given capture \a CI, 8459 /// record field declaration \a RI and captured value \a CV. 8460 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8461 const FieldDecl &RI, llvm::Value *CV, 8462 MapBaseValuesArrayTy &CurBasePointers, 8463 MapValuesArrayTy &CurPointers, 8464 MapValuesArrayTy &CurSizes, 8465 MapFlagsArrayTy &CurMapTypes) const { 8466 bool IsImplicit = true; 8467 // Do the default mapping. 8468 if (CI.capturesThis()) { 8469 CurBasePointers.push_back(CV); 8470 CurPointers.push_back(CV); 8471 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8472 CurSizes.push_back( 8473 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8474 CGF.Int64Ty, /*isSigned=*/true)); 8475 // Default map type. 8476 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8477 } else if (CI.capturesVariableByCopy()) { 8478 CurBasePointers.push_back(CV); 8479 CurPointers.push_back(CV); 8480 if (!RI.getType()->isAnyPointerType()) { 8481 // We have to signal to the runtime captures passed by value that are 8482 // not pointers. 8483 CurMapTypes.push_back(OMP_MAP_LITERAL); 8484 CurSizes.push_back(CGF.Builder.CreateIntCast( 8485 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8486 } else { 8487 // Pointers are implicitly mapped with a zero size and no flags 8488 // (other than first map that is added for all implicit maps). 8489 CurMapTypes.push_back(OMP_MAP_NONE); 8490 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8491 } 8492 const VarDecl *VD = CI.getCapturedVar(); 8493 auto I = FirstPrivateDecls.find(VD); 8494 if (I != FirstPrivateDecls.end()) 8495 IsImplicit = I->getSecond(); 8496 } else { 8497 assert(CI.capturesVariable() && "Expected captured reference."); 8498 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8499 QualType ElementType = PtrTy->getPointeeType(); 8500 CurSizes.push_back(CGF.Builder.CreateIntCast( 8501 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8502 // The default map type for a scalar/complex type is 'to' because by 8503 // default the value doesn't have to be retrieved. For an aggregate 8504 // type, the default is 'tofrom'. 8505 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8506 const VarDecl *VD = CI.getCapturedVar(); 8507 auto I = FirstPrivateDecls.find(VD); 8508 if (I != FirstPrivateDecls.end() && 8509 VD->getType().isConstant(CGF.getContext())) { 8510 llvm::Constant *Addr = 8511 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8512 // Copy the value of the original variable to the new global copy. 8513 CGF.Builder.CreateMemCpy( 8514 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(CGF), 8515 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8516 CurSizes.back(), /*IsVolatile=*/false); 8517 // Use new global variable as the base pointers. 8518 CurBasePointers.push_back(Addr); 8519 CurPointers.push_back(Addr); 8520 } else { 8521 CurBasePointers.push_back(CV); 8522 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8523 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8524 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8525 AlignmentSource::Decl)); 8526 CurPointers.push_back(PtrAddr.getPointer()); 8527 } else { 8528 CurPointers.push_back(CV); 8529 } 8530 } 8531 if (I != FirstPrivateDecls.end()) 8532 IsImplicit = I->getSecond(); 8533 } 8534 // Every default map produces a single argument which is a target parameter. 8535 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8536 8537 // Add flag stating this is an implicit map. 8538 if (IsImplicit) 8539 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8540 } 8541 }; 8542 } // anonymous namespace 8543 8544 /// Emit the arrays used to pass the captures and map information to the 8545 /// offloading runtime library. If there is no map or capture information, 8546 /// return nullptr by reference. 8547 static void 8548 emitOffloadingArrays(CodeGenFunction &CGF, 8549 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8550 MappableExprsHandler::MapValuesArrayTy &Pointers, 8551 MappableExprsHandler::MapValuesArrayTy &Sizes, 8552 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8553 CGOpenMPRuntime::TargetDataInfo &Info) { 8554 CodeGenModule &CGM = CGF.CGM; 8555 ASTContext &Ctx = CGF.getContext(); 8556 8557 // Reset the array information. 8558 Info.clearArrayInfo(); 8559 Info.NumberOfPtrs = BasePointers.size(); 8560 8561 if (Info.NumberOfPtrs) { 8562 // Detect if we have any capture size requiring runtime evaluation of the 8563 // size so that a constant array could be eventually used. 8564 bool hasRuntimeEvaluationCaptureSize = false; 8565 for (llvm::Value *S : Sizes) 8566 if (!isa<llvm::Constant>(S)) { 8567 hasRuntimeEvaluationCaptureSize = true; 8568 break; 8569 } 8570 8571 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8572 QualType PointerArrayType = Ctx.getConstantArrayType( 8573 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8574 /*IndexTypeQuals=*/0); 8575 8576 Info.BasePointersArray = 8577 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8578 Info.PointersArray = 8579 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8580 8581 // If we don't have any VLA types or other types that require runtime 8582 // evaluation, we can use a constant array for the map sizes, otherwise we 8583 // need to fill up the arrays as we do for the pointers. 8584 QualType Int64Ty = 8585 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8586 if (hasRuntimeEvaluationCaptureSize) { 8587 QualType SizeArrayType = Ctx.getConstantArrayType( 8588 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8589 /*IndexTypeQuals=*/0); 8590 Info.SizesArray = 8591 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8592 } else { 8593 // We expect all the sizes to be constant, so we collect them to create 8594 // a constant array. 8595 SmallVector<llvm::Constant *, 16> ConstSizes; 8596 for (llvm::Value *S : Sizes) 8597 ConstSizes.push_back(cast<llvm::Constant>(S)); 8598 8599 auto *SizesArrayInit = llvm::ConstantArray::get( 8600 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8601 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8602 auto *SizesArrayGbl = new llvm::GlobalVariable( 8603 CGM.getModule(), SizesArrayInit->getType(), 8604 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8605 SizesArrayInit, Name); 8606 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8607 Info.SizesArray = SizesArrayGbl; 8608 } 8609 8610 // The map types are always constant so we don't need to generate code to 8611 // fill arrays. Instead, we create an array constant. 8612 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8613 llvm::copy(MapTypes, Mapping.begin()); 8614 llvm::Constant *MapTypesArrayInit = 8615 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8616 std::string MaptypesName = 8617 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8618 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8619 CGM.getModule(), MapTypesArrayInit->getType(), 8620 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8621 MapTypesArrayInit, MaptypesName); 8622 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8623 Info.MapTypesArray = MapTypesArrayGbl; 8624 8625 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8626 llvm::Value *BPVal = *BasePointers[I]; 8627 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8628 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8629 Info.BasePointersArray, 0, I); 8630 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8631 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8632 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8633 CGF.Builder.CreateStore(BPVal, BPAddr); 8634 8635 if (Info.requiresDevicePointerInfo()) 8636 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8637 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8638 8639 llvm::Value *PVal = Pointers[I]; 8640 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8641 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8642 Info.PointersArray, 0, I); 8643 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8644 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8645 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8646 CGF.Builder.CreateStore(PVal, PAddr); 8647 8648 if (hasRuntimeEvaluationCaptureSize) { 8649 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8650 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8651 Info.SizesArray, 8652 /*Idx0=*/0, 8653 /*Idx1=*/I); 8654 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8655 CGF.Builder.CreateStore( 8656 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8657 SAddr); 8658 } 8659 } 8660 } 8661 } 8662 8663 /// Emit the arguments to be passed to the runtime library based on the 8664 /// arrays of pointers, sizes and map types. 8665 static void emitOffloadingArraysArgument( 8666 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8667 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8668 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8669 CodeGenModule &CGM = CGF.CGM; 8670 if (Info.NumberOfPtrs) { 8671 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8672 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8673 Info.BasePointersArray, 8674 /*Idx0=*/0, /*Idx1=*/0); 8675 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8676 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8677 Info.PointersArray, 8678 /*Idx0=*/0, 8679 /*Idx1=*/0); 8680 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8681 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8682 /*Idx0=*/0, /*Idx1=*/0); 8683 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8684 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8685 Info.MapTypesArray, 8686 /*Idx0=*/0, 8687 /*Idx1=*/0); 8688 } else { 8689 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8690 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8691 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8692 MapTypesArrayArg = 8693 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8694 } 8695 } 8696 8697 /// Check for inner distribute directive. 8698 static const OMPExecutableDirective * 8699 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8700 const auto *CS = D.getInnermostCapturedStmt(); 8701 const auto *Body = 8702 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8703 const Stmt *ChildStmt = 8704 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8705 8706 if (const auto *NestedDir = 8707 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8708 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8709 switch (D.getDirectiveKind()) { 8710 case OMPD_target: 8711 if (isOpenMPDistributeDirective(DKind)) 8712 return NestedDir; 8713 if (DKind == OMPD_teams) { 8714 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8715 /*IgnoreCaptured=*/true); 8716 if (!Body) 8717 return nullptr; 8718 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8719 if (const auto *NND = 8720 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8721 DKind = NND->getDirectiveKind(); 8722 if (isOpenMPDistributeDirective(DKind)) 8723 return NND; 8724 } 8725 } 8726 return nullptr; 8727 case OMPD_target_teams: 8728 if (isOpenMPDistributeDirective(DKind)) 8729 return NestedDir; 8730 return nullptr; 8731 case OMPD_target_parallel: 8732 case OMPD_target_simd: 8733 case OMPD_target_parallel_for: 8734 case OMPD_target_parallel_for_simd: 8735 return nullptr; 8736 case OMPD_target_teams_distribute: 8737 case OMPD_target_teams_distribute_simd: 8738 case OMPD_target_teams_distribute_parallel_for: 8739 case OMPD_target_teams_distribute_parallel_for_simd: 8740 case OMPD_parallel: 8741 case OMPD_for: 8742 case OMPD_parallel_for: 8743 case OMPD_parallel_master: 8744 case OMPD_parallel_sections: 8745 case OMPD_for_simd: 8746 case OMPD_parallel_for_simd: 8747 case OMPD_cancel: 8748 case OMPD_cancellation_point: 8749 case OMPD_ordered: 8750 case OMPD_threadprivate: 8751 case OMPD_allocate: 8752 case OMPD_task: 8753 case OMPD_simd: 8754 case OMPD_sections: 8755 case OMPD_section: 8756 case OMPD_single: 8757 case OMPD_master: 8758 case OMPD_critical: 8759 case OMPD_taskyield: 8760 case OMPD_barrier: 8761 case OMPD_taskwait: 8762 case OMPD_taskgroup: 8763 case OMPD_atomic: 8764 case OMPD_flush: 8765 case OMPD_teams: 8766 case OMPD_target_data: 8767 case OMPD_target_exit_data: 8768 case OMPD_target_enter_data: 8769 case OMPD_distribute: 8770 case OMPD_distribute_simd: 8771 case OMPD_distribute_parallel_for: 8772 case OMPD_distribute_parallel_for_simd: 8773 case OMPD_teams_distribute: 8774 case OMPD_teams_distribute_simd: 8775 case OMPD_teams_distribute_parallel_for: 8776 case OMPD_teams_distribute_parallel_for_simd: 8777 case OMPD_target_update: 8778 case OMPD_declare_simd: 8779 case OMPD_declare_variant: 8780 case OMPD_declare_target: 8781 case OMPD_end_declare_target: 8782 case OMPD_declare_reduction: 8783 case OMPD_declare_mapper: 8784 case OMPD_taskloop: 8785 case OMPD_taskloop_simd: 8786 case OMPD_master_taskloop: 8787 case OMPD_master_taskloop_simd: 8788 case OMPD_parallel_master_taskloop: 8789 case OMPD_parallel_master_taskloop_simd: 8790 case OMPD_requires: 8791 case OMPD_unknown: 8792 llvm_unreachable("Unexpected directive."); 8793 } 8794 } 8795 8796 return nullptr; 8797 } 8798 8799 /// Emit the user-defined mapper function. The code generation follows the 8800 /// pattern in the example below. 8801 /// \code 8802 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8803 /// void *base, void *begin, 8804 /// int64_t size, int64_t type) { 8805 /// // Allocate space for an array section first. 8806 /// if (size > 1 && !maptype.IsDelete) 8807 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8808 /// size*sizeof(Ty), clearToFrom(type)); 8809 /// // Map members. 8810 /// for (unsigned i = 0; i < size; i++) { 8811 /// // For each component specified by this mapper: 8812 /// for (auto c : all_components) { 8813 /// if (c.hasMapper()) 8814 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8815 /// c.arg_type); 8816 /// else 8817 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8818 /// c.arg_begin, c.arg_size, c.arg_type); 8819 /// } 8820 /// } 8821 /// // Delete the array section. 8822 /// if (size > 1 && maptype.IsDelete) 8823 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8824 /// size*sizeof(Ty), clearToFrom(type)); 8825 /// } 8826 /// \endcode 8827 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8828 CodeGenFunction *CGF) { 8829 if (UDMMap.count(D) > 0) 8830 return; 8831 ASTContext &C = CGM.getContext(); 8832 QualType Ty = D->getType(); 8833 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8834 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8835 auto *MapperVarDecl = 8836 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8837 SourceLocation Loc = D->getLocation(); 8838 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8839 8840 // Prepare mapper function arguments and attributes. 8841 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8842 C.VoidPtrTy, ImplicitParamDecl::Other); 8843 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8844 ImplicitParamDecl::Other); 8845 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8846 C.VoidPtrTy, ImplicitParamDecl::Other); 8847 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8848 ImplicitParamDecl::Other); 8849 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8850 ImplicitParamDecl::Other); 8851 FunctionArgList Args; 8852 Args.push_back(&HandleArg); 8853 Args.push_back(&BaseArg); 8854 Args.push_back(&BeginArg); 8855 Args.push_back(&SizeArg); 8856 Args.push_back(&TypeArg); 8857 const CGFunctionInfo &FnInfo = 8858 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8859 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8860 SmallString<64> TyStr; 8861 llvm::raw_svector_ostream Out(TyStr); 8862 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 8863 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 8864 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 8865 Name, &CGM.getModule()); 8866 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 8867 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 8868 // Start the mapper function code generation. 8869 CodeGenFunction MapperCGF(CGM); 8870 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 8871 // Compute the starting and end addreses of array elements. 8872 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 8873 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 8874 C.getPointerType(Int64Ty), Loc); 8875 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 8876 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 8877 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 8878 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 8879 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 8880 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 8881 C.getPointerType(Int64Ty), Loc); 8882 // Prepare common arguments for array initiation and deletion. 8883 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 8884 MapperCGF.GetAddrOfLocalVar(&HandleArg), 8885 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8886 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 8887 MapperCGF.GetAddrOfLocalVar(&BaseArg), 8888 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8889 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 8890 MapperCGF.GetAddrOfLocalVar(&BeginArg), 8891 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8892 8893 // Emit array initiation if this is an array section and \p MapType indicates 8894 // that memory allocation is required. 8895 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 8896 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8897 ElementSize, HeadBB, /*IsInit=*/true); 8898 8899 // Emit a for loop to iterate through SizeArg of elements and map all of them. 8900 8901 // Emit the loop header block. 8902 MapperCGF.EmitBlock(HeadBB); 8903 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 8904 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 8905 // Evaluate whether the initial condition is satisfied. 8906 llvm::Value *IsEmpty = 8907 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 8908 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 8909 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 8910 8911 // Emit the loop body block. 8912 MapperCGF.EmitBlock(BodyBB); 8913 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 8914 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 8915 PtrPHI->addIncoming(PtrBegin, EntryBB); 8916 Address PtrCurrent = 8917 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 8918 .getAlignment() 8919 .alignmentOfArrayElement(ElementSize)); 8920 // Privatize the declared variable of mapper to be the current array element. 8921 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 8922 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 8923 return MapperCGF 8924 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 8925 .getAddress(MapperCGF); 8926 }); 8927 (void)Scope.Privatize(); 8928 8929 // Get map clause information. Fill up the arrays with all mapped variables. 8930 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 8931 MappableExprsHandler::MapValuesArrayTy Pointers; 8932 MappableExprsHandler::MapValuesArrayTy Sizes; 8933 MappableExprsHandler::MapFlagsArrayTy MapTypes; 8934 MappableExprsHandler MEHandler(*D, MapperCGF); 8935 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 8936 8937 // Call the runtime API __tgt_mapper_num_components to get the number of 8938 // pre-existing components. 8939 llvm::Value *OffloadingArgs[] = {Handle}; 8940 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 8941 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 8942 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 8943 PreviousSize, 8944 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 8945 8946 // Fill up the runtime mapper handle for all components. 8947 for (unsigned I = 0; I < BasePointers.size(); ++I) { 8948 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 8949 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8950 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 8951 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8952 llvm::Value *CurSizeArg = Sizes[I]; 8953 8954 // Extract the MEMBER_OF field from the map type. 8955 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 8956 MapperCGF.EmitBlock(MemberBB); 8957 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 8958 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 8959 OriMapType, 8960 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 8961 llvm::BasicBlock *MemberCombineBB = 8962 MapperCGF.createBasicBlock("omp.member.combine"); 8963 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 8964 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 8965 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 8966 // Add the number of pre-existing components to the MEMBER_OF field if it 8967 // is valid. 8968 MapperCGF.EmitBlock(MemberCombineBB); 8969 llvm::Value *CombinedMember = 8970 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 8971 // Do nothing if it is not a member of previous components. 8972 MapperCGF.EmitBlock(TypeBB); 8973 llvm::PHINode *MemberMapType = 8974 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 8975 MemberMapType->addIncoming(OriMapType, MemberBB); 8976 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 8977 8978 // Combine the map type inherited from user-defined mapper with that 8979 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 8980 // bits of the \a MapType, which is the input argument of the mapper 8981 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 8982 // bits of MemberMapType. 8983 // [OpenMP 5.0], 1.2.6. map-type decay. 8984 // | alloc | to | from | tofrom | release | delete 8985 // ---------------------------------------------------------- 8986 // alloc | alloc | alloc | alloc | alloc | release | delete 8987 // to | alloc | to | alloc | to | release | delete 8988 // from | alloc | alloc | from | from | release | delete 8989 // tofrom | alloc | to | from | tofrom | release | delete 8990 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 8991 MapType, 8992 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 8993 MappableExprsHandler::OMP_MAP_FROM)); 8994 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 8995 llvm::BasicBlock *AllocElseBB = 8996 MapperCGF.createBasicBlock("omp.type.alloc.else"); 8997 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 8998 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 8999 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 9000 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 9001 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 9002 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 9003 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 9004 MapperCGF.EmitBlock(AllocBB); 9005 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9006 MemberMapType, 9007 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9008 MappableExprsHandler::OMP_MAP_FROM))); 9009 MapperCGF.Builder.CreateBr(EndBB); 9010 MapperCGF.EmitBlock(AllocElseBB); 9011 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9012 LeftToFrom, 9013 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9014 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9015 // In case of to, clear OMP_MAP_FROM. 9016 MapperCGF.EmitBlock(ToBB); 9017 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9018 MemberMapType, 9019 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9020 MapperCGF.Builder.CreateBr(EndBB); 9021 MapperCGF.EmitBlock(ToElseBB); 9022 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9023 LeftToFrom, 9024 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9025 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9026 // In case of from, clear OMP_MAP_TO. 9027 MapperCGF.EmitBlock(FromBB); 9028 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9029 MemberMapType, 9030 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9031 // In case of tofrom, do nothing. 9032 MapperCGF.EmitBlock(EndBB); 9033 llvm::PHINode *CurMapType = 9034 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9035 CurMapType->addIncoming(AllocMapType, AllocBB); 9036 CurMapType->addIncoming(ToMapType, ToBB); 9037 CurMapType->addIncoming(FromMapType, FromBB); 9038 CurMapType->addIncoming(MemberMapType, ToElseBB); 9039 9040 // TODO: call the corresponding mapper function if a user-defined mapper is 9041 // associated with this map clause. 9042 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9043 // data structure. 9044 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9045 CurSizeArg, CurMapType}; 9046 MapperCGF.EmitRuntimeCall( 9047 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9048 OffloadingArgs); 9049 } 9050 9051 // Update the pointer to point to the next element that needs to be mapped, 9052 // and check whether we have mapped all elements. 9053 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9054 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9055 PtrPHI->addIncoming(PtrNext, BodyBB); 9056 llvm::Value *IsDone = 9057 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9058 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9059 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9060 9061 MapperCGF.EmitBlock(ExitBB); 9062 // Emit array deletion if this is an array section and \p MapType indicates 9063 // that deletion is required. 9064 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9065 ElementSize, DoneBB, /*IsInit=*/false); 9066 9067 // Emit the function exit block. 9068 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9069 MapperCGF.FinishFunction(); 9070 UDMMap.try_emplace(D, Fn); 9071 if (CGF) { 9072 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9073 Decls.second.push_back(D); 9074 } 9075 } 9076 9077 /// Emit the array initialization or deletion portion for user-defined mapper 9078 /// code generation. First, it evaluates whether an array section is mapped and 9079 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9080 /// true, and \a MapType indicates to not delete this array, array 9081 /// initialization code is generated. If \a IsInit is false, and \a MapType 9082 /// indicates to not this array, array deletion code is generated. 9083 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9084 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9085 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9086 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9087 StringRef Prefix = IsInit ? ".init" : ".del"; 9088 9089 // Evaluate if this is an array section. 9090 llvm::BasicBlock *IsDeleteBB = 9091 MapperCGF.createBasicBlock(getName({"omp.array", Prefix, ".evaldelete"})); 9092 llvm::BasicBlock *BodyBB = 9093 MapperCGF.createBasicBlock(getName({"omp.array", Prefix})); 9094 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9095 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9096 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9097 9098 // Evaluate if we are going to delete this section. 9099 MapperCGF.EmitBlock(IsDeleteBB); 9100 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9101 MapType, 9102 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9103 llvm::Value *DeleteCond; 9104 if (IsInit) { 9105 DeleteCond = MapperCGF.Builder.CreateIsNull( 9106 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9107 } else { 9108 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9109 DeleteBit, getName({"omp.array", Prefix, ".delete"})); 9110 } 9111 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9112 9113 MapperCGF.EmitBlock(BodyBB); 9114 // Get the array size by multiplying element size and element number (i.e., \p 9115 // Size). 9116 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9117 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9118 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9119 // memory allocation/deletion purpose only. 9120 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9121 MapType, 9122 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9123 MappableExprsHandler::OMP_MAP_FROM))); 9124 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9125 // data structure. 9126 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9127 MapperCGF.EmitRuntimeCall( 9128 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9129 } 9130 9131 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9132 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9133 llvm::Value *DeviceID, 9134 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9135 const OMPLoopDirective &D)> 9136 SizeEmitter) { 9137 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9138 const OMPExecutableDirective *TD = &D; 9139 // Get nested teams distribute kind directive, if any. 9140 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9141 TD = getNestedDistributeDirective(CGM.getContext(), D); 9142 if (!TD) 9143 return; 9144 const auto *LD = cast<OMPLoopDirective>(TD); 9145 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9146 PrePostActionTy &) { 9147 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9148 llvm::Value *Args[] = {DeviceID, NumIterations}; 9149 CGF.EmitRuntimeCall( 9150 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9151 } 9152 }; 9153 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9154 } 9155 9156 void CGOpenMPRuntime::emitTargetCall( 9157 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9158 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9159 const Expr *Device, 9160 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9161 const OMPLoopDirective &D)> 9162 SizeEmitter) { 9163 if (!CGF.HaveInsertPoint()) 9164 return; 9165 9166 assert(OutlinedFn && "Invalid outlined function!"); 9167 9168 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9169 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9170 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9171 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9172 PrePostActionTy &) { 9173 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9174 }; 9175 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9176 9177 CodeGenFunction::OMPTargetDataInfo InputInfo; 9178 llvm::Value *MapTypesArray = nullptr; 9179 // Fill up the pointer arrays and transfer execution to the device. 9180 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9181 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9182 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9183 // On top of the arrays that were filled up, the target offloading call 9184 // takes as arguments the device id as well as the host pointer. The host 9185 // pointer is used by the runtime library to identify the current target 9186 // region, so it only has to be unique and not necessarily point to 9187 // anything. It could be the pointer to the outlined function that 9188 // implements the target region, but we aren't using that so that the 9189 // compiler doesn't need to keep that, and could therefore inline the host 9190 // function if proven worthwhile during optimization. 9191 9192 // From this point on, we need to have an ID of the target region defined. 9193 assert(OutlinedFnID && "Invalid outlined function ID!"); 9194 9195 // Emit device ID if any. 9196 llvm::Value *DeviceID; 9197 if (Device) { 9198 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9199 CGF.Int64Ty, /*isSigned=*/true); 9200 } else { 9201 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9202 } 9203 9204 // Emit the number of elements in the offloading arrays. 9205 llvm::Value *PointerNum = 9206 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9207 9208 // Return value of the runtime offloading call. 9209 llvm::Value *Return; 9210 9211 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9212 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9213 9214 // Emit tripcount for the target loop-based directive. 9215 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9216 9217 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9218 // The target region is an outlined function launched by the runtime 9219 // via calls __tgt_target() or __tgt_target_teams(). 9220 // 9221 // __tgt_target() launches a target region with one team and one thread, 9222 // executing a serial region. This master thread may in turn launch 9223 // more threads within its team upon encountering a parallel region, 9224 // however, no additional teams can be launched on the device. 9225 // 9226 // __tgt_target_teams() launches a target region with one or more teams, 9227 // each with one or more threads. This call is required for target 9228 // constructs such as: 9229 // 'target teams' 9230 // 'target' / 'teams' 9231 // 'target teams distribute parallel for' 9232 // 'target parallel' 9233 // and so on. 9234 // 9235 // Note that on the host and CPU targets, the runtime implementation of 9236 // these calls simply call the outlined function without forking threads. 9237 // The outlined functions themselves have runtime calls to 9238 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9239 // the compiler in emitTeamsCall() and emitParallelCall(). 9240 // 9241 // In contrast, on the NVPTX target, the implementation of 9242 // __tgt_target_teams() launches a GPU kernel with the requested number 9243 // of teams and threads so no additional calls to the runtime are required. 9244 if (NumTeams) { 9245 // If we have NumTeams defined this means that we have an enclosed teams 9246 // region. Therefore we also expect to have NumThreads defined. These two 9247 // values should be defined in the presence of a teams directive, 9248 // regardless of having any clauses associated. If the user is using teams 9249 // but no clauses, these two values will be the default that should be 9250 // passed to the runtime library - a 32-bit integer with the value zero. 9251 assert(NumThreads && "Thread limit expression should be available along " 9252 "with number of teams."); 9253 llvm::Value *OffloadingArgs[] = {DeviceID, 9254 OutlinedFnID, 9255 PointerNum, 9256 InputInfo.BasePointersArray.getPointer(), 9257 InputInfo.PointersArray.getPointer(), 9258 InputInfo.SizesArray.getPointer(), 9259 MapTypesArray, 9260 NumTeams, 9261 NumThreads}; 9262 Return = CGF.EmitRuntimeCall( 9263 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9264 : OMPRTL__tgt_target_teams), 9265 OffloadingArgs); 9266 } else { 9267 llvm::Value *OffloadingArgs[] = {DeviceID, 9268 OutlinedFnID, 9269 PointerNum, 9270 InputInfo.BasePointersArray.getPointer(), 9271 InputInfo.PointersArray.getPointer(), 9272 InputInfo.SizesArray.getPointer(), 9273 MapTypesArray}; 9274 Return = CGF.EmitRuntimeCall( 9275 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9276 : OMPRTL__tgt_target), 9277 OffloadingArgs); 9278 } 9279 9280 // Check the error code and execute the host version if required. 9281 llvm::BasicBlock *OffloadFailedBlock = 9282 CGF.createBasicBlock("omp_offload.failed"); 9283 llvm::BasicBlock *OffloadContBlock = 9284 CGF.createBasicBlock("omp_offload.cont"); 9285 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9286 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9287 9288 CGF.EmitBlock(OffloadFailedBlock); 9289 if (RequiresOuterTask) { 9290 CapturedVars.clear(); 9291 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9292 } 9293 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9294 CGF.EmitBranch(OffloadContBlock); 9295 9296 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9297 }; 9298 9299 // Notify that the host version must be executed. 9300 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9301 RequiresOuterTask](CodeGenFunction &CGF, 9302 PrePostActionTy &) { 9303 if (RequiresOuterTask) { 9304 CapturedVars.clear(); 9305 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9306 } 9307 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9308 }; 9309 9310 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9311 &CapturedVars, RequiresOuterTask, 9312 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9313 // Fill up the arrays with all the captured variables. 9314 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9315 MappableExprsHandler::MapValuesArrayTy Pointers; 9316 MappableExprsHandler::MapValuesArrayTy Sizes; 9317 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9318 9319 // Get mappable expression information. 9320 MappableExprsHandler MEHandler(D, CGF); 9321 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9322 9323 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9324 auto CV = CapturedVars.begin(); 9325 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9326 CE = CS.capture_end(); 9327 CI != CE; ++CI, ++RI, ++CV) { 9328 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9329 MappableExprsHandler::MapValuesArrayTy CurPointers; 9330 MappableExprsHandler::MapValuesArrayTy CurSizes; 9331 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9332 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9333 9334 // VLA sizes are passed to the outlined region by copy and do not have map 9335 // information associated. 9336 if (CI->capturesVariableArrayType()) { 9337 CurBasePointers.push_back(*CV); 9338 CurPointers.push_back(*CV); 9339 CurSizes.push_back(CGF.Builder.CreateIntCast( 9340 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9341 // Copy to the device as an argument. No need to retrieve it. 9342 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9343 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9344 MappableExprsHandler::OMP_MAP_IMPLICIT); 9345 } else { 9346 // If we have any information in the map clause, we use it, otherwise we 9347 // just do a default mapping. 9348 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9349 CurSizes, CurMapTypes, PartialStruct); 9350 if (CurBasePointers.empty()) 9351 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9352 CurPointers, CurSizes, CurMapTypes); 9353 // Generate correct mapping for variables captured by reference in 9354 // lambdas. 9355 if (CI->capturesVariable()) 9356 MEHandler.generateInfoForLambdaCaptures( 9357 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9358 CurMapTypes, LambdaPointers); 9359 } 9360 // We expect to have at least an element of information for this capture. 9361 assert(!CurBasePointers.empty() && 9362 "Non-existing map pointer for capture!"); 9363 assert(CurBasePointers.size() == CurPointers.size() && 9364 CurBasePointers.size() == CurSizes.size() && 9365 CurBasePointers.size() == CurMapTypes.size() && 9366 "Inconsistent map information sizes!"); 9367 9368 // If there is an entry in PartialStruct it means we have a struct with 9369 // individual members mapped. Emit an extra combined entry. 9370 if (PartialStruct.Base.isValid()) 9371 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9372 CurMapTypes, PartialStruct); 9373 9374 // We need to append the results of this capture to what we already have. 9375 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9376 Pointers.append(CurPointers.begin(), CurPointers.end()); 9377 Sizes.append(CurSizes.begin(), CurSizes.end()); 9378 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9379 } 9380 // Adjust MEMBER_OF flags for the lambdas captures. 9381 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9382 Pointers, MapTypes); 9383 // Map other list items in the map clause which are not captured variables 9384 // but "declare target link" global variables. 9385 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9386 MapTypes); 9387 9388 TargetDataInfo Info; 9389 // Fill up the arrays and create the arguments. 9390 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9391 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9392 Info.PointersArray, Info.SizesArray, 9393 Info.MapTypesArray, Info); 9394 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9395 InputInfo.BasePointersArray = 9396 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9397 InputInfo.PointersArray = 9398 Address(Info.PointersArray, CGM.getPointerAlign()); 9399 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9400 MapTypesArray = Info.MapTypesArray; 9401 if (RequiresOuterTask) 9402 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9403 else 9404 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9405 }; 9406 9407 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9408 CodeGenFunction &CGF, PrePostActionTy &) { 9409 if (RequiresOuterTask) { 9410 CodeGenFunction::OMPTargetDataInfo InputInfo; 9411 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9412 } else { 9413 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9414 } 9415 }; 9416 9417 // If we have a target function ID it means that we need to support 9418 // offloading, otherwise, just execute on the host. We need to execute on host 9419 // regardless of the conditional in the if clause if, e.g., the user do not 9420 // specify target triples. 9421 if (OutlinedFnID) { 9422 if (IfCond) { 9423 emitIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9424 } else { 9425 RegionCodeGenTy ThenRCG(TargetThenGen); 9426 ThenRCG(CGF); 9427 } 9428 } else { 9429 RegionCodeGenTy ElseRCG(TargetElseGen); 9430 ElseRCG(CGF); 9431 } 9432 } 9433 9434 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9435 StringRef ParentName) { 9436 if (!S) 9437 return; 9438 9439 // Codegen OMP target directives that offload compute to the device. 9440 bool RequiresDeviceCodegen = 9441 isa<OMPExecutableDirective>(S) && 9442 isOpenMPTargetExecutionDirective( 9443 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9444 9445 if (RequiresDeviceCodegen) { 9446 const auto &E = *cast<OMPExecutableDirective>(S); 9447 unsigned DeviceID; 9448 unsigned FileID; 9449 unsigned Line; 9450 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9451 FileID, Line); 9452 9453 // Is this a target region that should not be emitted as an entry point? If 9454 // so just signal we are done with this target region. 9455 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9456 ParentName, Line)) 9457 return; 9458 9459 switch (E.getDirectiveKind()) { 9460 case OMPD_target: 9461 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9462 cast<OMPTargetDirective>(E)); 9463 break; 9464 case OMPD_target_parallel: 9465 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9466 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9467 break; 9468 case OMPD_target_teams: 9469 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9470 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9471 break; 9472 case OMPD_target_teams_distribute: 9473 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9474 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9475 break; 9476 case OMPD_target_teams_distribute_simd: 9477 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9478 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9479 break; 9480 case OMPD_target_parallel_for: 9481 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9482 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9483 break; 9484 case OMPD_target_parallel_for_simd: 9485 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9486 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9487 break; 9488 case OMPD_target_simd: 9489 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9490 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9491 break; 9492 case OMPD_target_teams_distribute_parallel_for: 9493 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9494 CGM, ParentName, 9495 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9496 break; 9497 case OMPD_target_teams_distribute_parallel_for_simd: 9498 CodeGenFunction:: 9499 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9500 CGM, ParentName, 9501 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9502 break; 9503 case OMPD_parallel: 9504 case OMPD_for: 9505 case OMPD_parallel_for: 9506 case OMPD_parallel_master: 9507 case OMPD_parallel_sections: 9508 case OMPD_for_simd: 9509 case OMPD_parallel_for_simd: 9510 case OMPD_cancel: 9511 case OMPD_cancellation_point: 9512 case OMPD_ordered: 9513 case OMPD_threadprivate: 9514 case OMPD_allocate: 9515 case OMPD_task: 9516 case OMPD_simd: 9517 case OMPD_sections: 9518 case OMPD_section: 9519 case OMPD_single: 9520 case OMPD_master: 9521 case OMPD_critical: 9522 case OMPD_taskyield: 9523 case OMPD_barrier: 9524 case OMPD_taskwait: 9525 case OMPD_taskgroup: 9526 case OMPD_atomic: 9527 case OMPD_flush: 9528 case OMPD_teams: 9529 case OMPD_target_data: 9530 case OMPD_target_exit_data: 9531 case OMPD_target_enter_data: 9532 case OMPD_distribute: 9533 case OMPD_distribute_simd: 9534 case OMPD_distribute_parallel_for: 9535 case OMPD_distribute_parallel_for_simd: 9536 case OMPD_teams_distribute: 9537 case OMPD_teams_distribute_simd: 9538 case OMPD_teams_distribute_parallel_for: 9539 case OMPD_teams_distribute_parallel_for_simd: 9540 case OMPD_target_update: 9541 case OMPD_declare_simd: 9542 case OMPD_declare_variant: 9543 case OMPD_declare_target: 9544 case OMPD_end_declare_target: 9545 case OMPD_declare_reduction: 9546 case OMPD_declare_mapper: 9547 case OMPD_taskloop: 9548 case OMPD_taskloop_simd: 9549 case OMPD_master_taskloop: 9550 case OMPD_master_taskloop_simd: 9551 case OMPD_parallel_master_taskloop: 9552 case OMPD_parallel_master_taskloop_simd: 9553 case OMPD_requires: 9554 case OMPD_unknown: 9555 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9556 } 9557 return; 9558 } 9559 9560 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9561 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9562 return; 9563 9564 scanForTargetRegionsFunctions( 9565 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9566 return; 9567 } 9568 9569 // If this is a lambda function, look into its body. 9570 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9571 S = L->getBody(); 9572 9573 // Keep looking for target regions recursively. 9574 for (const Stmt *II : S->children()) 9575 scanForTargetRegionsFunctions(II, ParentName); 9576 } 9577 9578 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9579 // If emitting code for the host, we do not process FD here. Instead we do 9580 // the normal code generation. 9581 if (!CGM.getLangOpts().OpenMPIsDevice) { 9582 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9583 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9584 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9585 // Do not emit device_type(nohost) functions for the host. 9586 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9587 return true; 9588 } 9589 return false; 9590 } 9591 9592 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9593 // Try to detect target regions in the function. 9594 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9595 StringRef Name = CGM.getMangledName(GD); 9596 scanForTargetRegionsFunctions(FD->getBody(), Name); 9597 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9598 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9599 // Do not emit device_type(nohost) functions for the host. 9600 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9601 return true; 9602 } 9603 9604 // Do not to emit function if it is not marked as declare target. 9605 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9606 AlreadyEmittedTargetDecls.count(VD) == 0; 9607 } 9608 9609 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9610 if (!CGM.getLangOpts().OpenMPIsDevice) 9611 return false; 9612 9613 // Check if there are Ctors/Dtors in this declaration and look for target 9614 // regions in it. We use the complete variant to produce the kernel name 9615 // mangling. 9616 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9617 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9618 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9619 StringRef ParentName = 9620 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9621 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9622 } 9623 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9624 StringRef ParentName = 9625 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9626 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9627 } 9628 } 9629 9630 // Do not to emit variable if it is not marked as declare target. 9631 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9632 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9633 cast<VarDecl>(GD.getDecl())); 9634 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9635 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9636 HasRequiresUnifiedSharedMemory)) { 9637 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9638 return true; 9639 } 9640 return false; 9641 } 9642 9643 llvm::Constant * 9644 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9645 const VarDecl *VD) { 9646 assert(VD->getType().isConstant(CGM.getContext()) && 9647 "Expected constant variable."); 9648 StringRef VarName; 9649 llvm::Constant *Addr; 9650 llvm::GlobalValue::LinkageTypes Linkage; 9651 QualType Ty = VD->getType(); 9652 SmallString<128> Buffer; 9653 { 9654 unsigned DeviceID; 9655 unsigned FileID; 9656 unsigned Line; 9657 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9658 FileID, Line); 9659 llvm::raw_svector_ostream OS(Buffer); 9660 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9661 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9662 VarName = OS.str(); 9663 } 9664 Linkage = llvm::GlobalValue::InternalLinkage; 9665 Addr = 9666 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9667 getDefaultFirstprivateAddressSpace()); 9668 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9669 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9670 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9671 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9672 VarName, Addr, VarSize, 9673 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9674 return Addr; 9675 } 9676 9677 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9678 llvm::Constant *Addr) { 9679 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9680 !CGM.getLangOpts().OpenMPIsDevice) 9681 return; 9682 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9683 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9684 if (!Res) { 9685 if (CGM.getLangOpts().OpenMPIsDevice) { 9686 // Register non-target variables being emitted in device code (debug info 9687 // may cause this). 9688 StringRef VarName = CGM.getMangledName(VD); 9689 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9690 } 9691 return; 9692 } 9693 // Register declare target variables. 9694 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9695 StringRef VarName; 9696 CharUnits VarSize; 9697 llvm::GlobalValue::LinkageTypes Linkage; 9698 9699 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9700 !HasRequiresUnifiedSharedMemory) { 9701 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9702 VarName = CGM.getMangledName(VD); 9703 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9704 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9705 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9706 } else { 9707 VarSize = CharUnits::Zero(); 9708 } 9709 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9710 // Temp solution to prevent optimizations of the internal variables. 9711 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9712 std::string RefName = getName({VarName, "ref"}); 9713 if (!CGM.GetGlobalValue(RefName)) { 9714 llvm::Constant *AddrRef = 9715 getOrCreateInternalVariable(Addr->getType(), RefName); 9716 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9717 GVAddrRef->setConstant(/*Val=*/true); 9718 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9719 GVAddrRef->setInitializer(Addr); 9720 CGM.addCompilerUsedGlobal(GVAddrRef); 9721 } 9722 } 9723 } else { 9724 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9725 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9726 HasRequiresUnifiedSharedMemory)) && 9727 "Declare target attribute must link or to with unified memory."); 9728 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9729 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9730 else 9731 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9732 9733 if (CGM.getLangOpts().OpenMPIsDevice) { 9734 VarName = Addr->getName(); 9735 Addr = nullptr; 9736 } else { 9737 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9738 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9739 } 9740 VarSize = CGM.getPointerSize(); 9741 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9742 } 9743 9744 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9745 VarName, Addr, VarSize, Flags, Linkage); 9746 } 9747 9748 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9749 if (isa<FunctionDecl>(GD.getDecl()) || 9750 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9751 return emitTargetFunctions(GD); 9752 9753 return emitTargetGlobalVariable(GD); 9754 } 9755 9756 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9757 for (const VarDecl *VD : DeferredGlobalVariables) { 9758 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9759 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9760 if (!Res) 9761 continue; 9762 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9763 !HasRequiresUnifiedSharedMemory) { 9764 CGM.EmitGlobal(VD); 9765 } else { 9766 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9767 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9768 HasRequiresUnifiedSharedMemory)) && 9769 "Expected link clause or to clause with unified memory."); 9770 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9771 } 9772 } 9773 } 9774 9775 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9776 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9777 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9778 " Expected target-based directive."); 9779 } 9780 9781 void CGOpenMPRuntime::checkArchForUnifiedAddressing( 9782 const OMPRequiresDecl *D) { 9783 for (const OMPClause *Clause : D->clauselists()) { 9784 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9785 HasRequiresUnifiedSharedMemory = true; 9786 break; 9787 } 9788 } 9789 } 9790 9791 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9792 LangAS &AS) { 9793 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9794 return false; 9795 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9796 switch(A->getAllocatorType()) { 9797 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9798 // Not supported, fallback to the default mem space. 9799 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9800 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9801 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9802 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9803 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9804 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9805 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9806 AS = LangAS::Default; 9807 return true; 9808 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9809 llvm_unreachable("Expected predefined allocator for the variables with the " 9810 "static storage."); 9811 } 9812 return false; 9813 } 9814 9815 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9816 return HasRequiresUnifiedSharedMemory; 9817 } 9818 9819 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9820 CodeGenModule &CGM) 9821 : CGM(CGM) { 9822 if (CGM.getLangOpts().OpenMPIsDevice) { 9823 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9824 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9825 } 9826 } 9827 9828 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9829 if (CGM.getLangOpts().OpenMPIsDevice) 9830 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9831 } 9832 9833 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9834 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9835 return true; 9836 9837 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9838 // Do not to emit function if it is marked as declare target as it was already 9839 // emitted. 9840 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9841 if (D->hasBody() && AlreadyEmittedTargetDecls.count(D) == 0) { 9842 if (auto *F = dyn_cast_or_null<llvm::Function>( 9843 CGM.GetGlobalValue(CGM.getMangledName(GD)))) 9844 return !F->isDeclaration(); 9845 return false; 9846 } 9847 return true; 9848 } 9849 9850 return !AlreadyEmittedTargetDecls.insert(D).second; 9851 } 9852 9853 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9854 // If we don't have entries or if we are emitting code for the device, we 9855 // don't need to do anything. 9856 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9857 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9858 (OffloadEntriesInfoManager.empty() && 9859 !HasEmittedDeclareTargetRegion && 9860 !HasEmittedTargetRegion)) 9861 return nullptr; 9862 9863 // Create and register the function that handles the requires directives. 9864 ASTContext &C = CGM.getContext(); 9865 9866 llvm::Function *RequiresRegFn; 9867 { 9868 CodeGenFunction CGF(CGM); 9869 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9870 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9871 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9872 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9873 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9874 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9875 // TODO: check for other requires clauses. 9876 // The requires directive takes effect only when a target region is 9877 // present in the compilation unit. Otherwise it is ignored and not 9878 // passed to the runtime. This avoids the runtime from throwing an error 9879 // for mismatching requires clauses across compilation units that don't 9880 // contain at least 1 target region. 9881 assert((HasEmittedTargetRegion || 9882 HasEmittedDeclareTargetRegion || 9883 !OffloadEntriesInfoManager.empty()) && 9884 "Target or declare target region expected."); 9885 if (HasRequiresUnifiedSharedMemory) 9886 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9887 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 9888 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9889 CGF.FinishFunction(); 9890 } 9891 return RequiresRegFn; 9892 } 9893 9894 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9895 const OMPExecutableDirective &D, 9896 SourceLocation Loc, 9897 llvm::Function *OutlinedFn, 9898 ArrayRef<llvm::Value *> CapturedVars) { 9899 if (!CGF.HaveInsertPoint()) 9900 return; 9901 9902 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9903 CodeGenFunction::RunCleanupsScope Scope(CGF); 9904 9905 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9906 llvm::Value *Args[] = { 9907 RTLoc, 9908 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9909 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9910 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9911 RealArgs.append(std::begin(Args), std::end(Args)); 9912 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9913 9914 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 9915 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9916 } 9917 9918 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9919 const Expr *NumTeams, 9920 const Expr *ThreadLimit, 9921 SourceLocation Loc) { 9922 if (!CGF.HaveInsertPoint()) 9923 return; 9924 9925 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9926 9927 llvm::Value *NumTeamsVal = 9928 NumTeams 9929 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9930 CGF.CGM.Int32Ty, /* isSigned = */ true) 9931 : CGF.Builder.getInt32(0); 9932 9933 llvm::Value *ThreadLimitVal = 9934 ThreadLimit 9935 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 9936 CGF.CGM.Int32Ty, /* isSigned = */ true) 9937 : CGF.Builder.getInt32(0); 9938 9939 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 9940 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 9941 ThreadLimitVal}; 9942 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 9943 PushNumTeamsArgs); 9944 } 9945 9946 void CGOpenMPRuntime::emitTargetDataCalls( 9947 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 9948 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 9949 if (!CGF.HaveInsertPoint()) 9950 return; 9951 9952 // Action used to replace the default codegen action and turn privatization 9953 // off. 9954 PrePostActionTy NoPrivAction; 9955 9956 // Generate the code for the opening of the data environment. Capture all the 9957 // arguments of the runtime call by reference because they are used in the 9958 // closing of the region. 9959 auto &&BeginThenGen = [this, &D, Device, &Info, 9960 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 9961 // Fill up the arrays with all the mapped variables. 9962 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9963 MappableExprsHandler::MapValuesArrayTy Pointers; 9964 MappableExprsHandler::MapValuesArrayTy Sizes; 9965 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9966 9967 // Get map clause information. 9968 MappableExprsHandler MCHandler(D, CGF); 9969 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 9970 9971 // Fill up the arrays and create the arguments. 9972 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9973 9974 llvm::Value *BasePointersArrayArg = nullptr; 9975 llvm::Value *PointersArrayArg = nullptr; 9976 llvm::Value *SizesArrayArg = nullptr; 9977 llvm::Value *MapTypesArrayArg = nullptr; 9978 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 9979 SizesArrayArg, MapTypesArrayArg, Info); 9980 9981 // Emit device ID if any. 9982 llvm::Value *DeviceID = nullptr; 9983 if (Device) { 9984 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9985 CGF.Int64Ty, /*isSigned=*/true); 9986 } else { 9987 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9988 } 9989 9990 // Emit the number of elements in the offloading arrays. 9991 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 9992 9993 llvm::Value *OffloadingArgs[] = { 9994 DeviceID, PointerNum, BasePointersArrayArg, 9995 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 9996 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 9997 OffloadingArgs); 9998 9999 // If device pointer privatization is required, emit the body of the region 10000 // here. It will have to be duplicated: with and without privatization. 10001 if (!Info.CaptureDeviceAddrMap.empty()) 10002 CodeGen(CGF); 10003 }; 10004 10005 // Generate code for the closing of the data region. 10006 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 10007 PrePostActionTy &) { 10008 assert(Info.isValid() && "Invalid data environment closing arguments."); 10009 10010 llvm::Value *BasePointersArrayArg = nullptr; 10011 llvm::Value *PointersArrayArg = nullptr; 10012 llvm::Value *SizesArrayArg = nullptr; 10013 llvm::Value *MapTypesArrayArg = nullptr; 10014 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10015 SizesArrayArg, MapTypesArrayArg, Info); 10016 10017 // Emit device ID if any. 10018 llvm::Value *DeviceID = nullptr; 10019 if (Device) { 10020 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10021 CGF.Int64Ty, /*isSigned=*/true); 10022 } else { 10023 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10024 } 10025 10026 // Emit the number of elements in the offloading arrays. 10027 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10028 10029 llvm::Value *OffloadingArgs[] = { 10030 DeviceID, PointerNum, BasePointersArrayArg, 10031 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10032 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10033 OffloadingArgs); 10034 }; 10035 10036 // If we need device pointer privatization, we need to emit the body of the 10037 // region with no privatization in the 'else' branch of the conditional. 10038 // Otherwise, we don't have to do anything. 10039 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10040 PrePostActionTy &) { 10041 if (!Info.CaptureDeviceAddrMap.empty()) { 10042 CodeGen.setAction(NoPrivAction); 10043 CodeGen(CGF); 10044 } 10045 }; 10046 10047 // We don't have to do anything to close the region if the if clause evaluates 10048 // to false. 10049 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10050 10051 if (IfCond) { 10052 emitIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10053 } else { 10054 RegionCodeGenTy RCG(BeginThenGen); 10055 RCG(CGF); 10056 } 10057 10058 // If we don't require privatization of device pointers, we emit the body in 10059 // between the runtime calls. This avoids duplicating the body code. 10060 if (Info.CaptureDeviceAddrMap.empty()) { 10061 CodeGen.setAction(NoPrivAction); 10062 CodeGen(CGF); 10063 } 10064 10065 if (IfCond) { 10066 emitIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10067 } else { 10068 RegionCodeGenTy RCG(EndThenGen); 10069 RCG(CGF); 10070 } 10071 } 10072 10073 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10074 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10075 const Expr *Device) { 10076 if (!CGF.HaveInsertPoint()) 10077 return; 10078 10079 assert((isa<OMPTargetEnterDataDirective>(D) || 10080 isa<OMPTargetExitDataDirective>(D) || 10081 isa<OMPTargetUpdateDirective>(D)) && 10082 "Expecting either target enter, exit data, or update directives."); 10083 10084 CodeGenFunction::OMPTargetDataInfo InputInfo; 10085 llvm::Value *MapTypesArray = nullptr; 10086 // Generate the code for the opening of the data environment. 10087 auto &&ThenGen = [this, &D, Device, &InputInfo, 10088 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10089 // Emit device ID if any. 10090 llvm::Value *DeviceID = nullptr; 10091 if (Device) { 10092 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10093 CGF.Int64Ty, /*isSigned=*/true); 10094 } else { 10095 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10096 } 10097 10098 // Emit the number of elements in the offloading arrays. 10099 llvm::Constant *PointerNum = 10100 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10101 10102 llvm::Value *OffloadingArgs[] = {DeviceID, 10103 PointerNum, 10104 InputInfo.BasePointersArray.getPointer(), 10105 InputInfo.PointersArray.getPointer(), 10106 InputInfo.SizesArray.getPointer(), 10107 MapTypesArray}; 10108 10109 // Select the right runtime function call for each expected standalone 10110 // directive. 10111 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10112 OpenMPRTLFunction RTLFn; 10113 switch (D.getDirectiveKind()) { 10114 case OMPD_target_enter_data: 10115 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10116 : OMPRTL__tgt_target_data_begin; 10117 break; 10118 case OMPD_target_exit_data: 10119 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10120 : OMPRTL__tgt_target_data_end; 10121 break; 10122 case OMPD_target_update: 10123 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10124 : OMPRTL__tgt_target_data_update; 10125 break; 10126 case OMPD_parallel: 10127 case OMPD_for: 10128 case OMPD_parallel_for: 10129 case OMPD_parallel_master: 10130 case OMPD_parallel_sections: 10131 case OMPD_for_simd: 10132 case OMPD_parallel_for_simd: 10133 case OMPD_cancel: 10134 case OMPD_cancellation_point: 10135 case OMPD_ordered: 10136 case OMPD_threadprivate: 10137 case OMPD_allocate: 10138 case OMPD_task: 10139 case OMPD_simd: 10140 case OMPD_sections: 10141 case OMPD_section: 10142 case OMPD_single: 10143 case OMPD_master: 10144 case OMPD_critical: 10145 case OMPD_taskyield: 10146 case OMPD_barrier: 10147 case OMPD_taskwait: 10148 case OMPD_taskgroup: 10149 case OMPD_atomic: 10150 case OMPD_flush: 10151 case OMPD_teams: 10152 case OMPD_target_data: 10153 case OMPD_distribute: 10154 case OMPD_distribute_simd: 10155 case OMPD_distribute_parallel_for: 10156 case OMPD_distribute_parallel_for_simd: 10157 case OMPD_teams_distribute: 10158 case OMPD_teams_distribute_simd: 10159 case OMPD_teams_distribute_parallel_for: 10160 case OMPD_teams_distribute_parallel_for_simd: 10161 case OMPD_declare_simd: 10162 case OMPD_declare_variant: 10163 case OMPD_declare_target: 10164 case OMPD_end_declare_target: 10165 case OMPD_declare_reduction: 10166 case OMPD_declare_mapper: 10167 case OMPD_taskloop: 10168 case OMPD_taskloop_simd: 10169 case OMPD_master_taskloop: 10170 case OMPD_master_taskloop_simd: 10171 case OMPD_parallel_master_taskloop: 10172 case OMPD_parallel_master_taskloop_simd: 10173 case OMPD_target: 10174 case OMPD_target_simd: 10175 case OMPD_target_teams_distribute: 10176 case OMPD_target_teams_distribute_simd: 10177 case OMPD_target_teams_distribute_parallel_for: 10178 case OMPD_target_teams_distribute_parallel_for_simd: 10179 case OMPD_target_teams: 10180 case OMPD_target_parallel: 10181 case OMPD_target_parallel_for: 10182 case OMPD_target_parallel_for_simd: 10183 case OMPD_requires: 10184 case OMPD_unknown: 10185 llvm_unreachable("Unexpected standalone target data directive."); 10186 break; 10187 } 10188 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10189 }; 10190 10191 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10192 CodeGenFunction &CGF, PrePostActionTy &) { 10193 // Fill up the arrays with all the mapped variables. 10194 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10195 MappableExprsHandler::MapValuesArrayTy Pointers; 10196 MappableExprsHandler::MapValuesArrayTy Sizes; 10197 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10198 10199 // Get map clause information. 10200 MappableExprsHandler MEHandler(D, CGF); 10201 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10202 10203 TargetDataInfo Info; 10204 // Fill up the arrays and create the arguments. 10205 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10206 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10207 Info.PointersArray, Info.SizesArray, 10208 Info.MapTypesArray, Info); 10209 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10210 InputInfo.BasePointersArray = 10211 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10212 InputInfo.PointersArray = 10213 Address(Info.PointersArray, CGM.getPointerAlign()); 10214 InputInfo.SizesArray = 10215 Address(Info.SizesArray, CGM.getPointerAlign()); 10216 MapTypesArray = Info.MapTypesArray; 10217 if (D.hasClausesOfKind<OMPDependClause>()) 10218 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10219 else 10220 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10221 }; 10222 10223 if (IfCond) { 10224 emitIfClause(CGF, IfCond, TargetThenGen, 10225 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10226 } else { 10227 RegionCodeGenTy ThenRCG(TargetThenGen); 10228 ThenRCG(CGF); 10229 } 10230 } 10231 10232 namespace { 10233 /// Kind of parameter in a function with 'declare simd' directive. 10234 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10235 /// Attribute set of the parameter. 10236 struct ParamAttrTy { 10237 ParamKindTy Kind = Vector; 10238 llvm::APSInt StrideOrArg; 10239 llvm::APSInt Alignment; 10240 }; 10241 } // namespace 10242 10243 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10244 ArrayRef<ParamAttrTy> ParamAttrs) { 10245 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10246 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10247 // of that clause. The VLEN value must be power of 2. 10248 // In other case the notion of the function`s "characteristic data type" (CDT) 10249 // is used to compute the vector length. 10250 // CDT is defined in the following order: 10251 // a) For non-void function, the CDT is the return type. 10252 // b) If the function has any non-uniform, non-linear parameters, then the 10253 // CDT is the type of the first such parameter. 10254 // c) If the CDT determined by a) or b) above is struct, union, or class 10255 // type which is pass-by-value (except for the type that maps to the 10256 // built-in complex data type), the characteristic data type is int. 10257 // d) If none of the above three cases is applicable, the CDT is int. 10258 // The VLEN is then determined based on the CDT and the size of vector 10259 // register of that ISA for which current vector version is generated. The 10260 // VLEN is computed using the formula below: 10261 // VLEN = sizeof(vector_register) / sizeof(CDT), 10262 // where vector register size specified in section 3.2.1 Registers and the 10263 // Stack Frame of original AMD64 ABI document. 10264 QualType RetType = FD->getReturnType(); 10265 if (RetType.isNull()) 10266 return 0; 10267 ASTContext &C = FD->getASTContext(); 10268 QualType CDT; 10269 if (!RetType.isNull() && !RetType->isVoidType()) { 10270 CDT = RetType; 10271 } else { 10272 unsigned Offset = 0; 10273 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10274 if (ParamAttrs[Offset].Kind == Vector) 10275 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10276 ++Offset; 10277 } 10278 if (CDT.isNull()) { 10279 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10280 if (ParamAttrs[I + Offset].Kind == Vector) { 10281 CDT = FD->getParamDecl(I)->getType(); 10282 break; 10283 } 10284 } 10285 } 10286 } 10287 if (CDT.isNull()) 10288 CDT = C.IntTy; 10289 CDT = CDT->getCanonicalTypeUnqualified(); 10290 if (CDT->isRecordType() || CDT->isUnionType()) 10291 CDT = C.IntTy; 10292 return C.getTypeSize(CDT); 10293 } 10294 10295 static void 10296 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10297 const llvm::APSInt &VLENVal, 10298 ArrayRef<ParamAttrTy> ParamAttrs, 10299 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10300 struct ISADataTy { 10301 char ISA; 10302 unsigned VecRegSize; 10303 }; 10304 ISADataTy ISAData[] = { 10305 { 10306 'b', 128 10307 }, // SSE 10308 { 10309 'c', 256 10310 }, // AVX 10311 { 10312 'd', 256 10313 }, // AVX2 10314 { 10315 'e', 512 10316 }, // AVX512 10317 }; 10318 llvm::SmallVector<char, 2> Masked; 10319 switch (State) { 10320 case OMPDeclareSimdDeclAttr::BS_Undefined: 10321 Masked.push_back('N'); 10322 Masked.push_back('M'); 10323 break; 10324 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10325 Masked.push_back('N'); 10326 break; 10327 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10328 Masked.push_back('M'); 10329 break; 10330 } 10331 for (char Mask : Masked) { 10332 for (const ISADataTy &Data : ISAData) { 10333 SmallString<256> Buffer; 10334 llvm::raw_svector_ostream Out(Buffer); 10335 Out << "_ZGV" << Data.ISA << Mask; 10336 if (!VLENVal) { 10337 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10338 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10339 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10340 } else { 10341 Out << VLENVal; 10342 } 10343 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10344 switch (ParamAttr.Kind){ 10345 case LinearWithVarStride: 10346 Out << 's' << ParamAttr.StrideOrArg; 10347 break; 10348 case Linear: 10349 Out << 'l'; 10350 if (!!ParamAttr.StrideOrArg) 10351 Out << ParamAttr.StrideOrArg; 10352 break; 10353 case Uniform: 10354 Out << 'u'; 10355 break; 10356 case Vector: 10357 Out << 'v'; 10358 break; 10359 } 10360 if (!!ParamAttr.Alignment) 10361 Out << 'a' << ParamAttr.Alignment; 10362 } 10363 Out << '_' << Fn->getName(); 10364 Fn->addFnAttr(Out.str()); 10365 } 10366 } 10367 } 10368 10369 // This are the Functions that are needed to mangle the name of the 10370 // vector functions generated by the compiler, according to the rules 10371 // defined in the "Vector Function ABI specifications for AArch64", 10372 // available at 10373 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10374 10375 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10376 /// 10377 /// TODO: Need to implement the behavior for reference marked with a 10378 /// var or no linear modifiers (1.b in the section). For this, we 10379 /// need to extend ParamKindTy to support the linear modifiers. 10380 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10381 QT = QT.getCanonicalType(); 10382 10383 if (QT->isVoidType()) 10384 return false; 10385 10386 if (Kind == ParamKindTy::Uniform) 10387 return false; 10388 10389 if (Kind == ParamKindTy::Linear) 10390 return false; 10391 10392 // TODO: Handle linear references with modifiers 10393 10394 if (Kind == ParamKindTy::LinearWithVarStride) 10395 return false; 10396 10397 return true; 10398 } 10399 10400 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10401 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10402 QT = QT.getCanonicalType(); 10403 unsigned Size = C.getTypeSize(QT); 10404 10405 // Only scalars and complex within 16 bytes wide set PVB to true. 10406 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10407 return false; 10408 10409 if (QT->isFloatingType()) 10410 return true; 10411 10412 if (QT->isIntegerType()) 10413 return true; 10414 10415 if (QT->isPointerType()) 10416 return true; 10417 10418 // TODO: Add support for complex types (section 3.1.2, item 2). 10419 10420 return false; 10421 } 10422 10423 /// Computes the lane size (LS) of a return type or of an input parameter, 10424 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10425 /// TODO: Add support for references, section 3.2.1, item 1. 10426 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10427 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10428 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10429 if (getAArch64PBV(PTy, C)) 10430 return C.getTypeSize(PTy); 10431 } 10432 if (getAArch64PBV(QT, C)) 10433 return C.getTypeSize(QT); 10434 10435 return C.getTypeSize(C.getUIntPtrType()); 10436 } 10437 10438 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10439 // signature of the scalar function, as defined in 3.2.2 of the 10440 // AAVFABI. 10441 static std::tuple<unsigned, unsigned, bool> 10442 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10443 QualType RetType = FD->getReturnType().getCanonicalType(); 10444 10445 ASTContext &C = FD->getASTContext(); 10446 10447 bool OutputBecomesInput = false; 10448 10449 llvm::SmallVector<unsigned, 8> Sizes; 10450 if (!RetType->isVoidType()) { 10451 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10452 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10453 OutputBecomesInput = true; 10454 } 10455 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10456 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10457 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10458 } 10459 10460 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10461 // The LS of a function parameter / return value can only be a power 10462 // of 2, starting from 8 bits, up to 128. 10463 assert(std::all_of(Sizes.begin(), Sizes.end(), 10464 [](unsigned Size) { 10465 return Size == 8 || Size == 16 || Size == 32 || 10466 Size == 64 || Size == 128; 10467 }) && 10468 "Invalid size"); 10469 10470 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10471 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10472 OutputBecomesInput); 10473 } 10474 10475 /// Mangle the parameter part of the vector function name according to 10476 /// their OpenMP classification. The mangling function is defined in 10477 /// section 3.5 of the AAVFABI. 10478 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10479 SmallString<256> Buffer; 10480 llvm::raw_svector_ostream Out(Buffer); 10481 for (const auto &ParamAttr : ParamAttrs) { 10482 switch (ParamAttr.Kind) { 10483 case LinearWithVarStride: 10484 Out << "ls" << ParamAttr.StrideOrArg; 10485 break; 10486 case Linear: 10487 Out << 'l'; 10488 // Don't print the step value if it is not present or if it is 10489 // equal to 1. 10490 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10491 Out << ParamAttr.StrideOrArg; 10492 break; 10493 case Uniform: 10494 Out << 'u'; 10495 break; 10496 case Vector: 10497 Out << 'v'; 10498 break; 10499 } 10500 10501 if (!!ParamAttr.Alignment) 10502 Out << 'a' << ParamAttr.Alignment; 10503 } 10504 10505 return std::string(Out.str()); 10506 } 10507 10508 // Function used to add the attribute. The parameter `VLEN` is 10509 // templated to allow the use of "x" when targeting scalable functions 10510 // for SVE. 10511 template <typename T> 10512 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10513 char ISA, StringRef ParSeq, 10514 StringRef MangledName, bool OutputBecomesInput, 10515 llvm::Function *Fn) { 10516 SmallString<256> Buffer; 10517 llvm::raw_svector_ostream Out(Buffer); 10518 Out << Prefix << ISA << LMask << VLEN; 10519 if (OutputBecomesInput) 10520 Out << "v"; 10521 Out << ParSeq << "_" << MangledName; 10522 Fn->addFnAttr(Out.str()); 10523 } 10524 10525 // Helper function to generate the Advanced SIMD names depending on 10526 // the value of the NDS when simdlen is not present. 10527 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10528 StringRef Prefix, char ISA, 10529 StringRef ParSeq, StringRef MangledName, 10530 bool OutputBecomesInput, 10531 llvm::Function *Fn) { 10532 switch (NDS) { 10533 case 8: 10534 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10535 OutputBecomesInput, Fn); 10536 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10537 OutputBecomesInput, Fn); 10538 break; 10539 case 16: 10540 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10541 OutputBecomesInput, Fn); 10542 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10543 OutputBecomesInput, Fn); 10544 break; 10545 case 32: 10546 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10547 OutputBecomesInput, Fn); 10548 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10549 OutputBecomesInput, Fn); 10550 break; 10551 case 64: 10552 case 128: 10553 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10554 OutputBecomesInput, Fn); 10555 break; 10556 default: 10557 llvm_unreachable("Scalar type is too wide."); 10558 } 10559 } 10560 10561 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10562 static void emitAArch64DeclareSimdFunction( 10563 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10564 ArrayRef<ParamAttrTy> ParamAttrs, 10565 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10566 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10567 10568 // Get basic data for building the vector signature. 10569 const auto Data = getNDSWDS(FD, ParamAttrs); 10570 const unsigned NDS = std::get<0>(Data); 10571 const unsigned WDS = std::get<1>(Data); 10572 const bool OutputBecomesInput = std::get<2>(Data); 10573 10574 // Check the values provided via `simdlen` by the user. 10575 // 1. A `simdlen(1)` doesn't produce vector signatures, 10576 if (UserVLEN == 1) { 10577 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10578 DiagnosticsEngine::Warning, 10579 "The clause simdlen(1) has no effect when targeting aarch64."); 10580 CGM.getDiags().Report(SLoc, DiagID); 10581 return; 10582 } 10583 10584 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10585 // Advanced SIMD output. 10586 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10587 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10588 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10589 "power of 2 when targeting Advanced SIMD."); 10590 CGM.getDiags().Report(SLoc, DiagID); 10591 return; 10592 } 10593 10594 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10595 // limits. 10596 if (ISA == 's' && UserVLEN != 0) { 10597 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10598 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10599 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10600 "lanes in the architectural constraints " 10601 "for SVE (min is 128-bit, max is " 10602 "2048-bit, by steps of 128-bit)"); 10603 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10604 return; 10605 } 10606 } 10607 10608 // Sort out parameter sequence. 10609 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10610 StringRef Prefix = "_ZGV"; 10611 // Generate simdlen from user input (if any). 10612 if (UserVLEN) { 10613 if (ISA == 's') { 10614 // SVE generates only a masked function. 10615 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10616 OutputBecomesInput, Fn); 10617 } else { 10618 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10619 // Advanced SIMD generates one or two functions, depending on 10620 // the `[not]inbranch` clause. 10621 switch (State) { 10622 case OMPDeclareSimdDeclAttr::BS_Undefined: 10623 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10624 OutputBecomesInput, Fn); 10625 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10626 OutputBecomesInput, Fn); 10627 break; 10628 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10629 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10630 OutputBecomesInput, Fn); 10631 break; 10632 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10633 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10634 OutputBecomesInput, Fn); 10635 break; 10636 } 10637 } 10638 } else { 10639 // If no user simdlen is provided, follow the AAVFABI rules for 10640 // generating the vector length. 10641 if (ISA == 's') { 10642 // SVE, section 3.4.1, item 1. 10643 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10644 OutputBecomesInput, Fn); 10645 } else { 10646 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10647 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10648 // two vector names depending on the use of the clause 10649 // `[not]inbranch`. 10650 switch (State) { 10651 case OMPDeclareSimdDeclAttr::BS_Undefined: 10652 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10653 OutputBecomesInput, Fn); 10654 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10655 OutputBecomesInput, Fn); 10656 break; 10657 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10658 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10659 OutputBecomesInput, Fn); 10660 break; 10661 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10662 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10663 OutputBecomesInput, Fn); 10664 break; 10665 } 10666 } 10667 } 10668 } 10669 10670 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10671 llvm::Function *Fn) { 10672 ASTContext &C = CGM.getContext(); 10673 FD = FD->getMostRecentDecl(); 10674 // Map params to their positions in function decl. 10675 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10676 if (isa<CXXMethodDecl>(FD)) 10677 ParamPositions.try_emplace(FD, 0); 10678 unsigned ParamPos = ParamPositions.size(); 10679 for (const ParmVarDecl *P : FD->parameters()) { 10680 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10681 ++ParamPos; 10682 } 10683 while (FD) { 10684 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10685 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10686 // Mark uniform parameters. 10687 for (const Expr *E : Attr->uniforms()) { 10688 E = E->IgnoreParenImpCasts(); 10689 unsigned Pos; 10690 if (isa<CXXThisExpr>(E)) { 10691 Pos = ParamPositions[FD]; 10692 } else { 10693 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10694 ->getCanonicalDecl(); 10695 Pos = ParamPositions[PVD]; 10696 } 10697 ParamAttrs[Pos].Kind = Uniform; 10698 } 10699 // Get alignment info. 10700 auto NI = Attr->alignments_begin(); 10701 for (const Expr *E : Attr->aligneds()) { 10702 E = E->IgnoreParenImpCasts(); 10703 unsigned Pos; 10704 QualType ParmTy; 10705 if (isa<CXXThisExpr>(E)) { 10706 Pos = ParamPositions[FD]; 10707 ParmTy = E->getType(); 10708 } else { 10709 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10710 ->getCanonicalDecl(); 10711 Pos = ParamPositions[PVD]; 10712 ParmTy = PVD->getType(); 10713 } 10714 ParamAttrs[Pos].Alignment = 10715 (*NI) 10716 ? (*NI)->EvaluateKnownConstInt(C) 10717 : llvm::APSInt::getUnsigned( 10718 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10719 .getQuantity()); 10720 ++NI; 10721 } 10722 // Mark linear parameters. 10723 auto SI = Attr->steps_begin(); 10724 auto MI = Attr->modifiers_begin(); 10725 for (const Expr *E : Attr->linears()) { 10726 E = E->IgnoreParenImpCasts(); 10727 unsigned Pos; 10728 if (isa<CXXThisExpr>(E)) { 10729 Pos = ParamPositions[FD]; 10730 } else { 10731 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10732 ->getCanonicalDecl(); 10733 Pos = ParamPositions[PVD]; 10734 } 10735 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10736 ParamAttr.Kind = Linear; 10737 if (*SI) { 10738 Expr::EvalResult Result; 10739 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10740 if (const auto *DRE = 10741 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10742 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10743 ParamAttr.Kind = LinearWithVarStride; 10744 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10745 ParamPositions[StridePVD->getCanonicalDecl()]); 10746 } 10747 } 10748 } else { 10749 ParamAttr.StrideOrArg = Result.Val.getInt(); 10750 } 10751 } 10752 ++SI; 10753 ++MI; 10754 } 10755 llvm::APSInt VLENVal; 10756 SourceLocation ExprLoc; 10757 const Expr *VLENExpr = Attr->getSimdlen(); 10758 if (VLENExpr) { 10759 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10760 ExprLoc = VLENExpr->getExprLoc(); 10761 } 10762 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10763 if (CGM.getTriple().isX86()) { 10764 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10765 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10766 unsigned VLEN = VLENVal.getExtValue(); 10767 StringRef MangledName = Fn->getName(); 10768 if (CGM.getTarget().hasFeature("sve")) 10769 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10770 MangledName, 's', 128, Fn, ExprLoc); 10771 if (CGM.getTarget().hasFeature("neon")) 10772 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10773 MangledName, 'n', 128, Fn, ExprLoc); 10774 } 10775 } 10776 FD = FD->getPreviousDecl(); 10777 } 10778 } 10779 10780 namespace { 10781 /// Cleanup action for doacross support. 10782 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10783 public: 10784 static const int DoacrossFinArgs = 2; 10785 10786 private: 10787 llvm::FunctionCallee RTLFn; 10788 llvm::Value *Args[DoacrossFinArgs]; 10789 10790 public: 10791 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10792 ArrayRef<llvm::Value *> CallArgs) 10793 : RTLFn(RTLFn) { 10794 assert(CallArgs.size() == DoacrossFinArgs); 10795 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10796 } 10797 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10798 if (!CGF.HaveInsertPoint()) 10799 return; 10800 CGF.EmitRuntimeCall(RTLFn, Args); 10801 } 10802 }; 10803 } // namespace 10804 10805 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10806 const OMPLoopDirective &D, 10807 ArrayRef<Expr *> NumIterations) { 10808 if (!CGF.HaveInsertPoint()) 10809 return; 10810 10811 ASTContext &C = CGM.getContext(); 10812 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10813 RecordDecl *RD; 10814 if (KmpDimTy.isNull()) { 10815 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10816 // kmp_int64 lo; // lower 10817 // kmp_int64 up; // upper 10818 // kmp_int64 st; // stride 10819 // }; 10820 RD = C.buildImplicitRecord("kmp_dim"); 10821 RD->startDefinition(); 10822 addFieldToRecordDecl(C, RD, Int64Ty); 10823 addFieldToRecordDecl(C, RD, Int64Ty); 10824 addFieldToRecordDecl(C, RD, Int64Ty); 10825 RD->completeDefinition(); 10826 KmpDimTy = C.getRecordType(RD); 10827 } else { 10828 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10829 } 10830 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10831 QualType ArrayTy = 10832 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 10833 10834 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10835 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10836 enum { LowerFD = 0, UpperFD, StrideFD }; 10837 // Fill dims with data. 10838 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10839 LValue DimsLVal = CGF.MakeAddrLValue( 10840 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10841 // dims.upper = num_iterations; 10842 LValue UpperLVal = CGF.EmitLValueForField( 10843 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10844 llvm::Value *NumIterVal = 10845 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10846 D.getNumIterations()->getType(), Int64Ty, 10847 D.getNumIterations()->getExprLoc()); 10848 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10849 // dims.stride = 1; 10850 LValue StrideLVal = CGF.EmitLValueForField( 10851 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10852 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10853 StrideLVal); 10854 } 10855 10856 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10857 // kmp_int32 num_dims, struct kmp_dim * dims); 10858 llvm::Value *Args[] = { 10859 emitUpdateLocation(CGF, D.getBeginLoc()), 10860 getThreadID(CGF, D.getBeginLoc()), 10861 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10862 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10863 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10864 CGM.VoidPtrTy)}; 10865 10866 llvm::FunctionCallee RTLFn = 10867 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 10868 CGF.EmitRuntimeCall(RTLFn, Args); 10869 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10870 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10871 llvm::FunctionCallee FiniRTLFn = 10872 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 10873 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10874 llvm::makeArrayRef(FiniArgs)); 10875 } 10876 10877 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10878 const OMPDependClause *C) { 10879 QualType Int64Ty = 10880 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10881 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10882 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10883 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 10884 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10885 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10886 const Expr *CounterVal = C->getLoopData(I); 10887 assert(CounterVal); 10888 llvm::Value *CntVal = CGF.EmitScalarConversion( 10889 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10890 CounterVal->getExprLoc()); 10891 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10892 /*Volatile=*/false, Int64Ty); 10893 } 10894 llvm::Value *Args[] = { 10895 emitUpdateLocation(CGF, C->getBeginLoc()), 10896 getThreadID(CGF, C->getBeginLoc()), 10897 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10898 llvm::FunctionCallee RTLFn; 10899 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10900 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 10901 } else { 10902 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10903 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 10904 } 10905 CGF.EmitRuntimeCall(RTLFn, Args); 10906 } 10907 10908 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10909 llvm::FunctionCallee Callee, 10910 ArrayRef<llvm::Value *> Args) const { 10911 assert(Loc.isValid() && "Outlined function call location must be valid."); 10912 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10913 10914 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10915 if (Fn->doesNotThrow()) { 10916 CGF.EmitNounwindRuntimeCall(Fn, Args); 10917 return; 10918 } 10919 } 10920 CGF.EmitRuntimeCall(Callee, Args); 10921 } 10922 10923 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10924 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10925 ArrayRef<llvm::Value *> Args) const { 10926 emitCall(CGF, Loc, OutlinedFn, Args); 10927 } 10928 10929 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10930 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 10931 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 10932 HasEmittedDeclareTargetRegion = true; 10933 } 10934 10935 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 10936 const VarDecl *NativeParam, 10937 const VarDecl *TargetParam) const { 10938 return CGF.GetAddrOfLocalVar(NativeParam); 10939 } 10940 10941 namespace { 10942 /// Cleanup action for allocate support. 10943 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 10944 public: 10945 static const int CleanupArgs = 3; 10946 10947 private: 10948 llvm::FunctionCallee RTLFn; 10949 llvm::Value *Args[CleanupArgs]; 10950 10951 public: 10952 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 10953 ArrayRef<llvm::Value *> CallArgs) 10954 : RTLFn(RTLFn) { 10955 assert(CallArgs.size() == CleanupArgs && 10956 "Size of arguments does not match."); 10957 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10958 } 10959 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10960 if (!CGF.HaveInsertPoint()) 10961 return; 10962 CGF.EmitRuntimeCall(RTLFn, Args); 10963 } 10964 }; 10965 } // namespace 10966 10967 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 10968 const VarDecl *VD) { 10969 if (!VD) 10970 return Address::invalid(); 10971 const VarDecl *CVD = VD->getCanonicalDecl(); 10972 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 10973 return Address::invalid(); 10974 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 10975 // Use the default allocation. 10976 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 10977 !AA->getAllocator()) 10978 return Address::invalid(); 10979 llvm::Value *Size; 10980 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 10981 if (CVD->getType()->isVariablyModifiedType()) { 10982 Size = CGF.getTypeSize(CVD->getType()); 10983 // Align the size: ((size + align - 1) / align) * align 10984 Size = CGF.Builder.CreateNUWAdd( 10985 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 10986 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 10987 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 10988 } else { 10989 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 10990 Size = CGM.getSize(Sz.alignTo(Align)); 10991 } 10992 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 10993 assert(AA->getAllocator() && 10994 "Expected allocator expression for non-default allocator."); 10995 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 10996 // According to the standard, the original allocator type is a enum (integer). 10997 // Convert to pointer type, if required. 10998 if (Allocator->getType()->isIntegerTy()) 10999 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 11000 else if (Allocator->getType()->isPointerTy()) 11001 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 11002 CGM.VoidPtrTy); 11003 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 11004 11005 llvm::Value *Addr = 11006 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 11007 getName({CVD->getName(), ".void.addr"})); 11008 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 11009 Allocator}; 11010 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 11011 11012 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11013 llvm::makeArrayRef(FiniArgs)); 11014 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11015 Addr, 11016 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11017 getName({CVD->getName(), ".addr"})); 11018 return Address(Addr, Align); 11019 } 11020 11021 namespace { 11022 using OMPContextSelectorData = 11023 OpenMPCtxSelectorData<ArrayRef<StringRef>, llvm::APSInt>; 11024 using CompleteOMPContextSelectorData = SmallVector<OMPContextSelectorData, 4>; 11025 } // anonymous namespace 11026 11027 /// Checks current context and returns true if it matches the context selector. 11028 template <OpenMPContextSelectorSetKind CtxSet, OpenMPContextSelectorKind Ctx, 11029 typename... Arguments> 11030 static bool checkContext(const OMPContextSelectorData &Data, 11031 Arguments... Params) { 11032 assert(Data.CtxSet != OMP_CTX_SET_unknown && Data.Ctx != OMP_CTX_unknown && 11033 "Unknown context selector or context selector set."); 11034 return false; 11035 } 11036 11037 /// Checks for implementation={vendor(<vendor>)} context selector. 11038 /// \returns true iff <vendor>="llvm", false otherwise. 11039 template <> 11040 bool checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>( 11041 const OMPContextSelectorData &Data) { 11042 return llvm::all_of(Data.Names, 11043 [](StringRef S) { return !S.compare_lower("llvm"); }); 11044 } 11045 11046 /// Checks for device={kind(<kind>)} context selector. 11047 /// \returns true if <kind>="host" and compilation is for host. 11048 /// true if <kind>="nohost" and compilation is for device. 11049 /// true if <kind>="cpu" and compilation is for Arm, X86 or PPC CPU. 11050 /// true if <kind>="gpu" and compilation is for NVPTX or AMDGCN. 11051 /// false otherwise. 11052 template <> 11053 bool checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>( 11054 const OMPContextSelectorData &Data, CodeGenModule &CGM) { 11055 for (StringRef Name : Data.Names) { 11056 if (!Name.compare_lower("host")) { 11057 if (CGM.getLangOpts().OpenMPIsDevice) 11058 return false; 11059 continue; 11060 } 11061 if (!Name.compare_lower("nohost")) { 11062 if (!CGM.getLangOpts().OpenMPIsDevice) 11063 return false; 11064 continue; 11065 } 11066 switch (CGM.getTriple().getArch()) { 11067 case llvm::Triple::arm: 11068 case llvm::Triple::armeb: 11069 case llvm::Triple::aarch64: 11070 case llvm::Triple::aarch64_be: 11071 case llvm::Triple::aarch64_32: 11072 case llvm::Triple::ppc: 11073 case llvm::Triple::ppc64: 11074 case llvm::Triple::ppc64le: 11075 case llvm::Triple::x86: 11076 case llvm::Triple::x86_64: 11077 if (Name.compare_lower("cpu")) 11078 return false; 11079 break; 11080 case llvm::Triple::amdgcn: 11081 case llvm::Triple::nvptx: 11082 case llvm::Triple::nvptx64: 11083 if (Name.compare_lower("gpu")) 11084 return false; 11085 break; 11086 case llvm::Triple::UnknownArch: 11087 case llvm::Triple::arc: 11088 case llvm::Triple::avr: 11089 case llvm::Triple::bpfel: 11090 case llvm::Triple::bpfeb: 11091 case llvm::Triple::hexagon: 11092 case llvm::Triple::mips: 11093 case llvm::Triple::mipsel: 11094 case llvm::Triple::mips64: 11095 case llvm::Triple::mips64el: 11096 case llvm::Triple::msp430: 11097 case llvm::Triple::r600: 11098 case llvm::Triple::riscv32: 11099 case llvm::Triple::riscv64: 11100 case llvm::Triple::sparc: 11101 case llvm::Triple::sparcv9: 11102 case llvm::Triple::sparcel: 11103 case llvm::Triple::systemz: 11104 case llvm::Triple::tce: 11105 case llvm::Triple::tcele: 11106 case llvm::Triple::thumb: 11107 case llvm::Triple::thumbeb: 11108 case llvm::Triple::xcore: 11109 case llvm::Triple::le32: 11110 case llvm::Triple::le64: 11111 case llvm::Triple::amdil: 11112 case llvm::Triple::amdil64: 11113 case llvm::Triple::hsail: 11114 case llvm::Triple::hsail64: 11115 case llvm::Triple::spir: 11116 case llvm::Triple::spir64: 11117 case llvm::Triple::kalimba: 11118 case llvm::Triple::shave: 11119 case llvm::Triple::lanai: 11120 case llvm::Triple::wasm32: 11121 case llvm::Triple::wasm64: 11122 case llvm::Triple::renderscript32: 11123 case llvm::Triple::renderscript64: 11124 case llvm::Triple::ve: 11125 return false; 11126 } 11127 } 11128 return true; 11129 } 11130 11131 static bool matchesContext(CodeGenModule &CGM, 11132 const CompleteOMPContextSelectorData &ContextData) { 11133 for (const OMPContextSelectorData &Data : ContextData) { 11134 switch (Data.Ctx) { 11135 case OMP_CTX_vendor: 11136 assert(Data.CtxSet == OMP_CTX_SET_implementation && 11137 "Expected implementation context selector set."); 11138 if (!checkContext<OMP_CTX_SET_implementation, OMP_CTX_vendor>(Data)) 11139 return false; 11140 break; 11141 case OMP_CTX_kind: 11142 assert(Data.CtxSet == OMP_CTX_SET_device && 11143 "Expected device context selector set."); 11144 if (!checkContext<OMP_CTX_SET_device, OMP_CTX_kind, CodeGenModule &>(Data, 11145 CGM)) 11146 return false; 11147 break; 11148 case OMP_CTX_unknown: 11149 llvm_unreachable("Unknown context selector kind."); 11150 } 11151 } 11152 return true; 11153 } 11154 11155 static CompleteOMPContextSelectorData 11156 translateAttrToContextSelectorData(ASTContext &C, 11157 const OMPDeclareVariantAttr *A) { 11158 CompleteOMPContextSelectorData Data; 11159 for (unsigned I = 0, E = A->scores_size(); I < E; ++I) { 11160 Data.emplace_back(); 11161 auto CtxSet = static_cast<OpenMPContextSelectorSetKind>( 11162 *std::next(A->ctxSelectorSets_begin(), I)); 11163 auto Ctx = static_cast<OpenMPContextSelectorKind>( 11164 *std::next(A->ctxSelectors_begin(), I)); 11165 Data.back().CtxSet = CtxSet; 11166 Data.back().Ctx = Ctx; 11167 const Expr *Score = *std::next(A->scores_begin(), I); 11168 Data.back().Score = Score->EvaluateKnownConstInt(C); 11169 switch (Ctx) { 11170 case OMP_CTX_vendor: 11171 assert(CtxSet == OMP_CTX_SET_implementation && 11172 "Expected implementation context selector set."); 11173 Data.back().Names = 11174 llvm::makeArrayRef(A->implVendors_begin(), A->implVendors_end()); 11175 break; 11176 case OMP_CTX_kind: 11177 assert(CtxSet == OMP_CTX_SET_device && 11178 "Expected device context selector set."); 11179 Data.back().Names = 11180 llvm::makeArrayRef(A->deviceKinds_begin(), A->deviceKinds_end()); 11181 break; 11182 case OMP_CTX_unknown: 11183 llvm_unreachable("Unknown context selector kind."); 11184 } 11185 } 11186 return Data; 11187 } 11188 11189 static bool isStrictSubset(const CompleteOMPContextSelectorData &LHS, 11190 const CompleteOMPContextSelectorData &RHS) { 11191 llvm::SmallDenseMap<std::pair<int, int>, llvm::StringSet<>, 4> RHSData; 11192 for (const OMPContextSelectorData &D : RHS) { 11193 auto &Pair = RHSData.FindAndConstruct(std::make_pair(D.CtxSet, D.Ctx)); 11194 Pair.getSecond().insert(D.Names.begin(), D.Names.end()); 11195 } 11196 bool AllSetsAreEqual = true; 11197 for (const OMPContextSelectorData &D : LHS) { 11198 auto It = RHSData.find(std::make_pair(D.CtxSet, D.Ctx)); 11199 if (It == RHSData.end()) 11200 return false; 11201 if (D.Names.size() > It->getSecond().size()) 11202 return false; 11203 if (llvm::set_union(It->getSecond(), D.Names)) 11204 return false; 11205 AllSetsAreEqual = 11206 AllSetsAreEqual && (D.Names.size() == It->getSecond().size()); 11207 } 11208 11209 return LHS.size() != RHS.size() || !AllSetsAreEqual; 11210 } 11211 11212 static bool greaterCtxScore(const CompleteOMPContextSelectorData &LHS, 11213 const CompleteOMPContextSelectorData &RHS) { 11214 // Score is calculated as sum of all scores + 1. 11215 llvm::APSInt LHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11216 bool RHSIsSubsetOfLHS = isStrictSubset(RHS, LHS); 11217 if (RHSIsSubsetOfLHS) { 11218 LHSScore = llvm::APSInt::get(0); 11219 } else { 11220 for (const OMPContextSelectorData &Data : LHS) { 11221 if (Data.Score.getBitWidth() > LHSScore.getBitWidth()) { 11222 LHSScore = LHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11223 } else if (Data.Score.getBitWidth() < LHSScore.getBitWidth()) { 11224 LHSScore += Data.Score.extend(LHSScore.getBitWidth()); 11225 } else { 11226 LHSScore += Data.Score; 11227 } 11228 } 11229 } 11230 llvm::APSInt RHSScore(llvm::APInt(64, 1), /*isUnsigned=*/false); 11231 if (!RHSIsSubsetOfLHS && isStrictSubset(LHS, RHS)) { 11232 RHSScore = llvm::APSInt::get(0); 11233 } else { 11234 for (const OMPContextSelectorData &Data : RHS) { 11235 if (Data.Score.getBitWidth() > RHSScore.getBitWidth()) { 11236 RHSScore = RHSScore.extend(Data.Score.getBitWidth()) + Data.Score; 11237 } else if (Data.Score.getBitWidth() < RHSScore.getBitWidth()) { 11238 RHSScore += Data.Score.extend(RHSScore.getBitWidth()); 11239 } else { 11240 RHSScore += Data.Score; 11241 } 11242 } 11243 } 11244 return llvm::APSInt::compareValues(LHSScore, RHSScore) >= 0; 11245 } 11246 11247 /// Finds the variant function that matches current context with its context 11248 /// selector. 11249 static const FunctionDecl *getDeclareVariantFunction(CodeGenModule &CGM, 11250 const FunctionDecl *FD) { 11251 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11252 return FD; 11253 // Iterate through all DeclareVariant attributes and check context selectors. 11254 const OMPDeclareVariantAttr *TopMostAttr = nullptr; 11255 CompleteOMPContextSelectorData TopMostData; 11256 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11257 CompleteOMPContextSelectorData Data = 11258 translateAttrToContextSelectorData(CGM.getContext(), A); 11259 if (!matchesContext(CGM, Data)) 11260 continue; 11261 // If the attribute matches the context, find the attribute with the highest 11262 // score. 11263 if (!TopMostAttr || !greaterCtxScore(TopMostData, Data)) { 11264 TopMostAttr = A; 11265 TopMostData.swap(Data); 11266 } 11267 } 11268 if (!TopMostAttr) 11269 return FD; 11270 return cast<FunctionDecl>( 11271 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) 11272 ->getDecl()); 11273 } 11274 11275 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11276 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11277 // If the original function is defined already, use its definition. 11278 StringRef MangledName = CGM.getMangledName(GD); 11279 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11280 if (Orig && !Orig->isDeclaration()) 11281 return false; 11282 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM, D); 11283 // Emit original function if it does not have declare variant attribute or the 11284 // context does not match. 11285 if (NewFD == D) 11286 return false; 11287 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11288 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) { 11289 DeferredVariantFunction.erase(D); 11290 return true; 11291 } 11292 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11293 return true; 11294 } 11295 11296 CGOpenMPRuntime::NontemporalDeclsRAII::NontemporalDeclsRAII( 11297 CodeGenModule &CGM, const OMPLoopDirective &S) 11298 : CGM(CGM), NeedToPush(S.hasClausesOfKind<OMPNontemporalClause>()) { 11299 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11300 if (!NeedToPush) 11301 return; 11302 NontemporalDeclsSet &DS = 11303 CGM.getOpenMPRuntime().NontemporalDeclsStack.emplace_back(); 11304 for (const auto *C : S.getClausesOfKind<OMPNontemporalClause>()) { 11305 for (const Stmt *Ref : C->private_refs()) { 11306 const auto *SimpleRefExpr = cast<Expr>(Ref)->IgnoreParenImpCasts(); 11307 const ValueDecl *VD; 11308 if (const auto *DRE = dyn_cast<DeclRefExpr>(SimpleRefExpr)) { 11309 VD = DRE->getDecl(); 11310 } else { 11311 const auto *ME = cast<MemberExpr>(SimpleRefExpr); 11312 assert((ME->isImplicitCXXThis() || 11313 isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts())) && 11314 "Expected member of current class."); 11315 VD = ME->getMemberDecl(); 11316 } 11317 DS.insert(VD); 11318 } 11319 } 11320 } 11321 11322 CGOpenMPRuntime::NontemporalDeclsRAII::~NontemporalDeclsRAII() { 11323 if (!NeedToPush) 11324 return; 11325 CGM.getOpenMPRuntime().NontemporalDeclsStack.pop_back(); 11326 } 11327 11328 bool CGOpenMPRuntime::isNontemporalDecl(const ValueDecl *VD) const { 11329 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11330 11331 return llvm::any_of( 11332 CGM.getOpenMPRuntime().NontemporalDeclsStack, 11333 [VD](const NontemporalDeclsSet &Set) { return Set.count(VD) > 0; }); 11334 } 11335 11336 CGOpenMPRuntime::LastprivateConditionalRAII::LastprivateConditionalRAII( 11337 CodeGenFunction &CGF, const OMPExecutableDirective &S, LValue IVLVal) 11338 : CGM(CGF.CGM), 11339 NeedToPush(llvm::any_of(S.getClausesOfKind<OMPLastprivateClause>(), 11340 [](const OMPLastprivateClause *C) { 11341 return C->getKind() == 11342 OMPC_LASTPRIVATE_conditional; 11343 })) { 11344 assert(CGM.getLangOpts().OpenMP && "Not in OpenMP mode."); 11345 if (!NeedToPush) 11346 return; 11347 LastprivateConditionalData &Data = 11348 CGM.getOpenMPRuntime().LastprivateConditionalStack.emplace_back(); 11349 for (const auto *C : S.getClausesOfKind<OMPLastprivateClause>()) { 11350 if (C->getKind() != OMPC_LASTPRIVATE_conditional) 11351 continue; 11352 11353 for (const Expr *Ref : C->varlists()) { 11354 Data.DeclToUniqeName.try_emplace( 11355 cast<DeclRefExpr>(Ref->IgnoreParenImpCasts())->getDecl(), 11356 generateUniqueName(CGM, "pl_cond", Ref)); 11357 } 11358 } 11359 Data.IVLVal = IVLVal; 11360 Data.CGF = &CGF; 11361 } 11362 11363 CGOpenMPRuntime::LastprivateConditionalRAII::~LastprivateConditionalRAII() { 11364 if (!NeedToPush) 11365 return; 11366 CGM.getOpenMPRuntime().LastprivateConditionalStack.pop_back(); 11367 } 11368 11369 namespace { 11370 /// Checks if the lastprivate conditional variable is referenced in LHS. 11371 class LastprivateConditionalRefChecker final 11372 : public ConstStmtVisitor<LastprivateConditionalRefChecker, bool> { 11373 CodeGenFunction &CGF; 11374 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM; 11375 const Expr *FoundE = nullptr; 11376 const Decl *FoundD = nullptr; 11377 StringRef UniqueDeclName; 11378 LValue IVLVal; 11379 SourceLocation Loc; 11380 11381 public: 11382 bool VisitDeclRefExpr(const DeclRefExpr *E) { 11383 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11384 llvm::reverse(LPM)) { 11385 auto It = D.DeclToUniqeName.find(E->getDecl()); 11386 if (It == D.DeclToUniqeName.end()) 11387 continue; 11388 FoundE = E; 11389 FoundD = E->getDecl()->getCanonicalDecl(); 11390 UniqueDeclName = It->getSecond(); 11391 IVLVal = D.IVLVal; 11392 break; 11393 } 11394 return FoundE == E; 11395 } 11396 bool VisitMemberExpr(const MemberExpr *E) { 11397 if (!CGF.IsWrappedCXXThis(E->getBase())) 11398 return false; 11399 for (const CGOpenMPRuntime::LastprivateConditionalData &D : 11400 llvm::reverse(LPM)) { 11401 auto It = D.DeclToUniqeName.find(E->getMemberDecl()); 11402 if (It == D.DeclToUniqeName.end()) 11403 continue; 11404 FoundE = E; 11405 FoundD = E->getMemberDecl()->getCanonicalDecl(); 11406 UniqueDeclName = It->getSecond(); 11407 IVLVal = D.IVLVal; 11408 break; 11409 } 11410 return FoundE == E; 11411 } 11412 bool VisitStmt(const Stmt *S) { 11413 for (const Stmt *Child : S->children()) { 11414 if (!Child) 11415 continue; 11416 if (const auto *E = dyn_cast<Expr>(Child)) 11417 if (!E->isGLValue()) 11418 continue; 11419 if (Visit(Child)) 11420 return true; 11421 } 11422 return false; 11423 } 11424 explicit LastprivateConditionalRefChecker( 11425 CodeGenFunction &CGF, 11426 ArrayRef<CGOpenMPRuntime::LastprivateConditionalData> LPM) 11427 : CGF(CGF), LPM(LPM) {} 11428 std::tuple<const Expr *, const Decl *, StringRef, LValue> 11429 getFoundData() const { 11430 return std::make_tuple(FoundE, FoundD, UniqueDeclName, IVLVal); 11431 } 11432 }; 11433 } // namespace 11434 11435 void CGOpenMPRuntime::checkAndEmitLastprivateConditional(CodeGenFunction &CGF, 11436 const Expr *LHS) { 11437 if (CGF.getLangOpts().OpenMP < 50 || LastprivateConditionalStack.empty() || 11438 LastprivateConditionalStack.back().CGF != &CGF) 11439 return; 11440 LastprivateConditionalRefChecker Checker(CGF, LastprivateConditionalStack); 11441 if (!Checker.Visit(LHS)) 11442 return; 11443 const Expr *FoundE; 11444 const Decl *FoundD; 11445 StringRef UniqueDeclName; 11446 LValue IVLVal; 11447 std::tie(FoundE, FoundD, UniqueDeclName, IVLVal) = Checker.getFoundData(); 11448 11449 // Last updated loop counter for the lastprivate conditional var. 11450 // int<xx> last_iv = 0; 11451 llvm::Type *LLIVTy = CGF.ConvertTypeForMem(IVLVal.getType()); 11452 llvm::Constant *LastIV = 11453 getOrCreateInternalVariable(LLIVTy, getName({UniqueDeclName, "iv"})); 11454 cast<llvm::GlobalVariable>(LastIV)->setAlignment( 11455 IVLVal.getAlignment().getAsAlign()); 11456 LValue LastIVLVal = CGF.MakeNaturalAlignAddrLValue(LastIV, IVLVal.getType()); 11457 11458 // Private address of the lastprivate conditional in the current context. 11459 // priv_a 11460 LValue LVal = CGF.EmitLValue(FoundE); 11461 // Last value of the lastprivate conditional. 11462 // decltype(priv_a) last_a; 11463 llvm::Constant *Last = getOrCreateInternalVariable( 11464 LVal.getAddress(CGF).getElementType(), UniqueDeclName); 11465 cast<llvm::GlobalVariable>(Last)->setAlignment( 11466 LVal.getAlignment().getAsAlign()); 11467 LValue LastLVal = 11468 CGF.MakeAddrLValue(Last, LVal.getType(), LVal.getAlignment()); 11469 11470 // Global loop counter. Required to handle inner parallel-for regions. 11471 // global_iv 11472 llvm::Value *IVVal = CGF.EmitLoadOfScalar(IVLVal, FoundE->getExprLoc()); 11473 11474 // #pragma omp critical(a) 11475 // if (last_iv <= iv) { 11476 // last_iv = iv; 11477 // last_a = priv_a; 11478 // } 11479 auto &&CodeGen = [&LastIVLVal, &IVLVal, IVVal, &LVal, &LastLVal, 11480 FoundE](CodeGenFunction &CGF, PrePostActionTy &Action) { 11481 Action.Enter(CGF); 11482 llvm::Value *LastIVVal = 11483 CGF.EmitLoadOfScalar(LastIVLVal, FoundE->getExprLoc()); 11484 // (last_iv <= global_iv) ? Check if the variable is updated and store new 11485 // value in global var. 11486 llvm::Value *CmpRes; 11487 if (IVLVal.getType()->isSignedIntegerType()) { 11488 CmpRes = CGF.Builder.CreateICmpSLE(LastIVVal, IVVal); 11489 } else { 11490 assert(IVLVal.getType()->isUnsignedIntegerType() && 11491 "Loop iteration variable must be integer."); 11492 CmpRes = CGF.Builder.CreateICmpULE(LastIVVal, IVVal); 11493 } 11494 llvm::BasicBlock *ThenBB = CGF.createBasicBlock("lp_cond_then"); 11495 llvm::BasicBlock *ExitBB = CGF.createBasicBlock("lp_cond_exit"); 11496 CGF.Builder.CreateCondBr(CmpRes, ThenBB, ExitBB); 11497 // { 11498 CGF.EmitBlock(ThenBB); 11499 11500 // last_iv = global_iv; 11501 CGF.EmitStoreOfScalar(IVVal, LastIVLVal); 11502 11503 // last_a = priv_a; 11504 switch (CGF.getEvaluationKind(LVal.getType())) { 11505 case TEK_Scalar: { 11506 llvm::Value *PrivVal = CGF.EmitLoadOfScalar(LVal, FoundE->getExprLoc()); 11507 CGF.EmitStoreOfScalar(PrivVal, LastLVal); 11508 break; 11509 } 11510 case TEK_Complex: { 11511 CodeGenFunction::ComplexPairTy PrivVal = 11512 CGF.EmitLoadOfComplex(LVal, FoundE->getExprLoc()); 11513 CGF.EmitStoreOfComplex(PrivVal, LastLVal, /*isInit=*/false); 11514 break; 11515 } 11516 case TEK_Aggregate: 11517 llvm_unreachable( 11518 "Aggregates are not supported in lastprivate conditional."); 11519 } 11520 // } 11521 CGF.EmitBranch(ExitBB); 11522 // There is no need to emit line number for unconditional branch. 11523 (void)ApplyDebugLocation::CreateEmpty(CGF); 11524 CGF.EmitBlock(ExitBB, /*IsFinished=*/true); 11525 }; 11526 11527 if (CGM.getLangOpts().OpenMPSimd) { 11528 // Do not emit as a critical region as no parallel region could be emitted. 11529 RegionCodeGenTy ThenRCG(CodeGen); 11530 ThenRCG(CGF); 11531 } else { 11532 emitCriticalRegion(CGF, UniqueDeclName, CodeGen, FoundE->getExprLoc()); 11533 } 11534 } 11535 11536 void CGOpenMPRuntime::emitLastprivateConditionalFinalUpdate( 11537 CodeGenFunction &CGF, LValue PrivLVal, const VarDecl *VD, 11538 SourceLocation Loc) { 11539 if (CGF.getLangOpts().OpenMP < 50) 11540 return; 11541 auto It = LastprivateConditionalStack.back().DeclToUniqeName.find(VD); 11542 assert(It != LastprivateConditionalStack.back().DeclToUniqeName.end() && 11543 "Unknown lastprivate conditional variable."); 11544 StringRef UniqueName = It->getSecond(); 11545 llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(UniqueName); 11546 // The variable was not updated in the region - exit. 11547 if (!GV) 11548 return; 11549 LValue LPLVal = CGF.MakeAddrLValue( 11550 GV, PrivLVal.getType().getNonReferenceType(), PrivLVal.getAlignment()); 11551 llvm::Value *Res = CGF.EmitLoadOfScalar(LPLVal, Loc); 11552 CGF.EmitStoreOfScalar(Res, PrivLVal); 11553 } 11554 11555 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11556 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11557 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11558 llvm_unreachable("Not supported in SIMD-only mode"); 11559 } 11560 11561 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11562 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11563 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11564 llvm_unreachable("Not supported in SIMD-only mode"); 11565 } 11566 11567 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11568 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11569 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11570 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11571 bool Tied, unsigned &NumberOfParts) { 11572 llvm_unreachable("Not supported in SIMD-only mode"); 11573 } 11574 11575 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11576 SourceLocation Loc, 11577 llvm::Function *OutlinedFn, 11578 ArrayRef<llvm::Value *> CapturedVars, 11579 const Expr *IfCond) { 11580 llvm_unreachable("Not supported in SIMD-only mode"); 11581 } 11582 11583 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11584 CodeGenFunction &CGF, StringRef CriticalName, 11585 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11586 const Expr *Hint) { 11587 llvm_unreachable("Not supported in SIMD-only mode"); 11588 } 11589 11590 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11591 const RegionCodeGenTy &MasterOpGen, 11592 SourceLocation Loc) { 11593 llvm_unreachable("Not supported in SIMD-only mode"); 11594 } 11595 11596 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11597 SourceLocation Loc) { 11598 llvm_unreachable("Not supported in SIMD-only mode"); 11599 } 11600 11601 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11602 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11603 SourceLocation Loc) { 11604 llvm_unreachable("Not supported in SIMD-only mode"); 11605 } 11606 11607 void CGOpenMPSIMDRuntime::emitSingleRegion( 11608 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11609 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11610 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11611 ArrayRef<const Expr *> AssignmentOps) { 11612 llvm_unreachable("Not supported in SIMD-only mode"); 11613 } 11614 11615 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11616 const RegionCodeGenTy &OrderedOpGen, 11617 SourceLocation Loc, 11618 bool IsThreads) { 11619 llvm_unreachable("Not supported in SIMD-only mode"); 11620 } 11621 11622 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11623 SourceLocation Loc, 11624 OpenMPDirectiveKind Kind, 11625 bool EmitChecks, 11626 bool ForceSimpleCall) { 11627 llvm_unreachable("Not supported in SIMD-only mode"); 11628 } 11629 11630 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11631 CodeGenFunction &CGF, SourceLocation Loc, 11632 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11633 bool Ordered, const DispatchRTInput &DispatchValues) { 11634 llvm_unreachable("Not supported in SIMD-only mode"); 11635 } 11636 11637 void CGOpenMPSIMDRuntime::emitForStaticInit( 11638 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11639 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11640 llvm_unreachable("Not supported in SIMD-only mode"); 11641 } 11642 11643 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11644 CodeGenFunction &CGF, SourceLocation Loc, 11645 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11646 llvm_unreachable("Not supported in SIMD-only mode"); 11647 } 11648 11649 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11650 SourceLocation Loc, 11651 unsigned IVSize, 11652 bool IVSigned) { 11653 llvm_unreachable("Not supported in SIMD-only mode"); 11654 } 11655 11656 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11657 SourceLocation Loc, 11658 OpenMPDirectiveKind DKind) { 11659 llvm_unreachable("Not supported in SIMD-only mode"); 11660 } 11661 11662 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11663 SourceLocation Loc, 11664 unsigned IVSize, bool IVSigned, 11665 Address IL, Address LB, 11666 Address UB, Address ST) { 11667 llvm_unreachable("Not supported in SIMD-only mode"); 11668 } 11669 11670 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11671 llvm::Value *NumThreads, 11672 SourceLocation Loc) { 11673 llvm_unreachable("Not supported in SIMD-only mode"); 11674 } 11675 11676 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11677 ProcBindKind ProcBind, 11678 SourceLocation Loc) { 11679 llvm_unreachable("Not supported in SIMD-only mode"); 11680 } 11681 11682 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11683 const VarDecl *VD, 11684 Address VDAddr, 11685 SourceLocation Loc) { 11686 llvm_unreachable("Not supported in SIMD-only mode"); 11687 } 11688 11689 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11690 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11691 CodeGenFunction *CGF) { 11692 llvm_unreachable("Not supported in SIMD-only mode"); 11693 } 11694 11695 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11696 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11697 llvm_unreachable("Not supported in SIMD-only mode"); 11698 } 11699 11700 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11701 ArrayRef<const Expr *> Vars, 11702 SourceLocation Loc) { 11703 llvm_unreachable("Not supported in SIMD-only mode"); 11704 } 11705 11706 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11707 const OMPExecutableDirective &D, 11708 llvm::Function *TaskFunction, 11709 QualType SharedsTy, Address Shareds, 11710 const Expr *IfCond, 11711 const OMPTaskDataTy &Data) { 11712 llvm_unreachable("Not supported in SIMD-only mode"); 11713 } 11714 11715 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11716 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11717 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11718 const Expr *IfCond, const OMPTaskDataTy &Data) { 11719 llvm_unreachable("Not supported in SIMD-only mode"); 11720 } 11721 11722 void CGOpenMPSIMDRuntime::emitReduction( 11723 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11724 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11725 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11726 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11727 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 11728 ReductionOps, Options); 11729 } 11730 11731 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 11732 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 11733 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 11734 llvm_unreachable("Not supported in SIMD-only mode"); 11735 } 11736 11737 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 11738 SourceLocation Loc, 11739 ReductionCodeGen &RCG, 11740 unsigned N) { 11741 llvm_unreachable("Not supported in SIMD-only mode"); 11742 } 11743 11744 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 11745 SourceLocation Loc, 11746 llvm::Value *ReductionsPtr, 11747 LValue SharedLVal) { 11748 llvm_unreachable("Not supported in SIMD-only mode"); 11749 } 11750 11751 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 11752 SourceLocation Loc) { 11753 llvm_unreachable("Not supported in SIMD-only mode"); 11754 } 11755 11756 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 11757 CodeGenFunction &CGF, SourceLocation Loc, 11758 OpenMPDirectiveKind CancelRegion) { 11759 llvm_unreachable("Not supported in SIMD-only mode"); 11760 } 11761 11762 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 11763 SourceLocation Loc, const Expr *IfCond, 11764 OpenMPDirectiveKind CancelRegion) { 11765 llvm_unreachable("Not supported in SIMD-only mode"); 11766 } 11767 11768 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 11769 const OMPExecutableDirective &D, StringRef ParentName, 11770 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 11771 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 11772 llvm_unreachable("Not supported in SIMD-only mode"); 11773 } 11774 11775 void CGOpenMPSIMDRuntime::emitTargetCall( 11776 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11777 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 11778 const Expr *Device, 11779 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 11780 const OMPLoopDirective &D)> 11781 SizeEmitter) { 11782 llvm_unreachable("Not supported in SIMD-only mode"); 11783 } 11784 11785 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 11786 llvm_unreachable("Not supported in SIMD-only mode"); 11787 } 11788 11789 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 11790 llvm_unreachable("Not supported in SIMD-only mode"); 11791 } 11792 11793 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 11794 return false; 11795 } 11796 11797 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 11798 const OMPExecutableDirective &D, 11799 SourceLocation Loc, 11800 llvm::Function *OutlinedFn, 11801 ArrayRef<llvm::Value *> CapturedVars) { 11802 llvm_unreachable("Not supported in SIMD-only mode"); 11803 } 11804 11805 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11806 const Expr *NumTeams, 11807 const Expr *ThreadLimit, 11808 SourceLocation Loc) { 11809 llvm_unreachable("Not supported in SIMD-only mode"); 11810 } 11811 11812 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 11813 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11814 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11815 llvm_unreachable("Not supported in SIMD-only mode"); 11816 } 11817 11818 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 11819 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11820 const Expr *Device) { 11821 llvm_unreachable("Not supported in SIMD-only mode"); 11822 } 11823 11824 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11825 const OMPLoopDirective &D, 11826 ArrayRef<Expr *> NumIterations) { 11827 llvm_unreachable("Not supported in SIMD-only mode"); 11828 } 11829 11830 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11831 const OMPDependClause *C) { 11832 llvm_unreachable("Not supported in SIMD-only mode"); 11833 } 11834 11835 const VarDecl * 11836 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 11837 const VarDecl *NativeParam) const { 11838 llvm_unreachable("Not supported in SIMD-only mode"); 11839 } 11840 11841 Address 11842 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 11843 const VarDecl *NativeParam, 11844 const VarDecl *TargetParam) const { 11845 llvm_unreachable("Not supported in SIMD-only mode"); 11846 } 11847