1 //===----- CGOpenMPRuntime.cpp - Interface to OpenMP Runtimes -------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This provides a class for OpenMP runtime code generation. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "CGCXXABI.h" 14 #include "CGCleanup.h" 15 #include "CGOpenMPRuntime.h" 16 #include "CGRecordLayout.h" 17 #include "CodeGenFunction.h" 18 #include "clang/CodeGen/ConstantInitBuilder.h" 19 #include "clang/AST/Decl.h" 20 #include "clang/AST/StmtOpenMP.h" 21 #include "clang/Basic/BitmaskEnum.h" 22 #include "llvm/ADT/ArrayRef.h" 23 #include "llvm/Bitcode/BitcodeReader.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/IR/GlobalValue.h" 26 #include "llvm/IR/Value.h" 27 #include "llvm/Support/Format.h" 28 #include "llvm/Support/raw_ostream.h" 29 #include <cassert> 30 31 using namespace clang; 32 using namespace CodeGen; 33 34 namespace { 35 /// Base class for handling code generation inside OpenMP regions. 36 class CGOpenMPRegionInfo : public CodeGenFunction::CGCapturedStmtInfo { 37 public: 38 /// Kinds of OpenMP regions used in codegen. 39 enum CGOpenMPRegionKind { 40 /// Region with outlined function for standalone 'parallel' 41 /// directive. 42 ParallelOutlinedRegion, 43 /// Region with outlined function for standalone 'task' directive. 44 TaskOutlinedRegion, 45 /// Region for constructs that do not require function outlining, 46 /// like 'for', 'sections', 'atomic' etc. directives. 47 InlinedRegion, 48 /// Region with outlined function for standalone 'target' directive. 49 TargetRegion, 50 }; 51 52 CGOpenMPRegionInfo(const CapturedStmt &CS, 53 const CGOpenMPRegionKind RegionKind, 54 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 55 bool HasCancel) 56 : CGCapturedStmtInfo(CS, CR_OpenMP), RegionKind(RegionKind), 57 CodeGen(CodeGen), Kind(Kind), HasCancel(HasCancel) {} 58 59 CGOpenMPRegionInfo(const CGOpenMPRegionKind RegionKind, 60 const RegionCodeGenTy &CodeGen, OpenMPDirectiveKind Kind, 61 bool HasCancel) 62 : CGCapturedStmtInfo(CR_OpenMP), RegionKind(RegionKind), CodeGen(CodeGen), 63 Kind(Kind), HasCancel(HasCancel) {} 64 65 /// Get a variable or parameter for storing global thread id 66 /// inside OpenMP construct. 67 virtual const VarDecl *getThreadIDVariable() const = 0; 68 69 /// Emit the captured statement body. 70 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override; 71 72 /// Get an LValue for the current ThreadID variable. 73 /// \return LValue for thread id variable. This LValue always has type int32*. 74 virtual LValue getThreadIDVariableLValue(CodeGenFunction &CGF); 75 76 virtual void emitUntiedSwitch(CodeGenFunction & /*CGF*/) {} 77 78 CGOpenMPRegionKind getRegionKind() const { return RegionKind; } 79 80 OpenMPDirectiveKind getDirectiveKind() const { return Kind; } 81 82 bool hasCancel() const { return HasCancel; } 83 84 static bool classof(const CGCapturedStmtInfo *Info) { 85 return Info->getKind() == CR_OpenMP; 86 } 87 88 ~CGOpenMPRegionInfo() override = default; 89 90 protected: 91 CGOpenMPRegionKind RegionKind; 92 RegionCodeGenTy CodeGen; 93 OpenMPDirectiveKind Kind; 94 bool HasCancel; 95 }; 96 97 /// API for captured statement code generation in OpenMP constructs. 98 class CGOpenMPOutlinedRegionInfo final : public CGOpenMPRegionInfo { 99 public: 100 CGOpenMPOutlinedRegionInfo(const CapturedStmt &CS, const VarDecl *ThreadIDVar, 101 const RegionCodeGenTy &CodeGen, 102 OpenMPDirectiveKind Kind, bool HasCancel, 103 StringRef HelperName) 104 : CGOpenMPRegionInfo(CS, ParallelOutlinedRegion, CodeGen, Kind, 105 HasCancel), 106 ThreadIDVar(ThreadIDVar), HelperName(HelperName) { 107 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 108 } 109 110 /// Get a variable or parameter for storing global thread id 111 /// inside OpenMP construct. 112 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 113 114 /// Get the name of the capture helper. 115 StringRef getHelperName() const override { return HelperName; } 116 117 static bool classof(const CGCapturedStmtInfo *Info) { 118 return CGOpenMPRegionInfo::classof(Info) && 119 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 120 ParallelOutlinedRegion; 121 } 122 123 private: 124 /// A variable or parameter storing global thread id for OpenMP 125 /// constructs. 126 const VarDecl *ThreadIDVar; 127 StringRef HelperName; 128 }; 129 130 /// API for captured statement code generation in OpenMP constructs. 131 class CGOpenMPTaskOutlinedRegionInfo final : public CGOpenMPRegionInfo { 132 public: 133 class UntiedTaskActionTy final : public PrePostActionTy { 134 bool Untied; 135 const VarDecl *PartIDVar; 136 const RegionCodeGenTy UntiedCodeGen; 137 llvm::SwitchInst *UntiedSwitch = nullptr; 138 139 public: 140 UntiedTaskActionTy(bool Tied, const VarDecl *PartIDVar, 141 const RegionCodeGenTy &UntiedCodeGen) 142 : Untied(!Tied), PartIDVar(PartIDVar), UntiedCodeGen(UntiedCodeGen) {} 143 void Enter(CodeGenFunction &CGF) override { 144 if (Untied) { 145 // Emit task switching point. 146 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 147 CGF.GetAddrOfLocalVar(PartIDVar), 148 PartIDVar->getType()->castAs<PointerType>()); 149 llvm::Value *Res = 150 CGF.EmitLoadOfScalar(PartIdLVal, PartIDVar->getLocation()); 151 llvm::BasicBlock *DoneBB = CGF.createBasicBlock(".untied.done."); 152 UntiedSwitch = CGF.Builder.CreateSwitch(Res, DoneBB); 153 CGF.EmitBlock(DoneBB); 154 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 155 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 156 UntiedSwitch->addCase(CGF.Builder.getInt32(0), 157 CGF.Builder.GetInsertBlock()); 158 emitUntiedSwitch(CGF); 159 } 160 } 161 void emitUntiedSwitch(CodeGenFunction &CGF) const { 162 if (Untied) { 163 LValue PartIdLVal = CGF.EmitLoadOfPointerLValue( 164 CGF.GetAddrOfLocalVar(PartIDVar), 165 PartIDVar->getType()->castAs<PointerType>()); 166 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 167 PartIdLVal); 168 UntiedCodeGen(CGF); 169 CodeGenFunction::JumpDest CurPoint = 170 CGF.getJumpDestInCurrentScope(".untied.next."); 171 CGF.EmitBranchThroughCleanup(CGF.ReturnBlock); 172 CGF.EmitBlock(CGF.createBasicBlock(".untied.jmp.")); 173 UntiedSwitch->addCase(CGF.Builder.getInt32(UntiedSwitch->getNumCases()), 174 CGF.Builder.GetInsertBlock()); 175 CGF.EmitBranchThroughCleanup(CurPoint); 176 CGF.EmitBlock(CurPoint.getBlock()); 177 } 178 } 179 unsigned getNumberOfParts() const { return UntiedSwitch->getNumCases(); } 180 }; 181 CGOpenMPTaskOutlinedRegionInfo(const CapturedStmt &CS, 182 const VarDecl *ThreadIDVar, 183 const RegionCodeGenTy &CodeGen, 184 OpenMPDirectiveKind Kind, bool HasCancel, 185 const UntiedTaskActionTy &Action) 186 : CGOpenMPRegionInfo(CS, TaskOutlinedRegion, CodeGen, Kind, HasCancel), 187 ThreadIDVar(ThreadIDVar), Action(Action) { 188 assert(ThreadIDVar != nullptr && "No ThreadID in OpenMP region."); 189 } 190 191 /// Get a variable or parameter for storing global thread id 192 /// inside OpenMP construct. 193 const VarDecl *getThreadIDVariable() const override { return ThreadIDVar; } 194 195 /// Get an LValue for the current ThreadID variable. 196 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override; 197 198 /// Get the name of the capture helper. 199 StringRef getHelperName() const override { return ".omp_outlined."; } 200 201 void emitUntiedSwitch(CodeGenFunction &CGF) override { 202 Action.emitUntiedSwitch(CGF); 203 } 204 205 static bool classof(const CGCapturedStmtInfo *Info) { 206 return CGOpenMPRegionInfo::classof(Info) && 207 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == 208 TaskOutlinedRegion; 209 } 210 211 private: 212 /// A variable or parameter storing global thread id for OpenMP 213 /// constructs. 214 const VarDecl *ThreadIDVar; 215 /// Action for emitting code for untied tasks. 216 const UntiedTaskActionTy &Action; 217 }; 218 219 /// API for inlined captured statement code generation in OpenMP 220 /// constructs. 221 class CGOpenMPInlinedRegionInfo : public CGOpenMPRegionInfo { 222 public: 223 CGOpenMPInlinedRegionInfo(CodeGenFunction::CGCapturedStmtInfo *OldCSI, 224 const RegionCodeGenTy &CodeGen, 225 OpenMPDirectiveKind Kind, bool HasCancel) 226 : CGOpenMPRegionInfo(InlinedRegion, CodeGen, Kind, HasCancel), 227 OldCSI(OldCSI), 228 OuterRegionInfo(dyn_cast_or_null<CGOpenMPRegionInfo>(OldCSI)) {} 229 230 // Retrieve the value of the context parameter. 231 llvm::Value *getContextValue() const override { 232 if (OuterRegionInfo) 233 return OuterRegionInfo->getContextValue(); 234 llvm_unreachable("No context value for inlined OpenMP region"); 235 } 236 237 void setContextValue(llvm::Value *V) override { 238 if (OuterRegionInfo) { 239 OuterRegionInfo->setContextValue(V); 240 return; 241 } 242 llvm_unreachable("No context value for inlined OpenMP region"); 243 } 244 245 /// Lookup the captured field decl for a variable. 246 const FieldDecl *lookup(const VarDecl *VD) const override { 247 if (OuterRegionInfo) 248 return OuterRegionInfo->lookup(VD); 249 // If there is no outer outlined region,no need to lookup in a list of 250 // captured variables, we can use the original one. 251 return nullptr; 252 } 253 254 FieldDecl *getThisFieldDecl() const override { 255 if (OuterRegionInfo) 256 return OuterRegionInfo->getThisFieldDecl(); 257 return nullptr; 258 } 259 260 /// Get a variable or parameter for storing global thread id 261 /// inside OpenMP construct. 262 const VarDecl *getThreadIDVariable() const override { 263 if (OuterRegionInfo) 264 return OuterRegionInfo->getThreadIDVariable(); 265 return nullptr; 266 } 267 268 /// Get an LValue for the current ThreadID variable. 269 LValue getThreadIDVariableLValue(CodeGenFunction &CGF) override { 270 if (OuterRegionInfo) 271 return OuterRegionInfo->getThreadIDVariableLValue(CGF); 272 llvm_unreachable("No LValue for inlined OpenMP construct"); 273 } 274 275 /// Get the name of the capture helper. 276 StringRef getHelperName() const override { 277 if (auto *OuterRegionInfo = getOldCSI()) 278 return OuterRegionInfo->getHelperName(); 279 llvm_unreachable("No helper name for inlined OpenMP construct"); 280 } 281 282 void emitUntiedSwitch(CodeGenFunction &CGF) override { 283 if (OuterRegionInfo) 284 OuterRegionInfo->emitUntiedSwitch(CGF); 285 } 286 287 CodeGenFunction::CGCapturedStmtInfo *getOldCSI() const { return OldCSI; } 288 289 static bool classof(const CGCapturedStmtInfo *Info) { 290 return CGOpenMPRegionInfo::classof(Info) && 291 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == InlinedRegion; 292 } 293 294 ~CGOpenMPInlinedRegionInfo() override = default; 295 296 private: 297 /// CodeGen info about outer OpenMP region. 298 CodeGenFunction::CGCapturedStmtInfo *OldCSI; 299 CGOpenMPRegionInfo *OuterRegionInfo; 300 }; 301 302 /// API for captured statement code generation in OpenMP target 303 /// constructs. For this captures, implicit parameters are used instead of the 304 /// captured fields. The name of the target region has to be unique in a given 305 /// application so it is provided by the client, because only the client has 306 /// the information to generate that. 307 class CGOpenMPTargetRegionInfo final : public CGOpenMPRegionInfo { 308 public: 309 CGOpenMPTargetRegionInfo(const CapturedStmt &CS, 310 const RegionCodeGenTy &CodeGen, StringRef HelperName) 311 : CGOpenMPRegionInfo(CS, TargetRegion, CodeGen, OMPD_target, 312 /*HasCancel=*/false), 313 HelperName(HelperName) {} 314 315 /// This is unused for target regions because each starts executing 316 /// with a single thread. 317 const VarDecl *getThreadIDVariable() const override { return nullptr; } 318 319 /// Get the name of the capture helper. 320 StringRef getHelperName() const override { return HelperName; } 321 322 static bool classof(const CGCapturedStmtInfo *Info) { 323 return CGOpenMPRegionInfo::classof(Info) && 324 cast<CGOpenMPRegionInfo>(Info)->getRegionKind() == TargetRegion; 325 } 326 327 private: 328 StringRef HelperName; 329 }; 330 331 static void EmptyCodeGen(CodeGenFunction &, PrePostActionTy &) { 332 llvm_unreachable("No codegen for expressions"); 333 } 334 /// API for generation of expressions captured in a innermost OpenMP 335 /// region. 336 class CGOpenMPInnerExprInfo final : public CGOpenMPInlinedRegionInfo { 337 public: 338 CGOpenMPInnerExprInfo(CodeGenFunction &CGF, const CapturedStmt &CS) 339 : CGOpenMPInlinedRegionInfo(CGF.CapturedStmtInfo, EmptyCodeGen, 340 OMPD_unknown, 341 /*HasCancel=*/false), 342 PrivScope(CGF) { 343 // Make sure the globals captured in the provided statement are local by 344 // using the privatization logic. We assume the same variable is not 345 // captured more than once. 346 for (const auto &C : CS.captures()) { 347 if (!C.capturesVariable() && !C.capturesVariableByCopy()) 348 continue; 349 350 const VarDecl *VD = C.getCapturedVar(); 351 if (VD->isLocalVarDeclOrParm()) 352 continue; 353 354 DeclRefExpr DRE(CGF.getContext(), const_cast<VarDecl *>(VD), 355 /*RefersToEnclosingVariableOrCapture=*/false, 356 VD->getType().getNonReferenceType(), VK_LValue, 357 C.getLocation()); 358 PrivScope.addPrivate( 359 VD, [&CGF, &DRE]() { return CGF.EmitLValue(&DRE).getAddress(); }); 360 } 361 (void)PrivScope.Privatize(); 362 } 363 364 /// Lookup the captured field decl for a variable. 365 const FieldDecl *lookup(const VarDecl *VD) const override { 366 if (const FieldDecl *FD = CGOpenMPInlinedRegionInfo::lookup(VD)) 367 return FD; 368 return nullptr; 369 } 370 371 /// Emit the captured statement body. 372 void EmitBody(CodeGenFunction &CGF, const Stmt *S) override { 373 llvm_unreachable("No body for expressions"); 374 } 375 376 /// Get a variable or parameter for storing global thread id 377 /// inside OpenMP construct. 378 const VarDecl *getThreadIDVariable() const override { 379 llvm_unreachable("No thread id for expressions"); 380 } 381 382 /// Get the name of the capture helper. 383 StringRef getHelperName() const override { 384 llvm_unreachable("No helper name for expressions"); 385 } 386 387 static bool classof(const CGCapturedStmtInfo *Info) { return false; } 388 389 private: 390 /// Private scope to capture global variables. 391 CodeGenFunction::OMPPrivateScope PrivScope; 392 }; 393 394 /// RAII for emitting code of OpenMP constructs. 395 class InlinedOpenMPRegionRAII { 396 CodeGenFunction &CGF; 397 llvm::DenseMap<const VarDecl *, FieldDecl *> LambdaCaptureFields; 398 FieldDecl *LambdaThisCaptureField = nullptr; 399 const CodeGen::CGBlockInfo *BlockInfo = nullptr; 400 401 public: 402 /// Constructs region for combined constructs. 403 /// \param CodeGen Code generation sequence for combined directives. Includes 404 /// a list of functions used for code generation of implicitly inlined 405 /// regions. 406 InlinedOpenMPRegionRAII(CodeGenFunction &CGF, const RegionCodeGenTy &CodeGen, 407 OpenMPDirectiveKind Kind, bool HasCancel) 408 : CGF(CGF) { 409 // Start emission for the construct. 410 CGF.CapturedStmtInfo = new CGOpenMPInlinedRegionInfo( 411 CGF.CapturedStmtInfo, CodeGen, Kind, HasCancel); 412 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 413 LambdaThisCaptureField = CGF.LambdaThisCaptureField; 414 CGF.LambdaThisCaptureField = nullptr; 415 BlockInfo = CGF.BlockInfo; 416 CGF.BlockInfo = nullptr; 417 } 418 419 ~InlinedOpenMPRegionRAII() { 420 // Restore original CapturedStmtInfo only if we're done with code emission. 421 auto *OldCSI = 422 cast<CGOpenMPInlinedRegionInfo>(CGF.CapturedStmtInfo)->getOldCSI(); 423 delete CGF.CapturedStmtInfo; 424 CGF.CapturedStmtInfo = OldCSI; 425 std::swap(CGF.LambdaCaptureFields, LambdaCaptureFields); 426 CGF.LambdaThisCaptureField = LambdaThisCaptureField; 427 CGF.BlockInfo = BlockInfo; 428 } 429 }; 430 431 /// Values for bit flags used in the ident_t to describe the fields. 432 /// All enumeric elements are named and described in accordance with the code 433 /// from https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 434 enum OpenMPLocationFlags : unsigned { 435 /// Use trampoline for internal microtask. 436 OMP_IDENT_IMD = 0x01, 437 /// Use c-style ident structure. 438 OMP_IDENT_KMPC = 0x02, 439 /// Atomic reduction option for kmpc_reduce. 440 OMP_ATOMIC_REDUCE = 0x10, 441 /// Explicit 'barrier' directive. 442 OMP_IDENT_BARRIER_EXPL = 0x20, 443 /// Implicit barrier in code. 444 OMP_IDENT_BARRIER_IMPL = 0x40, 445 /// Implicit barrier in 'for' directive. 446 OMP_IDENT_BARRIER_IMPL_FOR = 0x40, 447 /// Implicit barrier in 'sections' directive. 448 OMP_IDENT_BARRIER_IMPL_SECTIONS = 0xC0, 449 /// Implicit barrier in 'single' directive. 450 OMP_IDENT_BARRIER_IMPL_SINGLE = 0x140, 451 /// Call of __kmp_for_static_init for static loop. 452 OMP_IDENT_WORK_LOOP = 0x200, 453 /// Call of __kmp_for_static_init for sections. 454 OMP_IDENT_WORK_SECTIONS = 0x400, 455 /// Call of __kmp_for_static_init for distribute. 456 OMP_IDENT_WORK_DISTRIBUTE = 0x800, 457 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_IDENT_WORK_DISTRIBUTE) 458 }; 459 460 namespace { 461 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 462 /// Values for bit flags for marking which requires clauses have been used. 463 enum OpenMPOffloadingRequiresDirFlags : int64_t { 464 /// flag undefined. 465 OMP_REQ_UNDEFINED = 0x000, 466 /// no requires clause present. 467 OMP_REQ_NONE = 0x001, 468 /// reverse_offload clause. 469 OMP_REQ_REVERSE_OFFLOAD = 0x002, 470 /// unified_address clause. 471 OMP_REQ_UNIFIED_ADDRESS = 0x004, 472 /// unified_shared_memory clause. 473 OMP_REQ_UNIFIED_SHARED_MEMORY = 0x008, 474 /// dynamic_allocators clause. 475 OMP_REQ_DYNAMIC_ALLOCATORS = 0x010, 476 LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/OMP_REQ_DYNAMIC_ALLOCATORS) 477 }; 478 479 enum OpenMPOffloadingReservedDeviceIDs { 480 /// Device ID if the device was not defined, runtime should get it 481 /// from environment variables in the spec. 482 OMP_DEVICEID_UNDEF = -1, 483 }; 484 } // anonymous namespace 485 486 /// Describes ident structure that describes a source location. 487 /// All descriptions are taken from 488 /// https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h 489 /// Original structure: 490 /// typedef struct ident { 491 /// kmp_int32 reserved_1; /**< might be used in Fortran; 492 /// see above */ 493 /// kmp_int32 flags; /**< also f.flags; KMP_IDENT_xxx flags; 494 /// KMP_IDENT_KMPC identifies this union 495 /// member */ 496 /// kmp_int32 reserved_2; /**< not really used in Fortran any more; 497 /// see above */ 498 ///#if USE_ITT_BUILD 499 /// /* but currently used for storing 500 /// region-specific ITT */ 501 /// /* contextual information. */ 502 ///#endif /* USE_ITT_BUILD */ 503 /// kmp_int32 reserved_3; /**< source[4] in Fortran, do not use for 504 /// C++ */ 505 /// char const *psource; /**< String describing the source location. 506 /// The string is composed of semi-colon separated 507 // fields which describe the source file, 508 /// the function and a pair of line numbers that 509 /// delimit the construct. 510 /// */ 511 /// } ident_t; 512 enum IdentFieldIndex { 513 /// might be used in Fortran 514 IdentField_Reserved_1, 515 /// OMP_IDENT_xxx flags; OMP_IDENT_KMPC identifies this union member. 516 IdentField_Flags, 517 /// Not really used in Fortran any more 518 IdentField_Reserved_2, 519 /// Source[4] in Fortran, do not use for C++ 520 IdentField_Reserved_3, 521 /// String describing the source location. The string is composed of 522 /// semi-colon separated fields which describe the source file, the function 523 /// and a pair of line numbers that delimit the construct. 524 IdentField_PSource 525 }; 526 527 /// Schedule types for 'omp for' loops (these enumerators are taken from 528 /// the enum sched_type in kmp.h). 529 enum OpenMPSchedType { 530 /// Lower bound for default (unordered) versions. 531 OMP_sch_lower = 32, 532 OMP_sch_static_chunked = 33, 533 OMP_sch_static = 34, 534 OMP_sch_dynamic_chunked = 35, 535 OMP_sch_guided_chunked = 36, 536 OMP_sch_runtime = 37, 537 OMP_sch_auto = 38, 538 /// static with chunk adjustment (e.g., simd) 539 OMP_sch_static_balanced_chunked = 45, 540 /// Lower bound for 'ordered' versions. 541 OMP_ord_lower = 64, 542 OMP_ord_static_chunked = 65, 543 OMP_ord_static = 66, 544 OMP_ord_dynamic_chunked = 67, 545 OMP_ord_guided_chunked = 68, 546 OMP_ord_runtime = 69, 547 OMP_ord_auto = 70, 548 OMP_sch_default = OMP_sch_static, 549 /// dist_schedule types 550 OMP_dist_sch_static_chunked = 91, 551 OMP_dist_sch_static = 92, 552 /// Support for OpenMP 4.5 monotonic and nonmonotonic schedule modifiers. 553 /// Set if the monotonic schedule modifier was present. 554 OMP_sch_modifier_monotonic = (1 << 29), 555 /// Set if the nonmonotonic schedule modifier was present. 556 OMP_sch_modifier_nonmonotonic = (1 << 30), 557 }; 558 559 enum OpenMPRTLFunction { 560 /// Call to void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, 561 /// kmpc_micro microtask, ...); 562 OMPRTL__kmpc_fork_call, 563 /// Call to void *__kmpc_threadprivate_cached(ident_t *loc, 564 /// kmp_int32 global_tid, void *data, size_t size, void ***cache); 565 OMPRTL__kmpc_threadprivate_cached, 566 /// Call to void __kmpc_threadprivate_register( ident_t *, 567 /// void *data, kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 568 OMPRTL__kmpc_threadprivate_register, 569 // Call to __kmpc_int32 kmpc_global_thread_num(ident_t *loc); 570 OMPRTL__kmpc_global_thread_num, 571 // Call to void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 572 // kmp_critical_name *crit); 573 OMPRTL__kmpc_critical, 574 // Call to void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 575 // global_tid, kmp_critical_name *crit, uintptr_t hint); 576 OMPRTL__kmpc_critical_with_hint, 577 // Call to void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 578 // kmp_critical_name *crit); 579 OMPRTL__kmpc_end_critical, 580 // Call to kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 581 // global_tid); 582 OMPRTL__kmpc_cancel_barrier, 583 // Call to void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 584 OMPRTL__kmpc_barrier, 585 // Call to void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 586 OMPRTL__kmpc_for_static_fini, 587 // Call to void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 588 // global_tid); 589 OMPRTL__kmpc_serialized_parallel, 590 // Call to void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 591 // global_tid); 592 OMPRTL__kmpc_end_serialized_parallel, 593 // Call to void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 594 // kmp_int32 num_threads); 595 OMPRTL__kmpc_push_num_threads, 596 // Call to void __kmpc_flush(ident_t *loc); 597 OMPRTL__kmpc_flush, 598 // Call to kmp_int32 __kmpc_master(ident_t *, kmp_int32 global_tid); 599 OMPRTL__kmpc_master, 600 // Call to void __kmpc_end_master(ident_t *, kmp_int32 global_tid); 601 OMPRTL__kmpc_end_master, 602 // Call to kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 603 // int end_part); 604 OMPRTL__kmpc_omp_taskyield, 605 // Call to kmp_int32 __kmpc_single(ident_t *, kmp_int32 global_tid); 606 OMPRTL__kmpc_single, 607 // Call to void __kmpc_end_single(ident_t *, kmp_int32 global_tid); 608 OMPRTL__kmpc_end_single, 609 // Call to kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 610 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 611 // kmp_routine_entry_t *task_entry); 612 OMPRTL__kmpc_omp_task_alloc, 613 // Call to kmp_task_t * __kmpc_omp_target_task_alloc(ident_t *, 614 // kmp_int32 gtid, kmp_int32 flags, size_t sizeof_kmp_task_t, 615 // size_t sizeof_shareds, kmp_routine_entry_t *task_entry, 616 // kmp_int64 device_id); 617 OMPRTL__kmpc_omp_target_task_alloc, 618 // Call to kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t * 619 // new_task); 620 OMPRTL__kmpc_omp_task, 621 // Call to void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 622 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 623 // kmp_int32 didit); 624 OMPRTL__kmpc_copyprivate, 625 // Call to kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 626 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 627 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 628 OMPRTL__kmpc_reduce, 629 // Call to kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 630 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 631 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 632 // *lck); 633 OMPRTL__kmpc_reduce_nowait, 634 // Call to void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 635 // kmp_critical_name *lck); 636 OMPRTL__kmpc_end_reduce, 637 // Call to void __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 638 // kmp_critical_name *lck); 639 OMPRTL__kmpc_end_reduce_nowait, 640 // Call to void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 641 // kmp_task_t * new_task); 642 OMPRTL__kmpc_omp_task_begin_if0, 643 // Call to void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 644 // kmp_task_t * new_task); 645 OMPRTL__kmpc_omp_task_complete_if0, 646 // Call to void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 647 OMPRTL__kmpc_ordered, 648 // Call to void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 649 OMPRTL__kmpc_end_ordered, 650 // Call to kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 651 // global_tid); 652 OMPRTL__kmpc_omp_taskwait, 653 // Call to void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 654 OMPRTL__kmpc_taskgroup, 655 // Call to void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 656 OMPRTL__kmpc_end_taskgroup, 657 // Call to void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 658 // int proc_bind); 659 OMPRTL__kmpc_push_proc_bind, 660 // Call to kmp_int32 __kmpc_omp_task_with_deps(ident_t *loc_ref, kmp_int32 661 // gtid, kmp_task_t * new_task, kmp_int32 ndeps, kmp_depend_info_t 662 // *dep_list, kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 663 OMPRTL__kmpc_omp_task_with_deps, 664 // Call to void __kmpc_omp_wait_deps(ident_t *loc_ref, kmp_int32 665 // gtid, kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 666 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 667 OMPRTL__kmpc_omp_wait_deps, 668 // Call to kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 669 // global_tid, kmp_int32 cncl_kind); 670 OMPRTL__kmpc_cancellationpoint, 671 // Call to kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 672 // kmp_int32 cncl_kind); 673 OMPRTL__kmpc_cancel, 674 // Call to void __kmpc_push_num_teams(ident_t *loc, kmp_int32 global_tid, 675 // kmp_int32 num_teams, kmp_int32 thread_limit); 676 OMPRTL__kmpc_push_num_teams, 677 // Call to void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 678 // microtask, ...); 679 OMPRTL__kmpc_fork_teams, 680 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 681 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 682 // sched, kmp_uint64 grainsize, void *task_dup); 683 OMPRTL__kmpc_taskloop, 684 // Call to void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 685 // num_dims, struct kmp_dim *dims); 686 OMPRTL__kmpc_doacross_init, 687 // Call to void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 688 OMPRTL__kmpc_doacross_fini, 689 // Call to void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 690 // *vec); 691 OMPRTL__kmpc_doacross_post, 692 // Call to void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 693 // *vec); 694 OMPRTL__kmpc_doacross_wait, 695 // Call to void *__kmpc_task_reduction_init(int gtid, int num_data, void 696 // *data); 697 OMPRTL__kmpc_task_reduction_init, 698 // Call to void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 699 // *d); 700 OMPRTL__kmpc_task_reduction_get_th_data, 701 // Call to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); 702 OMPRTL__kmpc_alloc, 703 // Call to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); 704 OMPRTL__kmpc_free, 705 706 // 707 // Offloading related calls 708 // 709 // Call to void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 710 // size); 711 OMPRTL__kmpc_push_target_tripcount, 712 // Call to int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 713 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 714 // *arg_types); 715 OMPRTL__tgt_target, 716 // Call to int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 717 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 718 // *arg_types); 719 OMPRTL__tgt_target_nowait, 720 // Call to int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 721 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 722 // *arg_types, int32_t num_teams, int32_t thread_limit); 723 OMPRTL__tgt_target_teams, 724 // Call to int32_t __tgt_target_teams_nowait(int64_t device_id, void 725 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 726 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 727 OMPRTL__tgt_target_teams_nowait, 728 // Call to void __tgt_register_requires(int64_t flags); 729 OMPRTL__tgt_register_requires, 730 // Call to void __tgt_register_lib(__tgt_bin_desc *desc); 731 OMPRTL__tgt_register_lib, 732 // Call to void __tgt_unregister_lib(__tgt_bin_desc *desc); 733 OMPRTL__tgt_unregister_lib, 734 // Call to void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 735 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 736 OMPRTL__tgt_target_data_begin, 737 // Call to void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 738 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 739 // *arg_types); 740 OMPRTL__tgt_target_data_begin_nowait, 741 // Call to void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 742 // void** args_base, void **args, size_t *arg_sizes, int64_t *arg_types); 743 OMPRTL__tgt_target_data_end, 744 // Call to void __tgt_target_data_end_nowait(int64_t device_id, int32_t 745 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 746 // *arg_types); 747 OMPRTL__tgt_target_data_end_nowait, 748 // Call to void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 749 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 750 OMPRTL__tgt_target_data_update, 751 // Call to void __tgt_target_data_update_nowait(int64_t device_id, int32_t 752 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 753 // *arg_types); 754 OMPRTL__tgt_target_data_update_nowait, 755 // Call to int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 756 OMPRTL__tgt_mapper_num_components, 757 // Call to void __tgt_push_mapper_component(void *rt_mapper_handle, void 758 // *base, void *begin, int64_t size, int64_t type); 759 OMPRTL__tgt_push_mapper_component, 760 }; 761 762 /// A basic class for pre|post-action for advanced codegen sequence for OpenMP 763 /// region. 764 class CleanupTy final : public EHScopeStack::Cleanup { 765 PrePostActionTy *Action; 766 767 public: 768 explicit CleanupTy(PrePostActionTy *Action) : Action(Action) {} 769 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 770 if (!CGF.HaveInsertPoint()) 771 return; 772 Action->Exit(CGF); 773 } 774 }; 775 776 } // anonymous namespace 777 778 void RegionCodeGenTy::operator()(CodeGenFunction &CGF) const { 779 CodeGenFunction::RunCleanupsScope Scope(CGF); 780 if (PrePostAction) { 781 CGF.EHStack.pushCleanup<CleanupTy>(NormalAndEHCleanup, PrePostAction); 782 Callback(CodeGen, CGF, *PrePostAction); 783 } else { 784 PrePostActionTy Action; 785 Callback(CodeGen, CGF, Action); 786 } 787 } 788 789 /// Check if the combiner is a call to UDR combiner and if it is so return the 790 /// UDR decl used for reduction. 791 static const OMPDeclareReductionDecl * 792 getReductionInit(const Expr *ReductionOp) { 793 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 794 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 795 if (const auto *DRE = 796 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 797 if (const auto *DRD = dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) 798 return DRD; 799 return nullptr; 800 } 801 802 static void emitInitWithReductionInitializer(CodeGenFunction &CGF, 803 const OMPDeclareReductionDecl *DRD, 804 const Expr *InitOp, 805 Address Private, Address Original, 806 QualType Ty) { 807 if (DRD->getInitializer()) { 808 std::pair<llvm::Function *, llvm::Function *> Reduction = 809 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 810 const auto *CE = cast<CallExpr>(InitOp); 811 const auto *OVE = cast<OpaqueValueExpr>(CE->getCallee()); 812 const Expr *LHS = CE->getArg(/*Arg=*/0)->IgnoreParenImpCasts(); 813 const Expr *RHS = CE->getArg(/*Arg=*/1)->IgnoreParenImpCasts(); 814 const auto *LHSDRE = 815 cast<DeclRefExpr>(cast<UnaryOperator>(LHS)->getSubExpr()); 816 const auto *RHSDRE = 817 cast<DeclRefExpr>(cast<UnaryOperator>(RHS)->getSubExpr()); 818 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 819 PrivateScope.addPrivate(cast<VarDecl>(LHSDRE->getDecl()), 820 [=]() { return Private; }); 821 PrivateScope.addPrivate(cast<VarDecl>(RHSDRE->getDecl()), 822 [=]() { return Original; }); 823 (void)PrivateScope.Privatize(); 824 RValue Func = RValue::get(Reduction.second); 825 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 826 CGF.EmitIgnoredExpr(InitOp); 827 } else { 828 llvm::Constant *Init = CGF.CGM.EmitNullConstant(Ty); 829 std::string Name = CGF.CGM.getOpenMPRuntime().getName({"init"}); 830 auto *GV = new llvm::GlobalVariable( 831 CGF.CGM.getModule(), Init->getType(), /*isConstant=*/true, 832 llvm::GlobalValue::PrivateLinkage, Init, Name); 833 LValue LV = CGF.MakeNaturalAlignAddrLValue(GV, Ty); 834 RValue InitRVal; 835 switch (CGF.getEvaluationKind(Ty)) { 836 case TEK_Scalar: 837 InitRVal = CGF.EmitLoadOfLValue(LV, DRD->getLocation()); 838 break; 839 case TEK_Complex: 840 InitRVal = 841 RValue::getComplex(CGF.EmitLoadOfComplex(LV, DRD->getLocation())); 842 break; 843 case TEK_Aggregate: 844 InitRVal = RValue::getAggregate(LV.getAddress()); 845 break; 846 } 847 OpaqueValueExpr OVE(DRD->getLocation(), Ty, VK_RValue); 848 CodeGenFunction::OpaqueValueMapping OpaqueMap(CGF, &OVE, InitRVal); 849 CGF.EmitAnyExprToMem(&OVE, Private, Ty.getQualifiers(), 850 /*IsInitializer=*/false); 851 } 852 } 853 854 /// Emit initialization of arrays of complex types. 855 /// \param DestAddr Address of the array. 856 /// \param Type Type of array. 857 /// \param Init Initial expression of array. 858 /// \param SrcAddr Address of the original array. 859 static void EmitOMPAggregateInit(CodeGenFunction &CGF, Address DestAddr, 860 QualType Type, bool EmitDeclareReductionInit, 861 const Expr *Init, 862 const OMPDeclareReductionDecl *DRD, 863 Address SrcAddr = Address::invalid()) { 864 // Perform element-by-element initialization. 865 QualType ElementTy; 866 867 // Drill down to the base element type on both arrays. 868 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 869 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, DestAddr); 870 DestAddr = 871 CGF.Builder.CreateElementBitCast(DestAddr, DestAddr.getElementType()); 872 if (DRD) 873 SrcAddr = 874 CGF.Builder.CreateElementBitCast(SrcAddr, DestAddr.getElementType()); 875 876 llvm::Value *SrcBegin = nullptr; 877 if (DRD) 878 SrcBegin = SrcAddr.getPointer(); 879 llvm::Value *DestBegin = DestAddr.getPointer(); 880 // Cast from pointer to array type to pointer to single element. 881 llvm::Value *DestEnd = CGF.Builder.CreateGEP(DestBegin, NumElements); 882 // The basic structure here is a while-do loop. 883 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arrayinit.body"); 884 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arrayinit.done"); 885 llvm::Value *IsEmpty = 886 CGF.Builder.CreateICmpEQ(DestBegin, DestEnd, "omp.arrayinit.isempty"); 887 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 888 889 // Enter the loop body, making that address the current address. 890 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 891 CGF.EmitBlock(BodyBB); 892 893 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 894 895 llvm::PHINode *SrcElementPHI = nullptr; 896 Address SrcElementCurrent = Address::invalid(); 897 if (DRD) { 898 SrcElementPHI = CGF.Builder.CreatePHI(SrcBegin->getType(), 2, 899 "omp.arraycpy.srcElementPast"); 900 SrcElementPHI->addIncoming(SrcBegin, EntryBB); 901 SrcElementCurrent = 902 Address(SrcElementPHI, 903 SrcAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 904 } 905 llvm::PHINode *DestElementPHI = CGF.Builder.CreatePHI( 906 DestBegin->getType(), 2, "omp.arraycpy.destElementPast"); 907 DestElementPHI->addIncoming(DestBegin, EntryBB); 908 Address DestElementCurrent = 909 Address(DestElementPHI, 910 DestAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 911 912 // Emit copy. 913 { 914 CodeGenFunction::RunCleanupsScope InitScope(CGF); 915 if (EmitDeclareReductionInit) { 916 emitInitWithReductionInitializer(CGF, DRD, Init, DestElementCurrent, 917 SrcElementCurrent, ElementTy); 918 } else 919 CGF.EmitAnyExprToMem(Init, DestElementCurrent, ElementTy.getQualifiers(), 920 /*IsInitializer=*/false); 921 } 922 923 if (DRD) { 924 // Shift the address forward by one element. 925 llvm::Value *SrcElementNext = CGF.Builder.CreateConstGEP1_32( 926 SrcElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 927 SrcElementPHI->addIncoming(SrcElementNext, CGF.Builder.GetInsertBlock()); 928 } 929 930 // Shift the address forward by one element. 931 llvm::Value *DestElementNext = CGF.Builder.CreateConstGEP1_32( 932 DestElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 933 // Check whether we've reached the end. 934 llvm::Value *Done = 935 CGF.Builder.CreateICmpEQ(DestElementNext, DestEnd, "omp.arraycpy.done"); 936 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 937 DestElementPHI->addIncoming(DestElementNext, CGF.Builder.GetInsertBlock()); 938 939 // Done. 940 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 941 } 942 943 LValue ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, const Expr *E) { 944 return CGF.EmitOMPSharedLValue(E); 945 } 946 947 LValue ReductionCodeGen::emitSharedLValueUB(CodeGenFunction &CGF, 948 const Expr *E) { 949 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(E)) 950 return CGF.EmitOMPArraySectionExpr(OASE, /*IsLowerBound=*/false); 951 return LValue(); 952 } 953 954 void ReductionCodeGen::emitAggregateInitialization( 955 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 956 const OMPDeclareReductionDecl *DRD) { 957 // Emit VarDecl with copy init for arrays. 958 // Get the address of the original variable captured in current 959 // captured region. 960 const auto *PrivateVD = 961 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 962 bool EmitDeclareReductionInit = 963 DRD && (DRD->getInitializer() || !PrivateVD->hasInit()); 964 EmitOMPAggregateInit(CGF, PrivateAddr, PrivateVD->getType(), 965 EmitDeclareReductionInit, 966 EmitDeclareReductionInit ? ClausesData[N].ReductionOp 967 : PrivateVD->getInit(), 968 DRD, SharedLVal.getAddress()); 969 } 970 971 ReductionCodeGen::ReductionCodeGen(ArrayRef<const Expr *> Shareds, 972 ArrayRef<const Expr *> Privates, 973 ArrayRef<const Expr *> ReductionOps) { 974 ClausesData.reserve(Shareds.size()); 975 SharedAddresses.reserve(Shareds.size()); 976 Sizes.reserve(Shareds.size()); 977 BaseDecls.reserve(Shareds.size()); 978 auto IPriv = Privates.begin(); 979 auto IRed = ReductionOps.begin(); 980 for (const Expr *Ref : Shareds) { 981 ClausesData.emplace_back(Ref, *IPriv, *IRed); 982 std::advance(IPriv, 1); 983 std::advance(IRed, 1); 984 } 985 } 986 987 void ReductionCodeGen::emitSharedLValue(CodeGenFunction &CGF, unsigned N) { 988 assert(SharedAddresses.size() == N && 989 "Number of generated lvalues must be exactly N."); 990 LValue First = emitSharedLValue(CGF, ClausesData[N].Ref); 991 LValue Second = emitSharedLValueUB(CGF, ClausesData[N].Ref); 992 SharedAddresses.emplace_back(First, Second); 993 } 994 995 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N) { 996 const auto *PrivateVD = 997 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 998 QualType PrivateType = PrivateVD->getType(); 999 bool AsArraySection = isa<OMPArraySectionExpr>(ClausesData[N].Ref); 1000 if (!PrivateType->isVariablyModifiedType()) { 1001 Sizes.emplace_back( 1002 CGF.getTypeSize( 1003 SharedAddresses[N].first.getType().getNonReferenceType()), 1004 nullptr); 1005 return; 1006 } 1007 llvm::Value *Size; 1008 llvm::Value *SizeInChars; 1009 auto *ElemType = 1010 cast<llvm::PointerType>(SharedAddresses[N].first.getPointer()->getType()) 1011 ->getElementType(); 1012 auto *ElemSizeOf = llvm::ConstantExpr::getSizeOf(ElemType); 1013 if (AsArraySection) { 1014 Size = CGF.Builder.CreatePtrDiff(SharedAddresses[N].second.getPointer(), 1015 SharedAddresses[N].first.getPointer()); 1016 Size = CGF.Builder.CreateNUWAdd( 1017 Size, llvm::ConstantInt::get(Size->getType(), /*V=*/1)); 1018 SizeInChars = CGF.Builder.CreateNUWMul(Size, ElemSizeOf); 1019 } else { 1020 SizeInChars = CGF.getTypeSize( 1021 SharedAddresses[N].first.getType().getNonReferenceType()); 1022 Size = CGF.Builder.CreateExactUDiv(SizeInChars, ElemSizeOf); 1023 } 1024 Sizes.emplace_back(SizeInChars, Size); 1025 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1026 CGF, 1027 cast<OpaqueValueExpr>( 1028 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1029 RValue::get(Size)); 1030 CGF.EmitVariablyModifiedType(PrivateType); 1031 } 1032 1033 void ReductionCodeGen::emitAggregateType(CodeGenFunction &CGF, unsigned N, 1034 llvm::Value *Size) { 1035 const auto *PrivateVD = 1036 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1037 QualType PrivateType = PrivateVD->getType(); 1038 if (!PrivateType->isVariablyModifiedType()) { 1039 assert(!Size && !Sizes[N].second && 1040 "Size should be nullptr for non-variably modified reduction " 1041 "items."); 1042 return; 1043 } 1044 CodeGenFunction::OpaqueValueMapping OpaqueMap( 1045 CGF, 1046 cast<OpaqueValueExpr>( 1047 CGF.getContext().getAsVariableArrayType(PrivateType)->getSizeExpr()), 1048 RValue::get(Size)); 1049 CGF.EmitVariablyModifiedType(PrivateType); 1050 } 1051 1052 void ReductionCodeGen::emitInitialization( 1053 CodeGenFunction &CGF, unsigned N, Address PrivateAddr, LValue SharedLVal, 1054 llvm::function_ref<bool(CodeGenFunction &)> DefaultInit) { 1055 assert(SharedAddresses.size() > N && "No variable was generated"); 1056 const auto *PrivateVD = 1057 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1058 const OMPDeclareReductionDecl *DRD = 1059 getReductionInit(ClausesData[N].ReductionOp); 1060 QualType PrivateType = PrivateVD->getType(); 1061 PrivateAddr = CGF.Builder.CreateElementBitCast( 1062 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1063 QualType SharedType = SharedAddresses[N].first.getType(); 1064 SharedLVal = CGF.MakeAddrLValue( 1065 CGF.Builder.CreateElementBitCast(SharedLVal.getAddress(), 1066 CGF.ConvertTypeForMem(SharedType)), 1067 SharedType, SharedAddresses[N].first.getBaseInfo(), 1068 CGF.CGM.getTBAAInfoForSubobject(SharedAddresses[N].first, SharedType)); 1069 if (CGF.getContext().getAsArrayType(PrivateVD->getType())) { 1070 emitAggregateInitialization(CGF, N, PrivateAddr, SharedLVal, DRD); 1071 } else if (DRD && (DRD->getInitializer() || !PrivateVD->hasInit())) { 1072 emitInitWithReductionInitializer(CGF, DRD, ClausesData[N].ReductionOp, 1073 PrivateAddr, SharedLVal.getAddress(), 1074 SharedLVal.getType()); 1075 } else if (!DefaultInit(CGF) && PrivateVD->hasInit() && 1076 !CGF.isTrivialInitializer(PrivateVD->getInit())) { 1077 CGF.EmitAnyExprToMem(PrivateVD->getInit(), PrivateAddr, 1078 PrivateVD->getType().getQualifiers(), 1079 /*IsInitializer=*/false); 1080 } 1081 } 1082 1083 bool ReductionCodeGen::needCleanups(unsigned N) { 1084 const auto *PrivateVD = 1085 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1086 QualType PrivateType = PrivateVD->getType(); 1087 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1088 return DTorKind != QualType::DK_none; 1089 } 1090 1091 void ReductionCodeGen::emitCleanups(CodeGenFunction &CGF, unsigned N, 1092 Address PrivateAddr) { 1093 const auto *PrivateVD = 1094 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Private)->getDecl()); 1095 QualType PrivateType = PrivateVD->getType(); 1096 QualType::DestructionKind DTorKind = PrivateType.isDestructedType(); 1097 if (needCleanups(N)) { 1098 PrivateAddr = CGF.Builder.CreateElementBitCast( 1099 PrivateAddr, CGF.ConvertTypeForMem(PrivateType)); 1100 CGF.pushDestroy(DTorKind, PrivateAddr, PrivateType); 1101 } 1102 } 1103 1104 static LValue loadToBegin(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1105 LValue BaseLV) { 1106 BaseTy = BaseTy.getNonReferenceType(); 1107 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1108 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1109 if (const auto *PtrTy = BaseTy->getAs<PointerType>()) { 1110 BaseLV = CGF.EmitLoadOfPointerLValue(BaseLV.getAddress(), PtrTy); 1111 } else { 1112 LValue RefLVal = CGF.MakeAddrLValue(BaseLV.getAddress(), BaseTy); 1113 BaseLV = CGF.EmitLoadOfReferenceLValue(RefLVal); 1114 } 1115 BaseTy = BaseTy->getPointeeType(); 1116 } 1117 return CGF.MakeAddrLValue( 1118 CGF.Builder.CreateElementBitCast(BaseLV.getAddress(), 1119 CGF.ConvertTypeForMem(ElTy)), 1120 BaseLV.getType(), BaseLV.getBaseInfo(), 1121 CGF.CGM.getTBAAInfoForSubobject(BaseLV, BaseLV.getType())); 1122 } 1123 1124 static Address castToBase(CodeGenFunction &CGF, QualType BaseTy, QualType ElTy, 1125 llvm::Type *BaseLVType, CharUnits BaseLVAlignment, 1126 llvm::Value *Addr) { 1127 Address Tmp = Address::invalid(); 1128 Address TopTmp = Address::invalid(); 1129 Address MostTopTmp = Address::invalid(); 1130 BaseTy = BaseTy.getNonReferenceType(); 1131 while ((BaseTy->isPointerType() || BaseTy->isReferenceType()) && 1132 !CGF.getContext().hasSameType(BaseTy, ElTy)) { 1133 Tmp = CGF.CreateMemTemp(BaseTy); 1134 if (TopTmp.isValid()) 1135 CGF.Builder.CreateStore(Tmp.getPointer(), TopTmp); 1136 else 1137 MostTopTmp = Tmp; 1138 TopTmp = Tmp; 1139 BaseTy = BaseTy->getPointeeType(); 1140 } 1141 llvm::Type *Ty = BaseLVType; 1142 if (Tmp.isValid()) 1143 Ty = Tmp.getElementType(); 1144 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Addr, Ty); 1145 if (Tmp.isValid()) { 1146 CGF.Builder.CreateStore(Addr, Tmp); 1147 return MostTopTmp; 1148 } 1149 return Address(Addr, BaseLVAlignment); 1150 } 1151 1152 static const VarDecl *getBaseDecl(const Expr *Ref, const DeclRefExpr *&DE) { 1153 const VarDecl *OrigVD = nullptr; 1154 if (const auto *OASE = dyn_cast<OMPArraySectionExpr>(Ref)) { 1155 const Expr *Base = OASE->getBase()->IgnoreParenImpCasts(); 1156 while (const auto *TempOASE = dyn_cast<OMPArraySectionExpr>(Base)) 1157 Base = TempOASE->getBase()->IgnoreParenImpCasts(); 1158 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1159 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1160 DE = cast<DeclRefExpr>(Base); 1161 OrigVD = cast<VarDecl>(DE->getDecl()); 1162 } else if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Ref)) { 1163 const Expr *Base = ASE->getBase()->IgnoreParenImpCasts(); 1164 while (const auto *TempASE = dyn_cast<ArraySubscriptExpr>(Base)) 1165 Base = TempASE->getBase()->IgnoreParenImpCasts(); 1166 DE = cast<DeclRefExpr>(Base); 1167 OrigVD = cast<VarDecl>(DE->getDecl()); 1168 } 1169 return OrigVD; 1170 } 1171 1172 Address ReductionCodeGen::adjustPrivateAddress(CodeGenFunction &CGF, unsigned N, 1173 Address PrivateAddr) { 1174 const DeclRefExpr *DE; 1175 if (const VarDecl *OrigVD = ::getBaseDecl(ClausesData[N].Ref, DE)) { 1176 BaseDecls.emplace_back(OrigVD); 1177 LValue OriginalBaseLValue = CGF.EmitLValue(DE); 1178 LValue BaseLValue = 1179 loadToBegin(CGF, OrigVD->getType(), SharedAddresses[N].first.getType(), 1180 OriginalBaseLValue); 1181 llvm::Value *Adjustment = CGF.Builder.CreatePtrDiff( 1182 BaseLValue.getPointer(), SharedAddresses[N].first.getPointer()); 1183 llvm::Value *PrivatePointer = 1184 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 1185 PrivateAddr.getPointer(), 1186 SharedAddresses[N].first.getAddress().getType()); 1187 llvm::Value *Ptr = CGF.Builder.CreateGEP(PrivatePointer, Adjustment); 1188 return castToBase(CGF, OrigVD->getType(), 1189 SharedAddresses[N].first.getType(), 1190 OriginalBaseLValue.getAddress().getType(), 1191 OriginalBaseLValue.getAlignment(), Ptr); 1192 } 1193 BaseDecls.emplace_back( 1194 cast<VarDecl>(cast<DeclRefExpr>(ClausesData[N].Ref)->getDecl())); 1195 return PrivateAddr; 1196 } 1197 1198 bool ReductionCodeGen::usesReductionInitializer(unsigned N) const { 1199 const OMPDeclareReductionDecl *DRD = 1200 getReductionInit(ClausesData[N].ReductionOp); 1201 return DRD && DRD->getInitializer(); 1202 } 1203 1204 LValue CGOpenMPRegionInfo::getThreadIDVariableLValue(CodeGenFunction &CGF) { 1205 return CGF.EmitLoadOfPointerLValue( 1206 CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1207 getThreadIDVariable()->getType()->castAs<PointerType>()); 1208 } 1209 1210 void CGOpenMPRegionInfo::EmitBody(CodeGenFunction &CGF, const Stmt * /*S*/) { 1211 if (!CGF.HaveInsertPoint()) 1212 return; 1213 // 1.2.2 OpenMP Language Terminology 1214 // Structured block - An executable statement with a single entry at the 1215 // top and a single exit at the bottom. 1216 // The point of exit cannot be a branch out of the structured block. 1217 // longjmp() and throw() must not violate the entry/exit criteria. 1218 CGF.EHStack.pushTerminate(); 1219 CodeGen(CGF); 1220 CGF.EHStack.popTerminate(); 1221 } 1222 1223 LValue CGOpenMPTaskOutlinedRegionInfo::getThreadIDVariableLValue( 1224 CodeGenFunction &CGF) { 1225 return CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(getThreadIDVariable()), 1226 getThreadIDVariable()->getType(), 1227 AlignmentSource::Decl); 1228 } 1229 1230 static FieldDecl *addFieldToRecordDecl(ASTContext &C, DeclContext *DC, 1231 QualType FieldTy) { 1232 auto *Field = FieldDecl::Create( 1233 C, DC, SourceLocation(), SourceLocation(), /*Id=*/nullptr, FieldTy, 1234 C.getTrivialTypeSourceInfo(FieldTy, SourceLocation()), 1235 /*BW=*/nullptr, /*Mutable=*/false, /*InitStyle=*/ICIS_NoInit); 1236 Field->setAccess(AS_public); 1237 DC->addDecl(Field); 1238 return Field; 1239 } 1240 1241 CGOpenMPRuntime::CGOpenMPRuntime(CodeGenModule &CGM, StringRef FirstSeparator, 1242 StringRef Separator) 1243 : CGM(CGM), FirstSeparator(FirstSeparator), Separator(Separator), 1244 OffloadEntriesInfoManager(CGM) { 1245 ASTContext &C = CGM.getContext(); 1246 RecordDecl *RD = C.buildImplicitRecord("ident_t"); 1247 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 1248 RD->startDefinition(); 1249 // reserved_1 1250 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1251 // flags 1252 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1253 // reserved_2 1254 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1255 // reserved_3 1256 addFieldToRecordDecl(C, RD, KmpInt32Ty); 1257 // psource 1258 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 1259 RD->completeDefinition(); 1260 IdentQTy = C.getRecordType(RD); 1261 IdentTy = CGM.getTypes().ConvertRecordDeclType(RD); 1262 KmpCriticalNameTy = llvm::ArrayType::get(CGM.Int32Ty, /*NumElements*/ 8); 1263 1264 loadOffloadInfoMetadata(); 1265 } 1266 1267 bool CGOpenMPRuntime::tryEmitDeclareVariant(const GlobalDecl &NewGD, 1268 const GlobalDecl &OldGD, 1269 llvm::GlobalValue *OrigAddr, 1270 bool IsForDefinition) { 1271 // Emit at least a definition for the aliasee if the the address of the 1272 // original function is requested. 1273 if (IsForDefinition || OrigAddr) 1274 (void)CGM.GetAddrOfGlobal(NewGD); 1275 StringRef NewMangledName = CGM.getMangledName(NewGD); 1276 llvm::GlobalValue *Addr = CGM.GetGlobalValue(NewMangledName); 1277 if (Addr && !Addr->isDeclaration()) { 1278 const auto *D = cast<FunctionDecl>(OldGD.getDecl()); 1279 const CGFunctionInfo &FI = CGM.getTypes().arrangeGlobalDeclaration(OldGD); 1280 llvm::Type *DeclTy = CGM.getTypes().GetFunctionType(FI); 1281 1282 // Create a reference to the named value. This ensures that it is emitted 1283 // if a deferred decl. 1284 llvm::GlobalValue::LinkageTypes LT = CGM.getFunctionLinkage(OldGD); 1285 1286 // Create the new alias itself, but don't set a name yet. 1287 auto *GA = 1288 llvm::GlobalAlias::create(DeclTy, 0, LT, "", Addr, &CGM.getModule()); 1289 1290 if (OrigAddr) { 1291 assert(OrigAddr->isDeclaration() && "Expected declaration"); 1292 1293 GA->takeName(OrigAddr); 1294 OrigAddr->replaceAllUsesWith( 1295 llvm::ConstantExpr::getBitCast(GA, OrigAddr->getType())); 1296 OrigAddr->eraseFromParent(); 1297 } else { 1298 GA->setName(CGM.getMangledName(OldGD)); 1299 } 1300 1301 // Set attributes which are particular to an alias; this is a 1302 // specialization of the attributes which may be set on a global function. 1303 if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakRefAttr>() || 1304 D->isWeakImported()) 1305 GA->setLinkage(llvm::Function::WeakAnyLinkage); 1306 1307 CGM.SetCommonAttributes(OldGD, GA); 1308 return true; 1309 } 1310 return false; 1311 } 1312 1313 void CGOpenMPRuntime::clear() { 1314 InternalVars.clear(); 1315 // Clean non-target variable declarations possibly used only in debug info. 1316 for (const auto &Data : EmittedNonTargetVariables) { 1317 if (!Data.getValue().pointsToAliveValue()) 1318 continue; 1319 auto *GV = dyn_cast<llvm::GlobalVariable>(Data.getValue()); 1320 if (!GV) 1321 continue; 1322 if (!GV->isDeclaration() || GV->getNumUses() > 0) 1323 continue; 1324 GV->eraseFromParent(); 1325 } 1326 // Emit aliases for the deferred aliasees. 1327 for (const auto &Pair : DeferredVariantFunction) { 1328 StringRef MangledName = CGM.getMangledName(Pair.second.second); 1329 llvm::GlobalValue *Addr = CGM.GetGlobalValue(MangledName); 1330 // If not able to emit alias, just emit original declaration. 1331 (void)tryEmitDeclareVariant(Pair.second.first, Pair.second.second, Addr, 1332 /*IsForDefinition=*/false); 1333 } 1334 } 1335 1336 std::string CGOpenMPRuntime::getName(ArrayRef<StringRef> Parts) const { 1337 SmallString<128> Buffer; 1338 llvm::raw_svector_ostream OS(Buffer); 1339 StringRef Sep = FirstSeparator; 1340 for (StringRef Part : Parts) { 1341 OS << Sep << Part; 1342 Sep = Separator; 1343 } 1344 return OS.str(); 1345 } 1346 1347 static llvm::Function * 1348 emitCombinerOrInitializer(CodeGenModule &CGM, QualType Ty, 1349 const Expr *CombinerInitializer, const VarDecl *In, 1350 const VarDecl *Out, bool IsCombiner) { 1351 // void .omp_combiner.(Ty *in, Ty *out); 1352 ASTContext &C = CGM.getContext(); 1353 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 1354 FunctionArgList Args; 1355 ImplicitParamDecl OmpOutParm(C, /*DC=*/nullptr, Out->getLocation(), 1356 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1357 ImplicitParamDecl OmpInParm(C, /*DC=*/nullptr, In->getLocation(), 1358 /*Id=*/nullptr, PtrTy, ImplicitParamDecl::Other); 1359 Args.push_back(&OmpOutParm); 1360 Args.push_back(&OmpInParm); 1361 const CGFunctionInfo &FnInfo = 1362 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 1363 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 1364 std::string Name = CGM.getOpenMPRuntime().getName( 1365 {IsCombiner ? "omp_combiner" : "omp_initializer", ""}); 1366 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 1367 Name, &CGM.getModule()); 1368 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 1369 if (CGM.getLangOpts().Optimize) { 1370 Fn->removeFnAttr(llvm::Attribute::NoInline); 1371 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 1372 Fn->addFnAttr(llvm::Attribute::AlwaysInline); 1373 } 1374 CodeGenFunction CGF(CGM); 1375 // Map "T omp_in;" variable to "*omp_in_parm" value in all expressions. 1376 // Map "T omp_out;" variable to "*omp_out_parm" value in all expressions. 1377 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, In->getLocation(), 1378 Out->getLocation()); 1379 CodeGenFunction::OMPPrivateScope Scope(CGF); 1380 Address AddrIn = CGF.GetAddrOfLocalVar(&OmpInParm); 1381 Scope.addPrivate(In, [&CGF, AddrIn, PtrTy]() { 1382 return CGF.EmitLoadOfPointerLValue(AddrIn, PtrTy->castAs<PointerType>()) 1383 .getAddress(); 1384 }); 1385 Address AddrOut = CGF.GetAddrOfLocalVar(&OmpOutParm); 1386 Scope.addPrivate(Out, [&CGF, AddrOut, PtrTy]() { 1387 return CGF.EmitLoadOfPointerLValue(AddrOut, PtrTy->castAs<PointerType>()) 1388 .getAddress(); 1389 }); 1390 (void)Scope.Privatize(); 1391 if (!IsCombiner && Out->hasInit() && 1392 !CGF.isTrivialInitializer(Out->getInit())) { 1393 CGF.EmitAnyExprToMem(Out->getInit(), CGF.GetAddrOfLocalVar(Out), 1394 Out->getType().getQualifiers(), 1395 /*IsInitializer=*/true); 1396 } 1397 if (CombinerInitializer) 1398 CGF.EmitIgnoredExpr(CombinerInitializer); 1399 Scope.ForceCleanup(); 1400 CGF.FinishFunction(); 1401 return Fn; 1402 } 1403 1404 void CGOpenMPRuntime::emitUserDefinedReduction( 1405 CodeGenFunction *CGF, const OMPDeclareReductionDecl *D) { 1406 if (UDRMap.count(D) > 0) 1407 return; 1408 llvm::Function *Combiner = emitCombinerOrInitializer( 1409 CGM, D->getType(), D->getCombiner(), 1410 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerIn())->getDecl()), 1411 cast<VarDecl>(cast<DeclRefExpr>(D->getCombinerOut())->getDecl()), 1412 /*IsCombiner=*/true); 1413 llvm::Function *Initializer = nullptr; 1414 if (const Expr *Init = D->getInitializer()) { 1415 Initializer = emitCombinerOrInitializer( 1416 CGM, D->getType(), 1417 D->getInitializerKind() == OMPDeclareReductionDecl::CallInit ? Init 1418 : nullptr, 1419 cast<VarDecl>(cast<DeclRefExpr>(D->getInitOrig())->getDecl()), 1420 cast<VarDecl>(cast<DeclRefExpr>(D->getInitPriv())->getDecl()), 1421 /*IsCombiner=*/false); 1422 } 1423 UDRMap.try_emplace(D, Combiner, Initializer); 1424 if (CGF) { 1425 auto &Decls = FunctionUDRMap.FindAndConstruct(CGF->CurFn); 1426 Decls.second.push_back(D); 1427 } 1428 } 1429 1430 std::pair<llvm::Function *, llvm::Function *> 1431 CGOpenMPRuntime::getUserDefinedReduction(const OMPDeclareReductionDecl *D) { 1432 auto I = UDRMap.find(D); 1433 if (I != UDRMap.end()) 1434 return I->second; 1435 emitUserDefinedReduction(/*CGF=*/nullptr, D); 1436 return UDRMap.lookup(D); 1437 } 1438 1439 static llvm::Function *emitParallelOrTeamsOutlinedFunction( 1440 CodeGenModule &CGM, const OMPExecutableDirective &D, const CapturedStmt *CS, 1441 const VarDecl *ThreadIDVar, OpenMPDirectiveKind InnermostKind, 1442 const StringRef OutlinedHelperName, const RegionCodeGenTy &CodeGen) { 1443 assert(ThreadIDVar->getType()->isPointerType() && 1444 "thread id variable must be of type kmp_int32 *"); 1445 CodeGenFunction CGF(CGM, true); 1446 bool HasCancel = false; 1447 if (const auto *OPD = dyn_cast<OMPParallelDirective>(&D)) 1448 HasCancel = OPD->hasCancel(); 1449 else if (const auto *OPSD = dyn_cast<OMPParallelSectionsDirective>(&D)) 1450 HasCancel = OPSD->hasCancel(); 1451 else if (const auto *OPFD = dyn_cast<OMPParallelForDirective>(&D)) 1452 HasCancel = OPFD->hasCancel(); 1453 else if (const auto *OPFD = dyn_cast<OMPTargetParallelForDirective>(&D)) 1454 HasCancel = OPFD->hasCancel(); 1455 else if (const auto *OPFD = dyn_cast<OMPDistributeParallelForDirective>(&D)) 1456 HasCancel = OPFD->hasCancel(); 1457 else if (const auto *OPFD = 1458 dyn_cast<OMPTeamsDistributeParallelForDirective>(&D)) 1459 HasCancel = OPFD->hasCancel(); 1460 else if (const auto *OPFD = 1461 dyn_cast<OMPTargetTeamsDistributeParallelForDirective>(&D)) 1462 HasCancel = OPFD->hasCancel(); 1463 CGOpenMPOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, InnermostKind, 1464 HasCancel, OutlinedHelperName); 1465 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1466 return CGF.GenerateOpenMPCapturedStmtFunction(*CS); 1467 } 1468 1469 llvm::Function *CGOpenMPRuntime::emitParallelOutlinedFunction( 1470 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1471 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1472 const CapturedStmt *CS = D.getCapturedStmt(OMPD_parallel); 1473 return emitParallelOrTeamsOutlinedFunction( 1474 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1475 } 1476 1477 llvm::Function *CGOpenMPRuntime::emitTeamsOutlinedFunction( 1478 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1479 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 1480 const CapturedStmt *CS = D.getCapturedStmt(OMPD_teams); 1481 return emitParallelOrTeamsOutlinedFunction( 1482 CGM, D, CS, ThreadIDVar, InnermostKind, getOutlinedHelperName(), CodeGen); 1483 } 1484 1485 llvm::Function *CGOpenMPRuntime::emitTaskOutlinedFunction( 1486 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 1487 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 1488 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 1489 bool Tied, unsigned &NumberOfParts) { 1490 auto &&UntiedCodeGen = [this, &D, TaskTVar](CodeGenFunction &CGF, 1491 PrePostActionTy &) { 1492 llvm::Value *ThreadID = getThreadID(CGF, D.getBeginLoc()); 1493 llvm::Value *UpLoc = emitUpdateLocation(CGF, D.getBeginLoc()); 1494 llvm::Value *TaskArgs[] = { 1495 UpLoc, ThreadID, 1496 CGF.EmitLoadOfPointerLValue(CGF.GetAddrOfLocalVar(TaskTVar), 1497 TaskTVar->getType()->castAs<PointerType>()) 1498 .getPointer()}; 1499 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), TaskArgs); 1500 }; 1501 CGOpenMPTaskOutlinedRegionInfo::UntiedTaskActionTy Action(Tied, PartIDVar, 1502 UntiedCodeGen); 1503 CodeGen.setAction(Action); 1504 assert(!ThreadIDVar->getType()->isPointerType() && 1505 "thread id variable must be of type kmp_int32 for tasks"); 1506 const OpenMPDirectiveKind Region = 1507 isOpenMPTaskLoopDirective(D.getDirectiveKind()) ? OMPD_taskloop 1508 : OMPD_task; 1509 const CapturedStmt *CS = D.getCapturedStmt(Region); 1510 const auto *TD = dyn_cast<OMPTaskDirective>(&D); 1511 CodeGenFunction CGF(CGM, true); 1512 CGOpenMPTaskOutlinedRegionInfo CGInfo(*CS, ThreadIDVar, CodeGen, 1513 InnermostKind, 1514 TD ? TD->hasCancel() : false, Action); 1515 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 1516 llvm::Function *Res = CGF.GenerateCapturedStmtFunction(*CS); 1517 if (!Tied) 1518 NumberOfParts = Action.getNumberOfParts(); 1519 return Res; 1520 } 1521 1522 static void buildStructValue(ConstantStructBuilder &Fields, CodeGenModule &CGM, 1523 const RecordDecl *RD, const CGRecordLayout &RL, 1524 ArrayRef<llvm::Constant *> Data) { 1525 llvm::StructType *StructTy = RL.getLLVMType(); 1526 unsigned PrevIdx = 0; 1527 ConstantInitBuilder CIBuilder(CGM); 1528 auto DI = Data.begin(); 1529 for (const FieldDecl *FD : RD->fields()) { 1530 unsigned Idx = RL.getLLVMFieldNo(FD); 1531 // Fill the alignment. 1532 for (unsigned I = PrevIdx; I < Idx; ++I) 1533 Fields.add(llvm::Constant::getNullValue(StructTy->getElementType(I))); 1534 PrevIdx = Idx + 1; 1535 Fields.add(*DI); 1536 ++DI; 1537 } 1538 } 1539 1540 template <class... As> 1541 static llvm::GlobalVariable * 1542 createGlobalStruct(CodeGenModule &CGM, QualType Ty, bool IsConstant, 1543 ArrayRef<llvm::Constant *> Data, const Twine &Name, 1544 As &&... Args) { 1545 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1546 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1547 ConstantInitBuilder CIBuilder(CGM); 1548 ConstantStructBuilder Fields = CIBuilder.beginStruct(RL.getLLVMType()); 1549 buildStructValue(Fields, CGM, RD, RL, Data); 1550 return Fields.finishAndCreateGlobal( 1551 Name, CGM.getContext().getAlignOfGlobalVarInChars(Ty), IsConstant, 1552 std::forward<As>(Args)...); 1553 } 1554 1555 template <typename T> 1556 static void 1557 createConstantGlobalStructAndAddToParent(CodeGenModule &CGM, QualType Ty, 1558 ArrayRef<llvm::Constant *> Data, 1559 T &Parent) { 1560 const auto *RD = cast<RecordDecl>(Ty->getAsTagDecl()); 1561 const CGRecordLayout &RL = CGM.getTypes().getCGRecordLayout(RD); 1562 ConstantStructBuilder Fields = Parent.beginStruct(RL.getLLVMType()); 1563 buildStructValue(Fields, CGM, RD, RL, Data); 1564 Fields.finishAndAddTo(Parent); 1565 } 1566 1567 Address CGOpenMPRuntime::getOrCreateDefaultLocation(unsigned Flags) { 1568 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1569 unsigned Reserved2Flags = getDefaultLocationReserved2Flags(); 1570 FlagsTy FlagsKey(Flags, Reserved2Flags); 1571 llvm::Value *Entry = OpenMPDefaultLocMap.lookup(FlagsKey); 1572 if (!Entry) { 1573 if (!DefaultOpenMPPSource) { 1574 // Initialize default location for psource field of ident_t structure of 1575 // all ident_t objects. Format is ";file;function;line;column;;". 1576 // Taken from 1577 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp_str.cpp 1578 DefaultOpenMPPSource = 1579 CGM.GetAddrOfConstantCString(";unknown;unknown;0;0;;").getPointer(); 1580 DefaultOpenMPPSource = 1581 llvm::ConstantExpr::getBitCast(DefaultOpenMPPSource, CGM.Int8PtrTy); 1582 } 1583 1584 llvm::Constant *Data[] = { 1585 llvm::ConstantInt::getNullValue(CGM.Int32Ty), 1586 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 1587 llvm::ConstantInt::get(CGM.Int32Ty, Reserved2Flags), 1588 llvm::ConstantInt::getNullValue(CGM.Int32Ty), DefaultOpenMPPSource}; 1589 llvm::GlobalValue *DefaultOpenMPLocation = 1590 createGlobalStruct(CGM, IdentQTy, isDefaultLocationConstant(), Data, "", 1591 llvm::GlobalValue::PrivateLinkage); 1592 DefaultOpenMPLocation->setUnnamedAddr( 1593 llvm::GlobalValue::UnnamedAddr::Global); 1594 1595 OpenMPDefaultLocMap[FlagsKey] = Entry = DefaultOpenMPLocation; 1596 } 1597 return Address(Entry, Align); 1598 } 1599 1600 void CGOpenMPRuntime::setLocThreadIdInsertPt(CodeGenFunction &CGF, 1601 bool AtCurrentPoint) { 1602 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1603 assert(!Elem.second.ServiceInsertPt && "Insert point is set already."); 1604 1605 llvm::Value *Undef = llvm::UndefValue::get(CGF.Int32Ty); 1606 if (AtCurrentPoint) { 1607 Elem.second.ServiceInsertPt = new llvm::BitCastInst( 1608 Undef, CGF.Int32Ty, "svcpt", CGF.Builder.GetInsertBlock()); 1609 } else { 1610 Elem.second.ServiceInsertPt = 1611 new llvm::BitCastInst(Undef, CGF.Int32Ty, "svcpt"); 1612 Elem.second.ServiceInsertPt->insertAfter(CGF.AllocaInsertPt); 1613 } 1614 } 1615 1616 void CGOpenMPRuntime::clearLocThreadIdInsertPt(CodeGenFunction &CGF) { 1617 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1618 if (Elem.second.ServiceInsertPt) { 1619 llvm::Instruction *Ptr = Elem.second.ServiceInsertPt; 1620 Elem.second.ServiceInsertPt = nullptr; 1621 Ptr->eraseFromParent(); 1622 } 1623 } 1624 1625 llvm::Value *CGOpenMPRuntime::emitUpdateLocation(CodeGenFunction &CGF, 1626 SourceLocation Loc, 1627 unsigned Flags) { 1628 Flags |= OMP_IDENT_KMPC; 1629 // If no debug info is generated - return global default location. 1630 if (CGM.getCodeGenOpts().getDebugInfo() == codegenoptions::NoDebugInfo || 1631 Loc.isInvalid()) 1632 return getOrCreateDefaultLocation(Flags).getPointer(); 1633 1634 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1635 1636 CharUnits Align = CGM.getContext().getTypeAlignInChars(IdentQTy); 1637 Address LocValue = Address::invalid(); 1638 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1639 if (I != OpenMPLocThreadIDMap.end()) 1640 LocValue = Address(I->second.DebugLoc, Align); 1641 1642 // OpenMPLocThreadIDMap may have null DebugLoc and non-null ThreadID, if 1643 // GetOpenMPThreadID was called before this routine. 1644 if (!LocValue.isValid()) { 1645 // Generate "ident_t .kmpc_loc.addr;" 1646 Address AI = CGF.CreateMemTemp(IdentQTy, ".kmpc_loc.addr"); 1647 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1648 Elem.second.DebugLoc = AI.getPointer(); 1649 LocValue = AI; 1650 1651 if (!Elem.second.ServiceInsertPt) 1652 setLocThreadIdInsertPt(CGF); 1653 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1654 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1655 CGF.Builder.CreateMemCpy(LocValue, getOrCreateDefaultLocation(Flags), 1656 CGF.getTypeSize(IdentQTy)); 1657 } 1658 1659 // char **psource = &.kmpc_loc_<flags>.addr.psource; 1660 LValue Base = CGF.MakeAddrLValue(LocValue, IdentQTy); 1661 auto Fields = cast<RecordDecl>(IdentQTy->getAsTagDecl())->field_begin(); 1662 LValue PSource = 1663 CGF.EmitLValueForField(Base, *std::next(Fields, IdentField_PSource)); 1664 1665 llvm::Value *OMPDebugLoc = OpenMPDebugLocMap.lookup(Loc.getRawEncoding()); 1666 if (OMPDebugLoc == nullptr) { 1667 SmallString<128> Buffer2; 1668 llvm::raw_svector_ostream OS2(Buffer2); 1669 // Build debug location 1670 PresumedLoc PLoc = CGF.getContext().getSourceManager().getPresumedLoc(Loc); 1671 OS2 << ";" << PLoc.getFilename() << ";"; 1672 if (const auto *FD = dyn_cast_or_null<FunctionDecl>(CGF.CurFuncDecl)) 1673 OS2 << FD->getQualifiedNameAsString(); 1674 OS2 << ";" << PLoc.getLine() << ";" << PLoc.getColumn() << ";;"; 1675 OMPDebugLoc = CGF.Builder.CreateGlobalStringPtr(OS2.str()); 1676 OpenMPDebugLocMap[Loc.getRawEncoding()] = OMPDebugLoc; 1677 } 1678 // *psource = ";<File>;<Function>;<Line>;<Column>;;"; 1679 CGF.EmitStoreOfScalar(OMPDebugLoc, PSource); 1680 1681 // Our callers always pass this to a runtime function, so for 1682 // convenience, go ahead and return a naked pointer. 1683 return LocValue.getPointer(); 1684 } 1685 1686 llvm::Value *CGOpenMPRuntime::getThreadID(CodeGenFunction &CGF, 1687 SourceLocation Loc) { 1688 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1689 1690 llvm::Value *ThreadID = nullptr; 1691 // Check whether we've already cached a load of the thread id in this 1692 // function. 1693 auto I = OpenMPLocThreadIDMap.find(CGF.CurFn); 1694 if (I != OpenMPLocThreadIDMap.end()) { 1695 ThreadID = I->second.ThreadID; 1696 if (ThreadID != nullptr) 1697 return ThreadID; 1698 } 1699 // If exceptions are enabled, do not use parameter to avoid possible crash. 1700 if (!CGF.EHStack.requiresLandingPad() || !CGF.getLangOpts().Exceptions || 1701 !CGF.getLangOpts().CXXExceptions || 1702 CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 1703 if (auto *OMPRegionInfo = 1704 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 1705 if (OMPRegionInfo->getThreadIDVariable()) { 1706 // Check if this an outlined function with thread id passed as argument. 1707 LValue LVal = OMPRegionInfo->getThreadIDVariableLValue(CGF); 1708 ThreadID = CGF.EmitLoadOfScalar(LVal, Loc); 1709 // If value loaded in entry block, cache it and use it everywhere in 1710 // function. 1711 if (CGF.Builder.GetInsertBlock() == CGF.AllocaInsertPt->getParent()) { 1712 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1713 Elem.second.ThreadID = ThreadID; 1714 } 1715 return ThreadID; 1716 } 1717 } 1718 } 1719 1720 // This is not an outlined function region - need to call __kmpc_int32 1721 // kmpc_global_thread_num(ident_t *loc). 1722 // Generate thread id value and cache this value for use across the 1723 // function. 1724 auto &Elem = OpenMPLocThreadIDMap.FindAndConstruct(CGF.CurFn); 1725 if (!Elem.second.ServiceInsertPt) 1726 setLocThreadIdInsertPt(CGF); 1727 CGBuilderTy::InsertPointGuard IPG(CGF.Builder); 1728 CGF.Builder.SetInsertPoint(Elem.second.ServiceInsertPt); 1729 llvm::CallInst *Call = CGF.Builder.CreateCall( 1730 createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 1731 emitUpdateLocation(CGF, Loc)); 1732 Call->setCallingConv(CGF.getRuntimeCC()); 1733 Elem.second.ThreadID = Call; 1734 return Call; 1735 } 1736 1737 void CGOpenMPRuntime::functionFinished(CodeGenFunction &CGF) { 1738 assert(CGF.CurFn && "No function in current CodeGenFunction."); 1739 if (OpenMPLocThreadIDMap.count(CGF.CurFn)) { 1740 clearLocThreadIdInsertPt(CGF); 1741 OpenMPLocThreadIDMap.erase(CGF.CurFn); 1742 } 1743 if (FunctionUDRMap.count(CGF.CurFn) > 0) { 1744 for(auto *D : FunctionUDRMap[CGF.CurFn]) 1745 UDRMap.erase(D); 1746 FunctionUDRMap.erase(CGF.CurFn); 1747 } 1748 auto I = FunctionUDMMap.find(CGF.CurFn); 1749 if (I != FunctionUDMMap.end()) { 1750 for(auto *D : I->second) 1751 UDMMap.erase(D); 1752 FunctionUDMMap.erase(I); 1753 } 1754 } 1755 1756 llvm::Type *CGOpenMPRuntime::getIdentTyPointerTy() { 1757 return IdentTy->getPointerTo(); 1758 } 1759 1760 llvm::Type *CGOpenMPRuntime::getKmpc_MicroPointerTy() { 1761 if (!Kmpc_MicroTy) { 1762 // Build void (*kmpc_micro)(kmp_int32 *global_tid, kmp_int32 *bound_tid,...) 1763 llvm::Type *MicroParams[] = {llvm::PointerType::getUnqual(CGM.Int32Ty), 1764 llvm::PointerType::getUnqual(CGM.Int32Ty)}; 1765 Kmpc_MicroTy = llvm::FunctionType::get(CGM.VoidTy, MicroParams, true); 1766 } 1767 return llvm::PointerType::getUnqual(Kmpc_MicroTy); 1768 } 1769 1770 llvm::FunctionCallee CGOpenMPRuntime::createRuntimeFunction(unsigned Function) { 1771 llvm::FunctionCallee RTLFn = nullptr; 1772 switch (static_cast<OpenMPRTLFunction>(Function)) { 1773 case OMPRTL__kmpc_fork_call: { 1774 // Build void __kmpc_fork_call(ident_t *loc, kmp_int32 argc, kmpc_micro 1775 // microtask, ...); 1776 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1777 getKmpc_MicroPointerTy()}; 1778 auto *FnTy = 1779 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 1780 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_call"); 1781 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 1782 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 1783 llvm::LLVMContext &Ctx = F->getContext(); 1784 llvm::MDBuilder MDB(Ctx); 1785 // Annotate the callback behavior of the __kmpc_fork_call: 1786 // - The callback callee is argument number 2 (microtask). 1787 // - The first two arguments of the callback callee are unknown (-1). 1788 // - All variadic arguments to the __kmpc_fork_call are passed to the 1789 // callback callee. 1790 F->addMetadata( 1791 llvm::LLVMContext::MD_callback, 1792 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 1793 2, {-1, -1}, 1794 /* VarArgsArePassed */ true)})); 1795 } 1796 } 1797 break; 1798 } 1799 case OMPRTL__kmpc_global_thread_num: { 1800 // Build kmp_int32 __kmpc_global_thread_num(ident_t *loc); 1801 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1802 auto *FnTy = 1803 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1804 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_global_thread_num"); 1805 break; 1806 } 1807 case OMPRTL__kmpc_threadprivate_cached: { 1808 // Build void *__kmpc_threadprivate_cached(ident_t *loc, 1809 // kmp_int32 global_tid, void *data, size_t size, void ***cache); 1810 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1811 CGM.VoidPtrTy, CGM.SizeTy, 1812 CGM.VoidPtrTy->getPointerTo()->getPointerTo()}; 1813 auto *FnTy = 1814 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg*/ false); 1815 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_cached"); 1816 break; 1817 } 1818 case OMPRTL__kmpc_critical: { 1819 // Build void __kmpc_critical(ident_t *loc, kmp_int32 global_tid, 1820 // kmp_critical_name *crit); 1821 llvm::Type *TypeParams[] = { 1822 getIdentTyPointerTy(), CGM.Int32Ty, 1823 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1824 auto *FnTy = 1825 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1826 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical"); 1827 break; 1828 } 1829 case OMPRTL__kmpc_critical_with_hint: { 1830 // Build void __kmpc_critical_with_hint(ident_t *loc, kmp_int32 global_tid, 1831 // kmp_critical_name *crit, uintptr_t hint); 1832 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1833 llvm::PointerType::getUnqual(KmpCriticalNameTy), 1834 CGM.IntPtrTy}; 1835 auto *FnTy = 1836 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1837 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_critical_with_hint"); 1838 break; 1839 } 1840 case OMPRTL__kmpc_threadprivate_register: { 1841 // Build void __kmpc_threadprivate_register(ident_t *, void *data, 1842 // kmpc_ctor ctor, kmpc_cctor cctor, kmpc_dtor dtor); 1843 // typedef void *(*kmpc_ctor)(void *); 1844 auto *KmpcCtorTy = 1845 llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 1846 /*isVarArg*/ false)->getPointerTo(); 1847 // typedef void *(*kmpc_cctor)(void *, void *); 1848 llvm::Type *KmpcCopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 1849 auto *KmpcCopyCtorTy = 1850 llvm::FunctionType::get(CGM.VoidPtrTy, KmpcCopyCtorTyArgs, 1851 /*isVarArg*/ false) 1852 ->getPointerTo(); 1853 // typedef void (*kmpc_dtor)(void *); 1854 auto *KmpcDtorTy = 1855 llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, /*isVarArg*/ false) 1856 ->getPointerTo(); 1857 llvm::Type *FnTyArgs[] = {getIdentTyPointerTy(), CGM.VoidPtrTy, KmpcCtorTy, 1858 KmpcCopyCtorTy, KmpcDtorTy}; 1859 auto *FnTy = llvm::FunctionType::get(CGM.VoidTy, FnTyArgs, 1860 /*isVarArg*/ false); 1861 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_threadprivate_register"); 1862 break; 1863 } 1864 case OMPRTL__kmpc_end_critical: { 1865 // Build void __kmpc_end_critical(ident_t *loc, kmp_int32 global_tid, 1866 // kmp_critical_name *crit); 1867 llvm::Type *TypeParams[] = { 1868 getIdentTyPointerTy(), CGM.Int32Ty, 1869 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 1870 auto *FnTy = 1871 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1872 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_critical"); 1873 break; 1874 } 1875 case OMPRTL__kmpc_cancel_barrier: { 1876 // Build kmp_int32 __kmpc_cancel_barrier(ident_t *loc, kmp_int32 1877 // global_tid); 1878 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1879 auto *FnTy = 1880 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 1881 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_cancel_barrier"); 1882 break; 1883 } 1884 case OMPRTL__kmpc_barrier: { 1885 // Build void __kmpc_barrier(ident_t *loc, kmp_int32 global_tid); 1886 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1887 auto *FnTy = 1888 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1889 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name*/ "__kmpc_barrier"); 1890 break; 1891 } 1892 case OMPRTL__kmpc_for_static_fini: { 1893 // Build void __kmpc_for_static_fini(ident_t *loc, kmp_int32 global_tid); 1894 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1895 auto *FnTy = 1896 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1897 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_for_static_fini"); 1898 break; 1899 } 1900 case OMPRTL__kmpc_push_num_threads: { 1901 // Build void __kmpc_push_num_threads(ident_t *loc, kmp_int32 global_tid, 1902 // kmp_int32 num_threads) 1903 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 1904 CGM.Int32Ty}; 1905 auto *FnTy = 1906 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1907 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_threads"); 1908 break; 1909 } 1910 case OMPRTL__kmpc_serialized_parallel: { 1911 // Build void __kmpc_serialized_parallel(ident_t *loc, kmp_int32 1912 // global_tid); 1913 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1914 auto *FnTy = 1915 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1916 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_serialized_parallel"); 1917 break; 1918 } 1919 case OMPRTL__kmpc_end_serialized_parallel: { 1920 // Build void __kmpc_end_serialized_parallel(ident_t *loc, kmp_int32 1921 // global_tid); 1922 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1923 auto *FnTy = 1924 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1925 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_serialized_parallel"); 1926 break; 1927 } 1928 case OMPRTL__kmpc_flush: { 1929 // Build void __kmpc_flush(ident_t *loc); 1930 llvm::Type *TypeParams[] = {getIdentTyPointerTy()}; 1931 auto *FnTy = 1932 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 1933 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_flush"); 1934 break; 1935 } 1936 case OMPRTL__kmpc_master: { 1937 // Build kmp_int32 __kmpc_master(ident_t *loc, kmp_int32 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_master"); 1942 break; 1943 } 1944 case OMPRTL__kmpc_end_master: { 1945 // Build void __kmpc_end_master(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_end_master"); 1950 break; 1951 } 1952 case OMPRTL__kmpc_omp_taskyield: { 1953 // Build kmp_int32 __kmpc_omp_taskyield(ident_t *, kmp_int32 global_tid, 1954 // int end_part); 1955 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 1956 auto *FnTy = 1957 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1958 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_taskyield"); 1959 break; 1960 } 1961 case OMPRTL__kmpc_single: { 1962 // Build kmp_int32 __kmpc_single(ident_t *loc, kmp_int32 global_tid); 1963 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1964 auto *FnTy = 1965 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 1966 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_single"); 1967 break; 1968 } 1969 case OMPRTL__kmpc_end_single: { 1970 // Build void __kmpc_end_single(ident_t *loc, kmp_int32 global_tid); 1971 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 1972 auto *FnTy = 1973 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 1974 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_single"); 1975 break; 1976 } 1977 case OMPRTL__kmpc_omp_task_alloc: { 1978 // Build kmp_task_t *__kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 1979 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1980 // kmp_routine_entry_t *task_entry); 1981 assert(KmpRoutineEntryPtrTy != nullptr && 1982 "Type kmp_routine_entry_t must be created."); 1983 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1984 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy}; 1985 // Return void * and then cast to particular kmp_task_t type. 1986 auto *FnTy = 1987 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 1988 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_alloc"); 1989 break; 1990 } 1991 case OMPRTL__kmpc_omp_target_task_alloc: { 1992 // Build kmp_task_t *__kmpc_omp_target_task_alloc(ident_t *, kmp_int32 gtid, 1993 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 1994 // kmp_routine_entry_t *task_entry, kmp_int64 device_id); 1995 assert(KmpRoutineEntryPtrTy != nullptr && 1996 "Type kmp_routine_entry_t must be created."); 1997 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 1998 CGM.SizeTy, CGM.SizeTy, KmpRoutineEntryPtrTy, 1999 CGM.Int64Ty}; 2000 // Return void * and then cast to particular kmp_task_t type. 2001 auto *FnTy = 2002 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2003 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_target_task_alloc"); 2004 break; 2005 } 2006 case OMPRTL__kmpc_omp_task: { 2007 // Build kmp_int32 __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2008 // *new_task); 2009 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2010 CGM.VoidPtrTy}; 2011 auto *FnTy = 2012 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2013 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task"); 2014 break; 2015 } 2016 case OMPRTL__kmpc_copyprivate: { 2017 // Build void __kmpc_copyprivate(ident_t *loc, kmp_int32 global_tid, 2018 // size_t cpy_size, void *cpy_data, void(*cpy_func)(void *, void *), 2019 // kmp_int32 didit); 2020 llvm::Type *CpyTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2021 auto *CpyFnTy = 2022 llvm::FunctionType::get(CGM.VoidTy, CpyTypeParams, /*isVarArg=*/false); 2023 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.SizeTy, 2024 CGM.VoidPtrTy, CpyFnTy->getPointerTo(), 2025 CGM.Int32Ty}; 2026 auto *FnTy = 2027 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2028 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_copyprivate"); 2029 break; 2030 } 2031 case OMPRTL__kmpc_reduce: { 2032 // Build kmp_int32 __kmpc_reduce(ident_t *loc, kmp_int32 global_tid, 2033 // kmp_int32 num_vars, size_t reduce_size, void *reduce_data, void 2034 // (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name *lck); 2035 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2036 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2037 /*isVarArg=*/false); 2038 llvm::Type *TypeParams[] = { 2039 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2040 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2041 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2042 auto *FnTy = 2043 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2044 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce"); 2045 break; 2046 } 2047 case OMPRTL__kmpc_reduce_nowait: { 2048 // Build kmp_int32 __kmpc_reduce_nowait(ident_t *loc, kmp_int32 2049 // global_tid, kmp_int32 num_vars, size_t reduce_size, void *reduce_data, 2050 // void (*reduce_func)(void *lhs_data, void *rhs_data), kmp_critical_name 2051 // *lck); 2052 llvm::Type *ReduceTypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2053 auto *ReduceFnTy = llvm::FunctionType::get(CGM.VoidTy, ReduceTypeParams, 2054 /*isVarArg=*/false); 2055 llvm::Type *TypeParams[] = { 2056 getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, CGM.SizeTy, 2057 CGM.VoidPtrTy, ReduceFnTy->getPointerTo(), 2058 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2059 auto *FnTy = 2060 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2061 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_reduce_nowait"); 2062 break; 2063 } 2064 case OMPRTL__kmpc_end_reduce: { 2065 // Build void __kmpc_end_reduce(ident_t *loc, kmp_int32 global_tid, 2066 // kmp_critical_name *lck); 2067 llvm::Type *TypeParams[] = { 2068 getIdentTyPointerTy(), CGM.Int32Ty, 2069 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2070 auto *FnTy = 2071 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2072 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce"); 2073 break; 2074 } 2075 case OMPRTL__kmpc_end_reduce_nowait: { 2076 // Build __kmpc_end_reduce_nowait(ident_t *loc, kmp_int32 global_tid, 2077 // kmp_critical_name *lck); 2078 llvm::Type *TypeParams[] = { 2079 getIdentTyPointerTy(), CGM.Int32Ty, 2080 llvm::PointerType::getUnqual(KmpCriticalNameTy)}; 2081 auto *FnTy = 2082 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2083 RTLFn = 2084 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_end_reduce_nowait"); 2085 break; 2086 } 2087 case OMPRTL__kmpc_omp_task_begin_if0: { 2088 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2089 // *new_task); 2090 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2091 CGM.VoidPtrTy}; 2092 auto *FnTy = 2093 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2094 RTLFn = 2095 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_begin_if0"); 2096 break; 2097 } 2098 case OMPRTL__kmpc_omp_task_complete_if0: { 2099 // Build void __kmpc_omp_task(ident_t *, kmp_int32 gtid, kmp_task_t 2100 // *new_task); 2101 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2102 CGM.VoidPtrTy}; 2103 auto *FnTy = 2104 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2105 RTLFn = CGM.CreateRuntimeFunction(FnTy, 2106 /*Name=*/"__kmpc_omp_task_complete_if0"); 2107 break; 2108 } 2109 case OMPRTL__kmpc_ordered: { 2110 // Build void __kmpc_ordered(ident_t *loc, kmp_int32 global_tid); 2111 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2112 auto *FnTy = 2113 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2114 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_ordered"); 2115 break; 2116 } 2117 case OMPRTL__kmpc_end_ordered: { 2118 // Build void __kmpc_end_ordered(ident_t *loc, kmp_int32 global_tid); 2119 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2120 auto *FnTy = 2121 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2122 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_ordered"); 2123 break; 2124 } 2125 case OMPRTL__kmpc_omp_taskwait: { 2126 // Build kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 global_tid); 2127 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2128 auto *FnTy = 2129 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2130 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_omp_taskwait"); 2131 break; 2132 } 2133 case OMPRTL__kmpc_taskgroup: { 2134 // Build void __kmpc_taskgroup(ident_t *loc, kmp_int32 global_tid); 2135 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2136 auto *FnTy = 2137 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2138 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_taskgroup"); 2139 break; 2140 } 2141 case OMPRTL__kmpc_end_taskgroup: { 2142 // Build void __kmpc_end_taskgroup(ident_t *loc, kmp_int32 global_tid); 2143 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2144 auto *FnTy = 2145 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2146 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_end_taskgroup"); 2147 break; 2148 } 2149 case OMPRTL__kmpc_push_proc_bind: { 2150 // Build void __kmpc_push_proc_bind(ident_t *loc, kmp_int32 global_tid, 2151 // int proc_bind) 2152 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2153 auto *FnTy = 2154 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2155 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_proc_bind"); 2156 break; 2157 } 2158 case OMPRTL__kmpc_omp_task_with_deps: { 2159 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 2160 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 2161 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list); 2162 llvm::Type *TypeParams[] = { 2163 getIdentTyPointerTy(), CGM.Int32Ty, CGM.VoidPtrTy, CGM.Int32Ty, 2164 CGM.VoidPtrTy, CGM.Int32Ty, CGM.VoidPtrTy}; 2165 auto *FnTy = 2166 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg=*/false); 2167 RTLFn = 2168 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_task_with_deps"); 2169 break; 2170 } 2171 case OMPRTL__kmpc_omp_wait_deps: { 2172 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 2173 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 ndeps_noalias, 2174 // kmp_depend_info_t *noalias_dep_list); 2175 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2176 CGM.Int32Ty, CGM.VoidPtrTy, 2177 CGM.Int32Ty, CGM.VoidPtrTy}; 2178 auto *FnTy = 2179 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2180 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_omp_wait_deps"); 2181 break; 2182 } 2183 case OMPRTL__kmpc_cancellationpoint: { 2184 // Build kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 2185 // global_tid, kmp_int32 cncl_kind) 2186 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2187 auto *FnTy = 2188 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2189 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancellationpoint"); 2190 break; 2191 } 2192 case OMPRTL__kmpc_cancel: { 2193 // Build kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 2194 // kmp_int32 cncl_kind) 2195 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.IntTy}; 2196 auto *FnTy = 2197 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2198 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_cancel"); 2199 break; 2200 } 2201 case OMPRTL__kmpc_push_num_teams: { 2202 // Build void kmpc_push_num_teams (ident_t loc, kmp_int32 global_tid, 2203 // kmp_int32 num_teams, kmp_int32 num_threads) 2204 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, CGM.Int32Ty, 2205 CGM.Int32Ty}; 2206 auto *FnTy = 2207 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2208 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_num_teams"); 2209 break; 2210 } 2211 case OMPRTL__kmpc_fork_teams: { 2212 // Build void __kmpc_fork_teams(ident_t *loc, kmp_int32 argc, kmpc_micro 2213 // microtask, ...); 2214 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2215 getKmpc_MicroPointerTy()}; 2216 auto *FnTy = 2217 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ true); 2218 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_fork_teams"); 2219 if (auto *F = dyn_cast<llvm::Function>(RTLFn.getCallee())) { 2220 if (!F->hasMetadata(llvm::LLVMContext::MD_callback)) { 2221 llvm::LLVMContext &Ctx = F->getContext(); 2222 llvm::MDBuilder MDB(Ctx); 2223 // Annotate the callback behavior of the __kmpc_fork_teams: 2224 // - The callback callee is argument number 2 (microtask). 2225 // - The first two arguments of the callback callee are unknown (-1). 2226 // - All variadic arguments to the __kmpc_fork_teams are passed to the 2227 // callback callee. 2228 F->addMetadata( 2229 llvm::LLVMContext::MD_callback, 2230 *llvm::MDNode::get(Ctx, {MDB.createCallbackEncoding( 2231 2, {-1, -1}, 2232 /* VarArgsArePassed */ true)})); 2233 } 2234 } 2235 break; 2236 } 2237 case OMPRTL__kmpc_taskloop: { 2238 // Build void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 2239 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 2240 // sched, kmp_uint64 grainsize, void *task_dup); 2241 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2242 CGM.IntTy, 2243 CGM.VoidPtrTy, 2244 CGM.IntTy, 2245 CGM.Int64Ty->getPointerTo(), 2246 CGM.Int64Ty->getPointerTo(), 2247 CGM.Int64Ty, 2248 CGM.IntTy, 2249 CGM.IntTy, 2250 CGM.Int64Ty, 2251 CGM.VoidPtrTy}; 2252 auto *FnTy = 2253 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2254 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_taskloop"); 2255 break; 2256 } 2257 case OMPRTL__kmpc_doacross_init: { 2258 // Build void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, kmp_int32 2259 // num_dims, struct kmp_dim *dims); 2260 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), 2261 CGM.Int32Ty, 2262 CGM.Int32Ty, 2263 CGM.VoidPtrTy}; 2264 auto *FnTy = 2265 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2266 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_init"); 2267 break; 2268 } 2269 case OMPRTL__kmpc_doacross_fini: { 2270 // Build void __kmpc_doacross_fini(ident_t *loc, kmp_int32 gtid); 2271 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty}; 2272 auto *FnTy = 2273 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2274 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_fini"); 2275 break; 2276 } 2277 case OMPRTL__kmpc_doacross_post: { 2278 // Build void __kmpc_doacross_post(ident_t *loc, kmp_int32 gtid, kmp_int64 2279 // *vec); 2280 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2281 CGM.Int64Ty->getPointerTo()}; 2282 auto *FnTy = 2283 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2284 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_post"); 2285 break; 2286 } 2287 case OMPRTL__kmpc_doacross_wait: { 2288 // Build void __kmpc_doacross_wait(ident_t *loc, kmp_int32 gtid, kmp_int64 2289 // *vec); 2290 llvm::Type *TypeParams[] = {getIdentTyPointerTy(), CGM.Int32Ty, 2291 CGM.Int64Ty->getPointerTo()}; 2292 auto *FnTy = 2293 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2294 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_doacross_wait"); 2295 break; 2296 } 2297 case OMPRTL__kmpc_task_reduction_init: { 2298 // Build void *__kmpc_task_reduction_init(int gtid, int num_data, void 2299 // *data); 2300 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.IntTy, CGM.VoidPtrTy}; 2301 auto *FnTy = 2302 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2303 RTLFn = 2304 CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_task_reduction_init"); 2305 break; 2306 } 2307 case OMPRTL__kmpc_task_reduction_get_th_data: { 2308 // Build void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 2309 // *d); 2310 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2311 auto *FnTy = 2312 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2313 RTLFn = CGM.CreateRuntimeFunction( 2314 FnTy, /*Name=*/"__kmpc_task_reduction_get_th_data"); 2315 break; 2316 } 2317 case OMPRTL__kmpc_alloc: { 2318 // Build to void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t 2319 // al); omp_allocator_handle_t type is void *. 2320 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.SizeTy, CGM.VoidPtrTy}; 2321 auto *FnTy = 2322 llvm::FunctionType::get(CGM.VoidPtrTy, TypeParams, /*isVarArg=*/false); 2323 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_alloc"); 2324 break; 2325 } 2326 case OMPRTL__kmpc_free: { 2327 // Build to void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t 2328 // al); omp_allocator_handle_t type is void *. 2329 llvm::Type *TypeParams[] = {CGM.IntTy, CGM.VoidPtrTy, CGM.VoidPtrTy}; 2330 auto *FnTy = 2331 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2332 RTLFn = CGM.CreateRuntimeFunction(FnTy, /*Name=*/"__kmpc_free"); 2333 break; 2334 } 2335 case OMPRTL__kmpc_push_target_tripcount: { 2336 // Build void __kmpc_push_target_tripcount(int64_t device_id, kmp_uint64 2337 // size); 2338 llvm::Type *TypeParams[] = {CGM.Int64Ty, CGM.Int64Ty}; 2339 llvm::FunctionType *FnTy = 2340 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2341 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__kmpc_push_target_tripcount"); 2342 break; 2343 } 2344 case OMPRTL__tgt_target: { 2345 // Build int32_t __tgt_target(int64_t device_id, void *host_ptr, int32_t 2346 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2347 // *arg_types); 2348 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2349 CGM.VoidPtrTy, 2350 CGM.Int32Ty, 2351 CGM.VoidPtrPtrTy, 2352 CGM.VoidPtrPtrTy, 2353 CGM.Int64Ty->getPointerTo(), 2354 CGM.Int64Ty->getPointerTo()}; 2355 auto *FnTy = 2356 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2357 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target"); 2358 break; 2359 } 2360 case OMPRTL__tgt_target_nowait: { 2361 // Build int32_t __tgt_target_nowait(int64_t device_id, void *host_ptr, 2362 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2363 // int64_t *arg_types); 2364 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2365 CGM.VoidPtrTy, 2366 CGM.Int32Ty, 2367 CGM.VoidPtrPtrTy, 2368 CGM.VoidPtrPtrTy, 2369 CGM.Int64Ty->getPointerTo(), 2370 CGM.Int64Ty->getPointerTo()}; 2371 auto *FnTy = 2372 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2373 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_nowait"); 2374 break; 2375 } 2376 case OMPRTL__tgt_target_teams: { 2377 // Build int32_t __tgt_target_teams(int64_t device_id, void *host_ptr, 2378 // int32_t arg_num, void** args_base, void **args, int64_t *arg_sizes, 2379 // int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2380 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2381 CGM.VoidPtrTy, 2382 CGM.Int32Ty, 2383 CGM.VoidPtrPtrTy, 2384 CGM.VoidPtrPtrTy, 2385 CGM.Int64Ty->getPointerTo(), 2386 CGM.Int64Ty->getPointerTo(), 2387 CGM.Int32Ty, 2388 CGM.Int32Ty}; 2389 auto *FnTy = 2390 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2391 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams"); 2392 break; 2393 } 2394 case OMPRTL__tgt_target_teams_nowait: { 2395 // Build int32_t __tgt_target_teams_nowait(int64_t device_id, void 2396 // *host_ptr, int32_t arg_num, void** args_base, void **args, int64_t 2397 // *arg_sizes, int64_t *arg_types, int32_t num_teams, int32_t thread_limit); 2398 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2399 CGM.VoidPtrTy, 2400 CGM.Int32Ty, 2401 CGM.VoidPtrPtrTy, 2402 CGM.VoidPtrPtrTy, 2403 CGM.Int64Ty->getPointerTo(), 2404 CGM.Int64Ty->getPointerTo(), 2405 CGM.Int32Ty, 2406 CGM.Int32Ty}; 2407 auto *FnTy = 2408 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2409 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_teams_nowait"); 2410 break; 2411 } 2412 case OMPRTL__tgt_register_requires: { 2413 // Build void __tgt_register_requires(int64_t flags); 2414 llvm::Type *TypeParams[] = {CGM.Int64Ty}; 2415 auto *FnTy = 2416 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2417 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_requires"); 2418 break; 2419 } 2420 case OMPRTL__tgt_register_lib: { 2421 // Build void __tgt_register_lib(__tgt_bin_desc *desc); 2422 QualType ParamTy = 2423 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2424 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2425 auto *FnTy = 2426 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2427 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_register_lib"); 2428 break; 2429 } 2430 case OMPRTL__tgt_unregister_lib: { 2431 // Build void __tgt_unregister_lib(__tgt_bin_desc *desc); 2432 QualType ParamTy = 2433 CGM.getContext().getPointerType(getTgtBinaryDescriptorQTy()); 2434 llvm::Type *TypeParams[] = {CGM.getTypes().ConvertTypeForMem(ParamTy)}; 2435 auto *FnTy = 2436 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2437 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_unregister_lib"); 2438 break; 2439 } 2440 case OMPRTL__tgt_target_data_begin: { 2441 // Build void __tgt_target_data_begin(int64_t device_id, int32_t arg_num, 2442 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2443 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2444 CGM.Int32Ty, 2445 CGM.VoidPtrPtrTy, 2446 CGM.VoidPtrPtrTy, 2447 CGM.Int64Ty->getPointerTo(), 2448 CGM.Int64Ty->getPointerTo()}; 2449 auto *FnTy = 2450 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2451 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin"); 2452 break; 2453 } 2454 case OMPRTL__tgt_target_data_begin_nowait: { 2455 // Build void __tgt_target_data_begin_nowait(int64_t device_id, int32_t 2456 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2457 // *arg_types); 2458 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2459 CGM.Int32Ty, 2460 CGM.VoidPtrPtrTy, 2461 CGM.VoidPtrPtrTy, 2462 CGM.Int64Ty->getPointerTo(), 2463 CGM.Int64Ty->getPointerTo()}; 2464 auto *FnTy = 2465 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2466 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_begin_nowait"); 2467 break; 2468 } 2469 case OMPRTL__tgt_target_data_end: { 2470 // Build void __tgt_target_data_end(int64_t device_id, int32_t arg_num, 2471 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2472 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2473 CGM.Int32Ty, 2474 CGM.VoidPtrPtrTy, 2475 CGM.VoidPtrPtrTy, 2476 CGM.Int64Ty->getPointerTo(), 2477 CGM.Int64Ty->getPointerTo()}; 2478 auto *FnTy = 2479 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2480 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end"); 2481 break; 2482 } 2483 case OMPRTL__tgt_target_data_end_nowait: { 2484 // Build void __tgt_target_data_end_nowait(int64_t device_id, int32_t 2485 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2486 // *arg_types); 2487 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2488 CGM.Int32Ty, 2489 CGM.VoidPtrPtrTy, 2490 CGM.VoidPtrPtrTy, 2491 CGM.Int64Ty->getPointerTo(), 2492 CGM.Int64Ty->getPointerTo()}; 2493 auto *FnTy = 2494 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2495 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_end_nowait"); 2496 break; 2497 } 2498 case OMPRTL__tgt_target_data_update: { 2499 // Build void __tgt_target_data_update(int64_t device_id, int32_t arg_num, 2500 // void** args_base, void **args, int64_t *arg_sizes, int64_t *arg_types); 2501 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2502 CGM.Int32Ty, 2503 CGM.VoidPtrPtrTy, 2504 CGM.VoidPtrPtrTy, 2505 CGM.Int64Ty->getPointerTo(), 2506 CGM.Int64Ty->getPointerTo()}; 2507 auto *FnTy = 2508 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2509 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update"); 2510 break; 2511 } 2512 case OMPRTL__tgt_target_data_update_nowait: { 2513 // Build void __tgt_target_data_update_nowait(int64_t device_id, int32_t 2514 // arg_num, void** args_base, void **args, int64_t *arg_sizes, int64_t 2515 // *arg_types); 2516 llvm::Type *TypeParams[] = {CGM.Int64Ty, 2517 CGM.Int32Ty, 2518 CGM.VoidPtrPtrTy, 2519 CGM.VoidPtrPtrTy, 2520 CGM.Int64Ty->getPointerTo(), 2521 CGM.Int64Ty->getPointerTo()}; 2522 auto *FnTy = 2523 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2524 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_target_data_update_nowait"); 2525 break; 2526 } 2527 case OMPRTL__tgt_mapper_num_components: { 2528 // Build int64_t __tgt_mapper_num_components(void *rt_mapper_handle); 2529 llvm::Type *TypeParams[] = {CGM.VoidPtrTy}; 2530 auto *FnTy = 2531 llvm::FunctionType::get(CGM.Int64Ty, TypeParams, /*isVarArg*/ false); 2532 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_mapper_num_components"); 2533 break; 2534 } 2535 case OMPRTL__tgt_push_mapper_component: { 2536 // Build void __tgt_push_mapper_component(void *rt_mapper_handle, void 2537 // *base, void *begin, int64_t size, int64_t type); 2538 llvm::Type *TypeParams[] = {CGM.VoidPtrTy, CGM.VoidPtrTy, CGM.VoidPtrTy, 2539 CGM.Int64Ty, CGM.Int64Ty}; 2540 auto *FnTy = 2541 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2542 RTLFn = CGM.CreateRuntimeFunction(FnTy, "__tgt_push_mapper_component"); 2543 break; 2544 } 2545 } 2546 assert(RTLFn && "Unable to find OpenMP runtime function"); 2547 return RTLFn; 2548 } 2549 2550 llvm::FunctionCallee 2551 CGOpenMPRuntime::createForStaticInitFunction(unsigned IVSize, bool IVSigned) { 2552 assert((IVSize == 32 || IVSize == 64) && 2553 "IV size is not compatible with the omp runtime"); 2554 StringRef Name = IVSize == 32 ? (IVSigned ? "__kmpc_for_static_init_4" 2555 : "__kmpc_for_static_init_4u") 2556 : (IVSigned ? "__kmpc_for_static_init_8" 2557 : "__kmpc_for_static_init_8u"); 2558 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2559 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2560 llvm::Type *TypeParams[] = { 2561 getIdentTyPointerTy(), // loc 2562 CGM.Int32Ty, // tid 2563 CGM.Int32Ty, // schedtype 2564 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2565 PtrTy, // p_lower 2566 PtrTy, // p_upper 2567 PtrTy, // p_stride 2568 ITy, // incr 2569 ITy // chunk 2570 }; 2571 auto *FnTy = 2572 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2573 return CGM.CreateRuntimeFunction(FnTy, Name); 2574 } 2575 2576 llvm::FunctionCallee 2577 CGOpenMPRuntime::createDispatchInitFunction(unsigned IVSize, bool IVSigned) { 2578 assert((IVSize == 32 || IVSize == 64) && 2579 "IV size is not compatible with the omp runtime"); 2580 StringRef Name = 2581 IVSize == 32 2582 ? (IVSigned ? "__kmpc_dispatch_init_4" : "__kmpc_dispatch_init_4u") 2583 : (IVSigned ? "__kmpc_dispatch_init_8" : "__kmpc_dispatch_init_8u"); 2584 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2585 llvm::Type *TypeParams[] = { getIdentTyPointerTy(), // loc 2586 CGM.Int32Ty, // tid 2587 CGM.Int32Ty, // schedtype 2588 ITy, // lower 2589 ITy, // upper 2590 ITy, // stride 2591 ITy // chunk 2592 }; 2593 auto *FnTy = 2594 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg*/ false); 2595 return CGM.CreateRuntimeFunction(FnTy, Name); 2596 } 2597 2598 llvm::FunctionCallee 2599 CGOpenMPRuntime::createDispatchFiniFunction(unsigned IVSize, bool IVSigned) { 2600 assert((IVSize == 32 || IVSize == 64) && 2601 "IV size is not compatible with the omp runtime"); 2602 StringRef Name = 2603 IVSize == 32 2604 ? (IVSigned ? "__kmpc_dispatch_fini_4" : "__kmpc_dispatch_fini_4u") 2605 : (IVSigned ? "__kmpc_dispatch_fini_8" : "__kmpc_dispatch_fini_8u"); 2606 llvm::Type *TypeParams[] = { 2607 getIdentTyPointerTy(), // loc 2608 CGM.Int32Ty, // tid 2609 }; 2610 auto *FnTy = 2611 llvm::FunctionType::get(CGM.VoidTy, TypeParams, /*isVarArg=*/false); 2612 return CGM.CreateRuntimeFunction(FnTy, Name); 2613 } 2614 2615 llvm::FunctionCallee 2616 CGOpenMPRuntime::createDispatchNextFunction(unsigned IVSize, bool IVSigned) { 2617 assert((IVSize == 32 || IVSize == 64) && 2618 "IV size is not compatible with the omp runtime"); 2619 StringRef Name = 2620 IVSize == 32 2621 ? (IVSigned ? "__kmpc_dispatch_next_4" : "__kmpc_dispatch_next_4u") 2622 : (IVSigned ? "__kmpc_dispatch_next_8" : "__kmpc_dispatch_next_8u"); 2623 llvm::Type *ITy = IVSize == 32 ? CGM.Int32Ty : CGM.Int64Ty; 2624 auto *PtrTy = llvm::PointerType::getUnqual(ITy); 2625 llvm::Type *TypeParams[] = { 2626 getIdentTyPointerTy(), // loc 2627 CGM.Int32Ty, // tid 2628 llvm::PointerType::getUnqual(CGM.Int32Ty), // p_lastiter 2629 PtrTy, // p_lower 2630 PtrTy, // p_upper 2631 PtrTy // p_stride 2632 }; 2633 auto *FnTy = 2634 llvm::FunctionType::get(CGM.Int32Ty, TypeParams, /*isVarArg*/ false); 2635 return CGM.CreateRuntimeFunction(FnTy, Name); 2636 } 2637 2638 /// Obtain information that uniquely identifies a target entry. This 2639 /// consists of the file and device IDs as well as line number associated with 2640 /// the relevant entry source location. 2641 static void getTargetEntryUniqueInfo(ASTContext &C, SourceLocation Loc, 2642 unsigned &DeviceID, unsigned &FileID, 2643 unsigned &LineNum) { 2644 SourceManager &SM = C.getSourceManager(); 2645 2646 // The loc should be always valid and have a file ID (the user cannot use 2647 // #pragma directives in macros) 2648 2649 assert(Loc.isValid() && "Source location is expected to be always valid."); 2650 2651 PresumedLoc PLoc = SM.getPresumedLoc(Loc); 2652 assert(PLoc.isValid() && "Source location is expected to be always valid."); 2653 2654 llvm::sys::fs::UniqueID ID; 2655 if (auto EC = llvm::sys::fs::getUniqueID(PLoc.getFilename(), ID)) 2656 SM.getDiagnostics().Report(diag::err_cannot_open_file) 2657 << PLoc.getFilename() << EC.message(); 2658 2659 DeviceID = ID.getDevice(); 2660 FileID = ID.getFile(); 2661 LineNum = PLoc.getLine(); 2662 } 2663 2664 Address CGOpenMPRuntime::getAddrOfDeclareTargetVar(const VarDecl *VD) { 2665 if (CGM.getLangOpts().OpenMPSimd) 2666 return Address::invalid(); 2667 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2668 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2669 if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || 2670 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2671 HasRequiresUnifiedSharedMemory))) { 2672 SmallString<64> PtrName; 2673 { 2674 llvm::raw_svector_ostream OS(PtrName); 2675 OS << CGM.getMangledName(GlobalDecl(VD)); 2676 if (!VD->isExternallyVisible()) { 2677 unsigned DeviceID, FileID, Line; 2678 getTargetEntryUniqueInfo(CGM.getContext(), 2679 VD->getCanonicalDecl()->getBeginLoc(), 2680 DeviceID, FileID, Line); 2681 OS << llvm::format("_%x", FileID); 2682 } 2683 OS << "_decl_tgt_ref_ptr"; 2684 } 2685 llvm::Value *Ptr = CGM.getModule().getNamedValue(PtrName); 2686 if (!Ptr) { 2687 QualType PtrTy = CGM.getContext().getPointerType(VD->getType()); 2688 Ptr = getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(PtrTy), 2689 PtrName); 2690 2691 auto *GV = cast<llvm::GlobalVariable>(Ptr); 2692 GV->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 2693 2694 if (!CGM.getLangOpts().OpenMPIsDevice) 2695 GV->setInitializer(CGM.GetAddrOfGlobal(VD)); 2696 registerTargetGlobalVariable(VD, cast<llvm::Constant>(Ptr)); 2697 } 2698 return Address(Ptr, CGM.getContext().getDeclAlign(VD)); 2699 } 2700 return Address::invalid(); 2701 } 2702 2703 llvm::Constant * 2704 CGOpenMPRuntime::getOrCreateThreadPrivateCache(const VarDecl *VD) { 2705 assert(!CGM.getLangOpts().OpenMPUseTLS || 2706 !CGM.getContext().getTargetInfo().isTLSSupported()); 2707 // Lookup the entry, lazily creating it if necessary. 2708 std::string Suffix = getName({"cache", ""}); 2709 return getOrCreateInternalVariable( 2710 CGM.Int8PtrPtrTy, Twine(CGM.getMangledName(VD)).concat(Suffix)); 2711 } 2712 2713 Address CGOpenMPRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 2714 const VarDecl *VD, 2715 Address VDAddr, 2716 SourceLocation Loc) { 2717 if (CGM.getLangOpts().OpenMPUseTLS && 2718 CGM.getContext().getTargetInfo().isTLSSupported()) 2719 return VDAddr; 2720 2721 llvm::Type *VarTy = VDAddr.getElementType(); 2722 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 2723 CGF.Builder.CreatePointerCast(VDAddr.getPointer(), 2724 CGM.Int8PtrTy), 2725 CGM.getSize(CGM.GetTargetTypeStoreSize(VarTy)), 2726 getOrCreateThreadPrivateCache(VD)}; 2727 return Address(CGF.EmitRuntimeCall( 2728 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 2729 VDAddr.getAlignment()); 2730 } 2731 2732 void CGOpenMPRuntime::emitThreadPrivateVarInit( 2733 CodeGenFunction &CGF, Address VDAddr, llvm::Value *Ctor, 2734 llvm::Value *CopyCtor, llvm::Value *Dtor, SourceLocation Loc) { 2735 // Call kmp_int32 __kmpc_global_thread_num(&loc) to init OpenMP runtime 2736 // library. 2737 llvm::Value *OMPLoc = emitUpdateLocation(CGF, Loc); 2738 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_global_thread_num), 2739 OMPLoc); 2740 // Call __kmpc_threadprivate_register(&loc, &var, ctor, cctor/*NULL*/, dtor) 2741 // to register constructor/destructor for variable. 2742 llvm::Value *Args[] = { 2743 OMPLoc, CGF.Builder.CreatePointerCast(VDAddr.getPointer(), CGM.VoidPtrTy), 2744 Ctor, CopyCtor, Dtor}; 2745 CGF.EmitRuntimeCall( 2746 createRuntimeFunction(OMPRTL__kmpc_threadprivate_register), Args); 2747 } 2748 2749 llvm::Function *CGOpenMPRuntime::emitThreadPrivateVarDefinition( 2750 const VarDecl *VD, Address VDAddr, SourceLocation Loc, 2751 bool PerformInit, CodeGenFunction *CGF) { 2752 if (CGM.getLangOpts().OpenMPUseTLS && 2753 CGM.getContext().getTargetInfo().isTLSSupported()) 2754 return nullptr; 2755 2756 VD = VD->getDefinition(CGM.getContext()); 2757 if (VD && ThreadPrivateWithDefinition.insert(CGM.getMangledName(VD)).second) { 2758 QualType ASTTy = VD->getType(); 2759 2760 llvm::Value *Ctor = nullptr, *CopyCtor = nullptr, *Dtor = nullptr; 2761 const Expr *Init = VD->getAnyInitializer(); 2762 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2763 // Generate function that re-emits the declaration's initializer into the 2764 // threadprivate copy of the variable VD 2765 CodeGenFunction CtorCGF(CGM); 2766 FunctionArgList Args; 2767 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2768 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2769 ImplicitParamDecl::Other); 2770 Args.push_back(&Dst); 2771 2772 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2773 CGM.getContext().VoidPtrTy, Args); 2774 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2775 std::string Name = getName({"__kmpc_global_ctor_", ""}); 2776 llvm::Function *Fn = 2777 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2778 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidPtrTy, Fn, FI, 2779 Args, Loc, Loc); 2780 llvm::Value *ArgVal = CtorCGF.EmitLoadOfScalar( 2781 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2782 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2783 Address Arg = Address(ArgVal, VDAddr.getAlignment()); 2784 Arg = CtorCGF.Builder.CreateElementBitCast( 2785 Arg, CtorCGF.ConvertTypeForMem(ASTTy)); 2786 CtorCGF.EmitAnyExprToMem(Init, Arg, Init->getType().getQualifiers(), 2787 /*IsInitializer=*/true); 2788 ArgVal = CtorCGF.EmitLoadOfScalar( 2789 CtorCGF.GetAddrOfLocalVar(&Dst), /*Volatile=*/false, 2790 CGM.getContext().VoidPtrTy, Dst.getLocation()); 2791 CtorCGF.Builder.CreateStore(ArgVal, CtorCGF.ReturnValue); 2792 CtorCGF.FinishFunction(); 2793 Ctor = Fn; 2794 } 2795 if (VD->getType().isDestructedType() != QualType::DK_none) { 2796 // Generate function that emits destructor call for the threadprivate copy 2797 // of the variable VD 2798 CodeGenFunction DtorCGF(CGM); 2799 FunctionArgList Args; 2800 ImplicitParamDecl Dst(CGM.getContext(), /*DC=*/nullptr, Loc, 2801 /*Id=*/nullptr, CGM.getContext().VoidPtrTy, 2802 ImplicitParamDecl::Other); 2803 Args.push_back(&Dst); 2804 2805 const auto &FI = CGM.getTypes().arrangeBuiltinFunctionDeclaration( 2806 CGM.getContext().VoidTy, Args); 2807 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2808 std::string Name = getName({"__kmpc_global_dtor_", ""}); 2809 llvm::Function *Fn = 2810 CGM.CreateGlobalInitOrDestructFunction(FTy, Name, FI, Loc); 2811 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2812 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, Args, 2813 Loc, Loc); 2814 // Create a scope with an artificial location for the body of this function. 2815 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2816 llvm::Value *ArgVal = DtorCGF.EmitLoadOfScalar( 2817 DtorCGF.GetAddrOfLocalVar(&Dst), 2818 /*Volatile=*/false, CGM.getContext().VoidPtrTy, Dst.getLocation()); 2819 DtorCGF.emitDestroy(Address(ArgVal, VDAddr.getAlignment()), ASTTy, 2820 DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2821 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2822 DtorCGF.FinishFunction(); 2823 Dtor = Fn; 2824 } 2825 // Do not emit init function if it is not required. 2826 if (!Ctor && !Dtor) 2827 return nullptr; 2828 2829 llvm::Type *CopyCtorTyArgs[] = {CGM.VoidPtrTy, CGM.VoidPtrTy}; 2830 auto *CopyCtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CopyCtorTyArgs, 2831 /*isVarArg=*/false) 2832 ->getPointerTo(); 2833 // Copying constructor for the threadprivate variable. 2834 // Must be NULL - reserved by runtime, but currently it requires that this 2835 // parameter is always NULL. Otherwise it fires assertion. 2836 CopyCtor = llvm::Constant::getNullValue(CopyCtorTy); 2837 if (Ctor == nullptr) { 2838 auto *CtorTy = llvm::FunctionType::get(CGM.VoidPtrTy, CGM.VoidPtrTy, 2839 /*isVarArg=*/false) 2840 ->getPointerTo(); 2841 Ctor = llvm::Constant::getNullValue(CtorTy); 2842 } 2843 if (Dtor == nullptr) { 2844 auto *DtorTy = llvm::FunctionType::get(CGM.VoidTy, CGM.VoidPtrTy, 2845 /*isVarArg=*/false) 2846 ->getPointerTo(); 2847 Dtor = llvm::Constant::getNullValue(DtorTy); 2848 } 2849 if (!CGF) { 2850 auto *InitFunctionTy = 2851 llvm::FunctionType::get(CGM.VoidTy, /*isVarArg*/ false); 2852 std::string Name = getName({"__omp_threadprivate_init_", ""}); 2853 llvm::Function *InitFunction = CGM.CreateGlobalInitOrDestructFunction( 2854 InitFunctionTy, Name, CGM.getTypes().arrangeNullaryFunction()); 2855 CodeGenFunction InitCGF(CGM); 2856 FunctionArgList ArgList; 2857 InitCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, InitFunction, 2858 CGM.getTypes().arrangeNullaryFunction(), ArgList, 2859 Loc, Loc); 2860 emitThreadPrivateVarInit(InitCGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2861 InitCGF.FinishFunction(); 2862 return InitFunction; 2863 } 2864 emitThreadPrivateVarInit(*CGF, VDAddr, Ctor, CopyCtor, Dtor, Loc); 2865 } 2866 return nullptr; 2867 } 2868 2869 bool CGOpenMPRuntime::emitDeclareTargetVarDefinition(const VarDecl *VD, 2870 llvm::GlobalVariable *Addr, 2871 bool PerformInit) { 2872 if (CGM.getLangOpts().OMPTargetTriples.empty() && 2873 !CGM.getLangOpts().OpenMPIsDevice) 2874 return false; 2875 Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 2876 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 2877 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 2878 (*Res == OMPDeclareTargetDeclAttr::MT_To && 2879 HasRequiresUnifiedSharedMemory)) 2880 return CGM.getLangOpts().OpenMPIsDevice; 2881 VD = VD->getDefinition(CGM.getContext()); 2882 if (VD && !DeclareTargetWithDefinition.insert(CGM.getMangledName(VD)).second) 2883 return CGM.getLangOpts().OpenMPIsDevice; 2884 2885 QualType ASTTy = VD->getType(); 2886 2887 SourceLocation Loc = VD->getCanonicalDecl()->getBeginLoc(); 2888 // Produce the unique prefix to identify the new target regions. We use 2889 // the source location of the variable declaration which we know to not 2890 // conflict with any target region. 2891 unsigned DeviceID; 2892 unsigned FileID; 2893 unsigned Line; 2894 getTargetEntryUniqueInfo(CGM.getContext(), Loc, DeviceID, FileID, Line); 2895 SmallString<128> Buffer, Out; 2896 { 2897 llvm::raw_svector_ostream OS(Buffer); 2898 OS << "__omp_offloading_" << llvm::format("_%x", DeviceID) 2899 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 2900 } 2901 2902 const Expr *Init = VD->getAnyInitializer(); 2903 if (CGM.getLangOpts().CPlusPlus && PerformInit) { 2904 llvm::Constant *Ctor; 2905 llvm::Constant *ID; 2906 if (CGM.getLangOpts().OpenMPIsDevice) { 2907 // Generate function that re-emits the declaration's initializer into 2908 // the threadprivate copy of the variable VD 2909 CodeGenFunction CtorCGF(CGM); 2910 2911 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2912 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2913 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2914 FTy, Twine(Buffer, "_ctor"), FI, Loc); 2915 auto NL = ApplyDebugLocation::CreateEmpty(CtorCGF); 2916 CtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2917 FunctionArgList(), Loc, Loc); 2918 auto AL = ApplyDebugLocation::CreateArtificial(CtorCGF); 2919 CtorCGF.EmitAnyExprToMem(Init, 2920 Address(Addr, CGM.getContext().getDeclAlign(VD)), 2921 Init->getType().getQualifiers(), 2922 /*IsInitializer=*/true); 2923 CtorCGF.FinishFunction(); 2924 Ctor = Fn; 2925 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2926 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Ctor)); 2927 } else { 2928 Ctor = new llvm::GlobalVariable( 2929 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2930 llvm::GlobalValue::PrivateLinkage, 2931 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_ctor")); 2932 ID = Ctor; 2933 } 2934 2935 // Register the information for the entry associated with the constructor. 2936 Out.clear(); 2937 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2938 DeviceID, FileID, Twine(Buffer, "_ctor").toStringRef(Out), Line, Ctor, 2939 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryCtor); 2940 } 2941 if (VD->getType().isDestructedType() != QualType::DK_none) { 2942 llvm::Constant *Dtor; 2943 llvm::Constant *ID; 2944 if (CGM.getLangOpts().OpenMPIsDevice) { 2945 // Generate function that emits destructor call for the threadprivate 2946 // copy of the variable VD 2947 CodeGenFunction DtorCGF(CGM); 2948 2949 const CGFunctionInfo &FI = CGM.getTypes().arrangeNullaryFunction(); 2950 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 2951 llvm::Function *Fn = CGM.CreateGlobalInitOrDestructFunction( 2952 FTy, Twine(Buffer, "_dtor"), FI, Loc); 2953 auto NL = ApplyDebugLocation::CreateEmpty(DtorCGF); 2954 DtorCGF.StartFunction(GlobalDecl(), CGM.getContext().VoidTy, Fn, FI, 2955 FunctionArgList(), Loc, Loc); 2956 // Create a scope with an artificial location for the body of this 2957 // function. 2958 auto AL = ApplyDebugLocation::CreateArtificial(DtorCGF); 2959 DtorCGF.emitDestroy(Address(Addr, CGM.getContext().getDeclAlign(VD)), 2960 ASTTy, DtorCGF.getDestroyer(ASTTy.isDestructedType()), 2961 DtorCGF.needsEHCleanup(ASTTy.isDestructedType())); 2962 DtorCGF.FinishFunction(); 2963 Dtor = Fn; 2964 ID = llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 2965 CGM.addUsedGlobal(cast<llvm::GlobalValue>(Dtor)); 2966 } else { 2967 Dtor = new llvm::GlobalVariable( 2968 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 2969 llvm::GlobalValue::PrivateLinkage, 2970 llvm::Constant::getNullValue(CGM.Int8Ty), Twine(Buffer, "_dtor")); 2971 ID = Dtor; 2972 } 2973 // Register the information for the entry associated with the destructor. 2974 Out.clear(); 2975 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 2976 DeviceID, FileID, Twine(Buffer, "_dtor").toStringRef(Out), Line, Dtor, 2977 ID, OffloadEntriesInfoManagerTy::OMPTargetRegionEntryDtor); 2978 } 2979 return CGM.getLangOpts().OpenMPIsDevice; 2980 } 2981 2982 Address CGOpenMPRuntime::getAddrOfArtificialThreadPrivate(CodeGenFunction &CGF, 2983 QualType VarType, 2984 StringRef Name) { 2985 std::string Suffix = getName({"artificial", ""}); 2986 std::string CacheSuffix = getName({"cache", ""}); 2987 llvm::Type *VarLVType = CGF.ConvertTypeForMem(VarType); 2988 llvm::Value *GAddr = 2989 getOrCreateInternalVariable(VarLVType, Twine(Name).concat(Suffix)); 2990 llvm::Value *Args[] = { 2991 emitUpdateLocation(CGF, SourceLocation()), 2992 getThreadID(CGF, SourceLocation()), 2993 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(GAddr, CGM.VoidPtrTy), 2994 CGF.Builder.CreateIntCast(CGF.getTypeSize(VarType), CGM.SizeTy, 2995 /*isSigned=*/false), 2996 getOrCreateInternalVariable( 2997 CGM.VoidPtrPtrTy, Twine(Name).concat(Suffix).concat(CacheSuffix))}; 2998 return Address( 2999 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3000 CGF.EmitRuntimeCall( 3001 createRuntimeFunction(OMPRTL__kmpc_threadprivate_cached), Args), 3002 VarLVType->getPointerTo(/*AddrSpace=*/0)), 3003 CGM.getPointerAlign()); 3004 } 3005 3006 void CGOpenMPRuntime::emitOMPIfClause(CodeGenFunction &CGF, const Expr *Cond, 3007 const RegionCodeGenTy &ThenGen, 3008 const RegionCodeGenTy &ElseGen) { 3009 CodeGenFunction::LexicalScope ConditionScope(CGF, Cond->getSourceRange()); 3010 3011 // If the condition constant folds and can be elided, try to avoid emitting 3012 // the condition and the dead arm of the if/else. 3013 bool CondConstant; 3014 if (CGF.ConstantFoldsToSimpleInteger(Cond, CondConstant)) { 3015 if (CondConstant) 3016 ThenGen(CGF); 3017 else 3018 ElseGen(CGF); 3019 return; 3020 } 3021 3022 // Otherwise, the condition did not fold, or we couldn't elide it. Just 3023 // emit the conditional branch. 3024 llvm::BasicBlock *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3025 llvm::BasicBlock *ElseBlock = CGF.createBasicBlock("omp_if.else"); 3026 llvm::BasicBlock *ContBlock = CGF.createBasicBlock("omp_if.end"); 3027 CGF.EmitBranchOnBoolExpr(Cond, ThenBlock, ElseBlock, /*TrueCount=*/0); 3028 3029 // Emit the 'then' code. 3030 CGF.EmitBlock(ThenBlock); 3031 ThenGen(CGF); 3032 CGF.EmitBranch(ContBlock); 3033 // Emit the 'else' code if present. 3034 // There is no need to emit line number for unconditional branch. 3035 (void)ApplyDebugLocation::CreateEmpty(CGF); 3036 CGF.EmitBlock(ElseBlock); 3037 ElseGen(CGF); 3038 // There is no need to emit line number for unconditional branch. 3039 (void)ApplyDebugLocation::CreateEmpty(CGF); 3040 CGF.EmitBranch(ContBlock); 3041 // Emit the continuation block for code after the if. 3042 CGF.EmitBlock(ContBlock, /*IsFinished=*/true); 3043 } 3044 3045 void CGOpenMPRuntime::emitParallelCall(CodeGenFunction &CGF, SourceLocation Loc, 3046 llvm::Function *OutlinedFn, 3047 ArrayRef<llvm::Value *> CapturedVars, 3048 const Expr *IfCond) { 3049 if (!CGF.HaveInsertPoint()) 3050 return; 3051 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 3052 auto &&ThenGen = [OutlinedFn, CapturedVars, RTLoc](CodeGenFunction &CGF, 3053 PrePostActionTy &) { 3054 // Build call __kmpc_fork_call(loc, n, microtask, var1, .., varn); 3055 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3056 llvm::Value *Args[] = { 3057 RTLoc, 3058 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 3059 CGF.Builder.CreateBitCast(OutlinedFn, RT.getKmpc_MicroPointerTy())}; 3060 llvm::SmallVector<llvm::Value *, 16> RealArgs; 3061 RealArgs.append(std::begin(Args), std::end(Args)); 3062 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 3063 3064 llvm::FunctionCallee RTLFn = 3065 RT.createRuntimeFunction(OMPRTL__kmpc_fork_call); 3066 CGF.EmitRuntimeCall(RTLFn, RealArgs); 3067 }; 3068 auto &&ElseGen = [OutlinedFn, CapturedVars, RTLoc, Loc](CodeGenFunction &CGF, 3069 PrePostActionTy &) { 3070 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 3071 llvm::Value *ThreadID = RT.getThreadID(CGF, Loc); 3072 // Build calls: 3073 // __kmpc_serialized_parallel(&Loc, GTid); 3074 llvm::Value *Args[] = {RTLoc, ThreadID}; 3075 CGF.EmitRuntimeCall( 3076 RT.createRuntimeFunction(OMPRTL__kmpc_serialized_parallel), Args); 3077 3078 // OutlinedFn(>id, &zero, CapturedStruct); 3079 Address ZeroAddr = CGF.CreateDefaultAlignTempAlloca(CGF.Int32Ty, 3080 /*Name*/ ".zero.addr"); 3081 CGF.InitTempAlloca(ZeroAddr, CGF.Builder.getInt32(/*C*/ 0)); 3082 llvm::SmallVector<llvm::Value *, 16> OutlinedFnArgs; 3083 // ThreadId for serialized parallels is 0. 3084 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 3085 OutlinedFnArgs.push_back(ZeroAddr.getPointer()); 3086 OutlinedFnArgs.append(CapturedVars.begin(), CapturedVars.end()); 3087 RT.emitOutlinedFunctionCall(CGF, Loc, OutlinedFn, OutlinedFnArgs); 3088 3089 // __kmpc_end_serialized_parallel(&Loc, GTid); 3090 llvm::Value *EndArgs[] = {RT.emitUpdateLocation(CGF, Loc), ThreadID}; 3091 CGF.EmitRuntimeCall( 3092 RT.createRuntimeFunction(OMPRTL__kmpc_end_serialized_parallel), 3093 EndArgs); 3094 }; 3095 if (IfCond) { 3096 emitOMPIfClause(CGF, IfCond, ThenGen, ElseGen); 3097 } else { 3098 RegionCodeGenTy ThenRCG(ThenGen); 3099 ThenRCG(CGF); 3100 } 3101 } 3102 3103 // If we're inside an (outlined) parallel region, use the region info's 3104 // thread-ID variable (it is passed in a first argument of the outlined function 3105 // as "kmp_int32 *gtid"). Otherwise, if we're not inside parallel region, but in 3106 // regular serial code region, get thread ID by calling kmp_int32 3107 // kmpc_global_thread_num(ident_t *loc), stash this thread ID in a temporary and 3108 // return the address of that temp. 3109 Address CGOpenMPRuntime::emitThreadIDAddress(CodeGenFunction &CGF, 3110 SourceLocation Loc) { 3111 if (auto *OMPRegionInfo = 3112 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3113 if (OMPRegionInfo->getThreadIDVariable()) 3114 return OMPRegionInfo->getThreadIDVariableLValue(CGF).getAddress(); 3115 3116 llvm::Value *ThreadID = getThreadID(CGF, Loc); 3117 QualType Int32Ty = 3118 CGF.getContext().getIntTypeForBitwidth(/*DestWidth*/ 32, /*Signed*/ true); 3119 Address ThreadIDTemp = CGF.CreateMemTemp(Int32Ty, /*Name*/ ".threadid_temp."); 3120 CGF.EmitStoreOfScalar(ThreadID, 3121 CGF.MakeAddrLValue(ThreadIDTemp, Int32Ty)); 3122 3123 return ThreadIDTemp; 3124 } 3125 3126 llvm::Constant *CGOpenMPRuntime::getOrCreateInternalVariable( 3127 llvm::Type *Ty, const llvm::Twine &Name, unsigned AddressSpace) { 3128 SmallString<256> Buffer; 3129 llvm::raw_svector_ostream Out(Buffer); 3130 Out << Name; 3131 StringRef RuntimeName = Out.str(); 3132 auto &Elem = *InternalVars.try_emplace(RuntimeName, nullptr).first; 3133 if (Elem.second) { 3134 assert(Elem.second->getType()->getPointerElementType() == Ty && 3135 "OMP internal variable has different type than requested"); 3136 return &*Elem.second; 3137 } 3138 3139 return Elem.second = new llvm::GlobalVariable( 3140 CGM.getModule(), Ty, /*IsConstant*/ false, 3141 llvm::GlobalValue::CommonLinkage, llvm::Constant::getNullValue(Ty), 3142 Elem.first(), /*InsertBefore=*/nullptr, 3143 llvm::GlobalValue::NotThreadLocal, AddressSpace); 3144 } 3145 3146 llvm::Value *CGOpenMPRuntime::getCriticalRegionLock(StringRef CriticalName) { 3147 std::string Prefix = Twine("gomp_critical_user_", CriticalName).str(); 3148 std::string Name = getName({Prefix, "var"}); 3149 return getOrCreateInternalVariable(KmpCriticalNameTy, Name); 3150 } 3151 3152 namespace { 3153 /// Common pre(post)-action for different OpenMP constructs. 3154 class CommonActionTy final : public PrePostActionTy { 3155 llvm::FunctionCallee EnterCallee; 3156 ArrayRef<llvm::Value *> EnterArgs; 3157 llvm::FunctionCallee ExitCallee; 3158 ArrayRef<llvm::Value *> ExitArgs; 3159 bool Conditional; 3160 llvm::BasicBlock *ContBlock = nullptr; 3161 3162 public: 3163 CommonActionTy(llvm::FunctionCallee EnterCallee, 3164 ArrayRef<llvm::Value *> EnterArgs, 3165 llvm::FunctionCallee ExitCallee, 3166 ArrayRef<llvm::Value *> ExitArgs, bool Conditional = false) 3167 : EnterCallee(EnterCallee), EnterArgs(EnterArgs), ExitCallee(ExitCallee), 3168 ExitArgs(ExitArgs), Conditional(Conditional) {} 3169 void Enter(CodeGenFunction &CGF) override { 3170 llvm::Value *EnterRes = CGF.EmitRuntimeCall(EnterCallee, EnterArgs); 3171 if (Conditional) { 3172 llvm::Value *CallBool = CGF.Builder.CreateIsNotNull(EnterRes); 3173 auto *ThenBlock = CGF.createBasicBlock("omp_if.then"); 3174 ContBlock = CGF.createBasicBlock("omp_if.end"); 3175 // Generate the branch (If-stmt) 3176 CGF.Builder.CreateCondBr(CallBool, ThenBlock, ContBlock); 3177 CGF.EmitBlock(ThenBlock); 3178 } 3179 } 3180 void Done(CodeGenFunction &CGF) { 3181 // Emit the rest of blocks/branches 3182 CGF.EmitBranch(ContBlock); 3183 CGF.EmitBlock(ContBlock, true); 3184 } 3185 void Exit(CodeGenFunction &CGF) override { 3186 CGF.EmitRuntimeCall(ExitCallee, ExitArgs); 3187 } 3188 }; 3189 } // anonymous namespace 3190 3191 void CGOpenMPRuntime::emitCriticalRegion(CodeGenFunction &CGF, 3192 StringRef CriticalName, 3193 const RegionCodeGenTy &CriticalOpGen, 3194 SourceLocation Loc, const Expr *Hint) { 3195 // __kmpc_critical[_with_hint](ident_t *, gtid, Lock[, hint]); 3196 // CriticalOpGen(); 3197 // __kmpc_end_critical(ident_t *, gtid, Lock); 3198 // Prepare arguments and build a call to __kmpc_critical 3199 if (!CGF.HaveInsertPoint()) 3200 return; 3201 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3202 getCriticalRegionLock(CriticalName)}; 3203 llvm::SmallVector<llvm::Value *, 4> EnterArgs(std::begin(Args), 3204 std::end(Args)); 3205 if (Hint) { 3206 EnterArgs.push_back(CGF.Builder.CreateIntCast( 3207 CGF.EmitScalarExpr(Hint), CGM.IntPtrTy, /*isSigned=*/false)); 3208 } 3209 CommonActionTy Action( 3210 createRuntimeFunction(Hint ? OMPRTL__kmpc_critical_with_hint 3211 : OMPRTL__kmpc_critical), 3212 EnterArgs, createRuntimeFunction(OMPRTL__kmpc_end_critical), Args); 3213 CriticalOpGen.setAction(Action); 3214 emitInlinedDirective(CGF, OMPD_critical, CriticalOpGen); 3215 } 3216 3217 void CGOpenMPRuntime::emitMasterRegion(CodeGenFunction &CGF, 3218 const RegionCodeGenTy &MasterOpGen, 3219 SourceLocation Loc) { 3220 if (!CGF.HaveInsertPoint()) 3221 return; 3222 // if(__kmpc_master(ident_t *, gtid)) { 3223 // MasterOpGen(); 3224 // __kmpc_end_master(ident_t *, gtid); 3225 // } 3226 // Prepare arguments and build a call to __kmpc_master 3227 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3228 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_master), Args, 3229 createRuntimeFunction(OMPRTL__kmpc_end_master), Args, 3230 /*Conditional=*/true); 3231 MasterOpGen.setAction(Action); 3232 emitInlinedDirective(CGF, OMPD_master, MasterOpGen); 3233 Action.Done(CGF); 3234 } 3235 3236 void CGOpenMPRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 3237 SourceLocation Loc) { 3238 if (!CGF.HaveInsertPoint()) 3239 return; 3240 // Build call __kmpc_omp_taskyield(loc, thread_id, 0); 3241 llvm::Value *Args[] = { 3242 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3243 llvm::ConstantInt::get(CGM.IntTy, /*V=*/0, /*isSigned=*/true)}; 3244 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskyield), Args); 3245 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 3246 Region->emitUntiedSwitch(CGF); 3247 } 3248 3249 void CGOpenMPRuntime::emitTaskgroupRegion(CodeGenFunction &CGF, 3250 const RegionCodeGenTy &TaskgroupOpGen, 3251 SourceLocation Loc) { 3252 if (!CGF.HaveInsertPoint()) 3253 return; 3254 // __kmpc_taskgroup(ident_t *, gtid); 3255 // TaskgroupOpGen(); 3256 // __kmpc_end_taskgroup(ident_t *, gtid); 3257 // Prepare arguments and build a call to __kmpc_taskgroup 3258 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3259 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_taskgroup), Args, 3260 createRuntimeFunction(OMPRTL__kmpc_end_taskgroup), 3261 Args); 3262 TaskgroupOpGen.setAction(Action); 3263 emitInlinedDirective(CGF, OMPD_taskgroup, TaskgroupOpGen); 3264 } 3265 3266 /// Given an array of pointers to variables, project the address of a 3267 /// given variable. 3268 static Address emitAddrOfVarFromArray(CodeGenFunction &CGF, Address Array, 3269 unsigned Index, const VarDecl *Var) { 3270 // Pull out the pointer to the variable. 3271 Address PtrAddr = CGF.Builder.CreateConstArrayGEP(Array, Index); 3272 llvm::Value *Ptr = CGF.Builder.CreateLoad(PtrAddr); 3273 3274 Address Addr = Address(Ptr, CGF.getContext().getDeclAlign(Var)); 3275 Addr = CGF.Builder.CreateElementBitCast( 3276 Addr, CGF.ConvertTypeForMem(Var->getType())); 3277 return Addr; 3278 } 3279 3280 static llvm::Value *emitCopyprivateCopyFunction( 3281 CodeGenModule &CGM, llvm::Type *ArgsType, 3282 ArrayRef<const Expr *> CopyprivateVars, ArrayRef<const Expr *> DestExprs, 3283 ArrayRef<const Expr *> SrcExprs, ArrayRef<const Expr *> AssignmentOps, 3284 SourceLocation Loc) { 3285 ASTContext &C = CGM.getContext(); 3286 // void copy_func(void *LHSArg, void *RHSArg); 3287 FunctionArgList Args; 3288 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3289 ImplicitParamDecl::Other); 3290 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 3291 ImplicitParamDecl::Other); 3292 Args.push_back(&LHSArg); 3293 Args.push_back(&RHSArg); 3294 const auto &CGFI = 3295 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 3296 std::string Name = 3297 CGM.getOpenMPRuntime().getName({"omp", "copyprivate", "copy_func"}); 3298 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 3299 llvm::GlobalValue::InternalLinkage, Name, 3300 &CGM.getModule()); 3301 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 3302 Fn->setDoesNotRecurse(); 3303 CodeGenFunction CGF(CGM); 3304 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 3305 // Dest = (void*[n])(LHSArg); 3306 // Src = (void*[n])(RHSArg); 3307 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3308 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 3309 ArgsType), CGF.getPointerAlign()); 3310 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3311 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 3312 ArgsType), CGF.getPointerAlign()); 3313 // *(Type0*)Dst[0] = *(Type0*)Src[0]; 3314 // *(Type1*)Dst[1] = *(Type1*)Src[1]; 3315 // ... 3316 // *(Typen*)Dst[n] = *(Typen*)Src[n]; 3317 for (unsigned I = 0, E = AssignmentOps.size(); I < E; ++I) { 3318 const auto *DestVar = 3319 cast<VarDecl>(cast<DeclRefExpr>(DestExprs[I])->getDecl()); 3320 Address DestAddr = emitAddrOfVarFromArray(CGF, LHS, I, DestVar); 3321 3322 const auto *SrcVar = 3323 cast<VarDecl>(cast<DeclRefExpr>(SrcExprs[I])->getDecl()); 3324 Address SrcAddr = emitAddrOfVarFromArray(CGF, RHS, I, SrcVar); 3325 3326 const auto *VD = cast<DeclRefExpr>(CopyprivateVars[I])->getDecl(); 3327 QualType Type = VD->getType(); 3328 CGF.EmitOMPCopy(Type, DestAddr, SrcAddr, DestVar, SrcVar, AssignmentOps[I]); 3329 } 3330 CGF.FinishFunction(); 3331 return Fn; 3332 } 3333 3334 void CGOpenMPRuntime::emitSingleRegion(CodeGenFunction &CGF, 3335 const RegionCodeGenTy &SingleOpGen, 3336 SourceLocation Loc, 3337 ArrayRef<const Expr *> CopyprivateVars, 3338 ArrayRef<const Expr *> SrcExprs, 3339 ArrayRef<const Expr *> DstExprs, 3340 ArrayRef<const Expr *> AssignmentOps) { 3341 if (!CGF.HaveInsertPoint()) 3342 return; 3343 assert(CopyprivateVars.size() == SrcExprs.size() && 3344 CopyprivateVars.size() == DstExprs.size() && 3345 CopyprivateVars.size() == AssignmentOps.size()); 3346 ASTContext &C = CGM.getContext(); 3347 // int32 did_it = 0; 3348 // if(__kmpc_single(ident_t *, gtid)) { 3349 // SingleOpGen(); 3350 // __kmpc_end_single(ident_t *, gtid); 3351 // did_it = 1; 3352 // } 3353 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3354 // <copy_func>, did_it); 3355 3356 Address DidIt = Address::invalid(); 3357 if (!CopyprivateVars.empty()) { 3358 // int32 did_it = 0; 3359 QualType KmpInt32Ty = 3360 C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 3361 DidIt = CGF.CreateMemTemp(KmpInt32Ty, ".omp.copyprivate.did_it"); 3362 CGF.Builder.CreateStore(CGF.Builder.getInt32(0), DidIt); 3363 } 3364 // Prepare arguments and build a call to __kmpc_single 3365 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3366 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_single), Args, 3367 createRuntimeFunction(OMPRTL__kmpc_end_single), Args, 3368 /*Conditional=*/true); 3369 SingleOpGen.setAction(Action); 3370 emitInlinedDirective(CGF, OMPD_single, SingleOpGen); 3371 if (DidIt.isValid()) { 3372 // did_it = 1; 3373 CGF.Builder.CreateStore(CGF.Builder.getInt32(1), DidIt); 3374 } 3375 Action.Done(CGF); 3376 // call __kmpc_copyprivate(ident_t *, gtid, <buf_size>, <copyprivate list>, 3377 // <copy_func>, did_it); 3378 if (DidIt.isValid()) { 3379 llvm::APInt ArraySize(/*unsigned int numBits=*/32, CopyprivateVars.size()); 3380 QualType CopyprivateArrayTy = C.getConstantArrayType( 3381 C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 3382 /*IndexTypeQuals=*/0); 3383 // Create a list of all private variables for copyprivate. 3384 Address CopyprivateList = 3385 CGF.CreateMemTemp(CopyprivateArrayTy, ".omp.copyprivate.cpr_list"); 3386 for (unsigned I = 0, E = CopyprivateVars.size(); I < E; ++I) { 3387 Address Elem = CGF.Builder.CreateConstArrayGEP(CopyprivateList, I); 3388 CGF.Builder.CreateStore( 3389 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 3390 CGF.EmitLValue(CopyprivateVars[I]).getPointer(), CGF.VoidPtrTy), 3391 Elem); 3392 } 3393 // Build function that copies private values from single region to all other 3394 // threads in the corresponding parallel region. 3395 llvm::Value *CpyFn = emitCopyprivateCopyFunction( 3396 CGM, CGF.ConvertTypeForMem(CopyprivateArrayTy)->getPointerTo(), 3397 CopyprivateVars, SrcExprs, DstExprs, AssignmentOps, Loc); 3398 llvm::Value *BufSize = CGF.getTypeSize(CopyprivateArrayTy); 3399 Address CL = 3400 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(CopyprivateList, 3401 CGF.VoidPtrTy); 3402 llvm::Value *DidItVal = CGF.Builder.CreateLoad(DidIt); 3403 llvm::Value *Args[] = { 3404 emitUpdateLocation(CGF, Loc), // ident_t *<loc> 3405 getThreadID(CGF, Loc), // i32 <gtid> 3406 BufSize, // size_t <buf_size> 3407 CL.getPointer(), // void *<copyprivate list> 3408 CpyFn, // void (*) (void *, void *) <copy_func> 3409 DidItVal // i32 did_it 3410 }; 3411 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_copyprivate), Args); 3412 } 3413 } 3414 3415 void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF, 3416 const RegionCodeGenTy &OrderedOpGen, 3417 SourceLocation Loc, bool IsThreads) { 3418 if (!CGF.HaveInsertPoint()) 3419 return; 3420 // __kmpc_ordered(ident_t *, gtid); 3421 // OrderedOpGen(); 3422 // __kmpc_end_ordered(ident_t *, gtid); 3423 // Prepare arguments and build a call to __kmpc_ordered 3424 if (IsThreads) { 3425 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3426 CommonActionTy Action(createRuntimeFunction(OMPRTL__kmpc_ordered), Args, 3427 createRuntimeFunction(OMPRTL__kmpc_end_ordered), 3428 Args); 3429 OrderedOpGen.setAction(Action); 3430 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3431 return; 3432 } 3433 emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen); 3434 } 3435 3436 unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) { 3437 unsigned Flags; 3438 if (Kind == OMPD_for) 3439 Flags = OMP_IDENT_BARRIER_IMPL_FOR; 3440 else if (Kind == OMPD_sections) 3441 Flags = OMP_IDENT_BARRIER_IMPL_SECTIONS; 3442 else if (Kind == OMPD_single) 3443 Flags = OMP_IDENT_BARRIER_IMPL_SINGLE; 3444 else if (Kind == OMPD_barrier) 3445 Flags = OMP_IDENT_BARRIER_EXPL; 3446 else 3447 Flags = OMP_IDENT_BARRIER_IMPL; 3448 return Flags; 3449 } 3450 3451 void CGOpenMPRuntime::getDefaultScheduleAndChunk( 3452 CodeGenFunction &CGF, const OMPLoopDirective &S, 3453 OpenMPScheduleClauseKind &ScheduleKind, const Expr *&ChunkExpr) const { 3454 // Check if the loop directive is actually a doacross loop directive. In this 3455 // case choose static, 1 schedule. 3456 if (llvm::any_of( 3457 S.getClausesOfKind<OMPOrderedClause>(), 3458 [](const OMPOrderedClause *C) { return C->getNumForLoops(); })) { 3459 ScheduleKind = OMPC_SCHEDULE_static; 3460 // Chunk size is 1 in this case. 3461 llvm::APInt ChunkSize(32, 1); 3462 ChunkExpr = IntegerLiteral::Create( 3463 CGF.getContext(), ChunkSize, 3464 CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/0), 3465 SourceLocation()); 3466 } 3467 } 3468 3469 void CGOpenMPRuntime::emitBarrierCall(CodeGenFunction &CGF, SourceLocation Loc, 3470 OpenMPDirectiveKind Kind, bool EmitChecks, 3471 bool ForceSimpleCall) { 3472 if (!CGF.HaveInsertPoint()) 3473 return; 3474 // Build call __kmpc_cancel_barrier(loc, thread_id); 3475 // Build call __kmpc_barrier(loc, thread_id); 3476 unsigned Flags = getDefaultFlagsForBarriers(Kind); 3477 // Build call __kmpc_cancel_barrier(loc, thread_id) or __kmpc_barrier(loc, 3478 // thread_id); 3479 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc, Flags), 3480 getThreadID(CGF, Loc)}; 3481 if (auto *OMPRegionInfo = 3482 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 3483 if (!ForceSimpleCall && OMPRegionInfo->hasCancel()) { 3484 llvm::Value *Result = CGF.EmitRuntimeCall( 3485 createRuntimeFunction(OMPRTL__kmpc_cancel_barrier), Args); 3486 if (EmitChecks) { 3487 // if (__kmpc_cancel_barrier()) { 3488 // exit from construct; 3489 // } 3490 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 3491 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 3492 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 3493 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 3494 CGF.EmitBlock(ExitBB); 3495 // exit from construct; 3496 CodeGenFunction::JumpDest CancelDestination = 3497 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 3498 CGF.EmitBranchThroughCleanup(CancelDestination); 3499 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 3500 } 3501 return; 3502 } 3503 } 3504 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_barrier), Args); 3505 } 3506 3507 /// Map the OpenMP loop schedule to the runtime enumeration. 3508 static OpenMPSchedType getRuntimeSchedule(OpenMPScheduleClauseKind ScheduleKind, 3509 bool Chunked, bool Ordered) { 3510 switch (ScheduleKind) { 3511 case OMPC_SCHEDULE_static: 3512 return Chunked ? (Ordered ? OMP_ord_static_chunked : OMP_sch_static_chunked) 3513 : (Ordered ? OMP_ord_static : OMP_sch_static); 3514 case OMPC_SCHEDULE_dynamic: 3515 return Ordered ? OMP_ord_dynamic_chunked : OMP_sch_dynamic_chunked; 3516 case OMPC_SCHEDULE_guided: 3517 return Ordered ? OMP_ord_guided_chunked : OMP_sch_guided_chunked; 3518 case OMPC_SCHEDULE_runtime: 3519 return Ordered ? OMP_ord_runtime : OMP_sch_runtime; 3520 case OMPC_SCHEDULE_auto: 3521 return Ordered ? OMP_ord_auto : OMP_sch_auto; 3522 case OMPC_SCHEDULE_unknown: 3523 assert(!Chunked && "chunk was specified but schedule kind not known"); 3524 return Ordered ? OMP_ord_static : OMP_sch_static; 3525 } 3526 llvm_unreachable("Unexpected runtime schedule"); 3527 } 3528 3529 /// Map the OpenMP distribute schedule to the runtime enumeration. 3530 static OpenMPSchedType 3531 getRuntimeSchedule(OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) { 3532 // only static is allowed for dist_schedule 3533 return Chunked ? OMP_dist_sch_static_chunked : OMP_dist_sch_static; 3534 } 3535 3536 bool CGOpenMPRuntime::isStaticNonchunked(OpenMPScheduleClauseKind ScheduleKind, 3537 bool Chunked) const { 3538 OpenMPSchedType Schedule = 3539 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3540 return Schedule == OMP_sch_static; 3541 } 3542 3543 bool CGOpenMPRuntime::isStaticNonchunked( 3544 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3545 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3546 return Schedule == OMP_dist_sch_static; 3547 } 3548 3549 bool CGOpenMPRuntime::isStaticChunked(OpenMPScheduleClauseKind ScheduleKind, 3550 bool Chunked) const { 3551 OpenMPSchedType Schedule = 3552 getRuntimeSchedule(ScheduleKind, Chunked, /*Ordered=*/false); 3553 return Schedule == OMP_sch_static_chunked; 3554 } 3555 3556 bool CGOpenMPRuntime::isStaticChunked( 3557 OpenMPDistScheduleClauseKind ScheduleKind, bool Chunked) const { 3558 OpenMPSchedType Schedule = getRuntimeSchedule(ScheduleKind, Chunked); 3559 return Schedule == OMP_dist_sch_static_chunked; 3560 } 3561 3562 bool CGOpenMPRuntime::isDynamic(OpenMPScheduleClauseKind ScheduleKind) const { 3563 OpenMPSchedType Schedule = 3564 getRuntimeSchedule(ScheduleKind, /*Chunked=*/false, /*Ordered=*/false); 3565 assert(Schedule != OMP_sch_static_chunked && "cannot be chunked here"); 3566 return Schedule != OMP_sch_static; 3567 } 3568 3569 static int addMonoNonMonoModifier(CodeGenModule &CGM, OpenMPSchedType Schedule, 3570 OpenMPScheduleClauseModifier M1, 3571 OpenMPScheduleClauseModifier M2) { 3572 int Modifier = 0; 3573 switch (M1) { 3574 case OMPC_SCHEDULE_MODIFIER_monotonic: 3575 Modifier = OMP_sch_modifier_monotonic; 3576 break; 3577 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3578 Modifier = OMP_sch_modifier_nonmonotonic; 3579 break; 3580 case OMPC_SCHEDULE_MODIFIER_simd: 3581 if (Schedule == OMP_sch_static_chunked) 3582 Schedule = OMP_sch_static_balanced_chunked; 3583 break; 3584 case OMPC_SCHEDULE_MODIFIER_last: 3585 case OMPC_SCHEDULE_MODIFIER_unknown: 3586 break; 3587 } 3588 switch (M2) { 3589 case OMPC_SCHEDULE_MODIFIER_monotonic: 3590 Modifier = OMP_sch_modifier_monotonic; 3591 break; 3592 case OMPC_SCHEDULE_MODIFIER_nonmonotonic: 3593 Modifier = OMP_sch_modifier_nonmonotonic; 3594 break; 3595 case OMPC_SCHEDULE_MODIFIER_simd: 3596 if (Schedule == OMP_sch_static_chunked) 3597 Schedule = OMP_sch_static_balanced_chunked; 3598 break; 3599 case OMPC_SCHEDULE_MODIFIER_last: 3600 case OMPC_SCHEDULE_MODIFIER_unknown: 3601 break; 3602 } 3603 // OpenMP 5.0, 2.9.2 Worksharing-Loop Construct, Desription. 3604 // If the static schedule kind is specified or if the ordered clause is 3605 // specified, and if the nonmonotonic modifier is not specified, the effect is 3606 // as if the monotonic modifier is specified. Otherwise, unless the monotonic 3607 // modifier is specified, the effect is as if the nonmonotonic modifier is 3608 // specified. 3609 if (CGM.getLangOpts().OpenMP >= 50 && Modifier == 0) { 3610 if (!(Schedule == OMP_sch_static_chunked || Schedule == OMP_sch_static || 3611 Schedule == OMP_sch_static_balanced_chunked || 3612 Schedule == OMP_ord_static_chunked || Schedule == OMP_ord_static)) 3613 Modifier = OMP_sch_modifier_nonmonotonic; 3614 } 3615 return Schedule | Modifier; 3616 } 3617 3618 void CGOpenMPRuntime::emitForDispatchInit( 3619 CodeGenFunction &CGF, SourceLocation Loc, 3620 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 3621 bool Ordered, const DispatchRTInput &DispatchValues) { 3622 if (!CGF.HaveInsertPoint()) 3623 return; 3624 OpenMPSchedType Schedule = getRuntimeSchedule( 3625 ScheduleKind.Schedule, DispatchValues.Chunk != nullptr, Ordered); 3626 assert(Ordered || 3627 (Schedule != OMP_sch_static && Schedule != OMP_sch_static_chunked && 3628 Schedule != OMP_ord_static && Schedule != OMP_ord_static_chunked && 3629 Schedule != OMP_sch_static_balanced_chunked)); 3630 // Call __kmpc_dispatch_init( 3631 // ident_t *loc, kmp_int32 tid, kmp_int32 schedule, 3632 // kmp_int[32|64] lower, kmp_int[32|64] upper, 3633 // kmp_int[32|64] stride, kmp_int[32|64] chunk); 3634 3635 // If the Chunk was not specified in the clause - use default value 1. 3636 llvm::Value *Chunk = DispatchValues.Chunk ? DispatchValues.Chunk 3637 : CGF.Builder.getIntN(IVSize, 1); 3638 llvm::Value *Args[] = { 3639 emitUpdateLocation(CGF, Loc), 3640 getThreadID(CGF, Loc), 3641 CGF.Builder.getInt32(addMonoNonMonoModifier( 3642 CGM, Schedule, ScheduleKind.M1, ScheduleKind.M2)), // Schedule type 3643 DispatchValues.LB, // Lower 3644 DispatchValues.UB, // Upper 3645 CGF.Builder.getIntN(IVSize, 1), // Stride 3646 Chunk // Chunk 3647 }; 3648 CGF.EmitRuntimeCall(createDispatchInitFunction(IVSize, IVSigned), Args); 3649 } 3650 3651 static void emitForStaticInitCall( 3652 CodeGenFunction &CGF, llvm::Value *UpdateLocation, llvm::Value *ThreadId, 3653 llvm::FunctionCallee ForStaticInitFunction, OpenMPSchedType Schedule, 3654 OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, 3655 const CGOpenMPRuntime::StaticRTInput &Values) { 3656 if (!CGF.HaveInsertPoint()) 3657 return; 3658 3659 assert(!Values.Ordered); 3660 assert(Schedule == OMP_sch_static || Schedule == OMP_sch_static_chunked || 3661 Schedule == OMP_sch_static_balanced_chunked || 3662 Schedule == OMP_ord_static || Schedule == OMP_ord_static_chunked || 3663 Schedule == OMP_dist_sch_static || 3664 Schedule == OMP_dist_sch_static_chunked); 3665 3666 // Call __kmpc_for_static_init( 3667 // ident_t *loc, kmp_int32 tid, kmp_int32 schedtype, 3668 // kmp_int32 *p_lastiter, kmp_int[32|64] *p_lower, 3669 // kmp_int[32|64] *p_upper, kmp_int[32|64] *p_stride, 3670 // kmp_int[32|64] incr, kmp_int[32|64] chunk); 3671 llvm::Value *Chunk = Values.Chunk; 3672 if (Chunk == nullptr) { 3673 assert((Schedule == OMP_sch_static || Schedule == OMP_ord_static || 3674 Schedule == OMP_dist_sch_static) && 3675 "expected static non-chunked schedule"); 3676 // If the Chunk was not specified in the clause - use default value 1. 3677 Chunk = CGF.Builder.getIntN(Values.IVSize, 1); 3678 } else { 3679 assert((Schedule == OMP_sch_static_chunked || 3680 Schedule == OMP_sch_static_balanced_chunked || 3681 Schedule == OMP_ord_static_chunked || 3682 Schedule == OMP_dist_sch_static_chunked) && 3683 "expected static chunked schedule"); 3684 } 3685 llvm::Value *Args[] = { 3686 UpdateLocation, 3687 ThreadId, 3688 CGF.Builder.getInt32(addMonoNonMonoModifier(CGF.CGM, Schedule, M1, 3689 M2)), // Schedule type 3690 Values.IL.getPointer(), // &isLastIter 3691 Values.LB.getPointer(), // &LB 3692 Values.UB.getPointer(), // &UB 3693 Values.ST.getPointer(), // &Stride 3694 CGF.Builder.getIntN(Values.IVSize, 1), // Incr 3695 Chunk // Chunk 3696 }; 3697 CGF.EmitRuntimeCall(ForStaticInitFunction, Args); 3698 } 3699 3700 void CGOpenMPRuntime::emitForStaticInit(CodeGenFunction &CGF, 3701 SourceLocation Loc, 3702 OpenMPDirectiveKind DKind, 3703 const OpenMPScheduleTy &ScheduleKind, 3704 const StaticRTInput &Values) { 3705 OpenMPSchedType ScheduleNum = getRuntimeSchedule( 3706 ScheduleKind.Schedule, Values.Chunk != nullptr, Values.Ordered); 3707 assert(isOpenMPWorksharingDirective(DKind) && 3708 "Expected loop-based or sections-based directive."); 3709 llvm::Value *UpdatedLocation = emitUpdateLocation(CGF, Loc, 3710 isOpenMPLoopDirective(DKind) 3711 ? OMP_IDENT_WORK_LOOP 3712 : OMP_IDENT_WORK_SECTIONS); 3713 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3714 llvm::FunctionCallee StaticInitFunction = 3715 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3716 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3717 ScheduleNum, ScheduleKind.M1, ScheduleKind.M2, Values); 3718 } 3719 3720 void CGOpenMPRuntime::emitDistributeStaticInit( 3721 CodeGenFunction &CGF, SourceLocation Loc, 3722 OpenMPDistScheduleClauseKind SchedKind, 3723 const CGOpenMPRuntime::StaticRTInput &Values) { 3724 OpenMPSchedType ScheduleNum = 3725 getRuntimeSchedule(SchedKind, Values.Chunk != nullptr); 3726 llvm::Value *UpdatedLocation = 3727 emitUpdateLocation(CGF, Loc, OMP_IDENT_WORK_DISTRIBUTE); 3728 llvm::Value *ThreadId = getThreadID(CGF, Loc); 3729 llvm::FunctionCallee StaticInitFunction = 3730 createForStaticInitFunction(Values.IVSize, Values.IVSigned); 3731 emitForStaticInitCall(CGF, UpdatedLocation, ThreadId, StaticInitFunction, 3732 ScheduleNum, OMPC_SCHEDULE_MODIFIER_unknown, 3733 OMPC_SCHEDULE_MODIFIER_unknown, Values); 3734 } 3735 3736 void CGOpenMPRuntime::emitForStaticFinish(CodeGenFunction &CGF, 3737 SourceLocation Loc, 3738 OpenMPDirectiveKind DKind) { 3739 if (!CGF.HaveInsertPoint()) 3740 return; 3741 // Call __kmpc_for_static_fini(ident_t *loc, kmp_int32 tid); 3742 llvm::Value *Args[] = { 3743 emitUpdateLocation(CGF, Loc, 3744 isOpenMPDistributeDirective(DKind) 3745 ? OMP_IDENT_WORK_DISTRIBUTE 3746 : isOpenMPLoopDirective(DKind) 3747 ? OMP_IDENT_WORK_LOOP 3748 : OMP_IDENT_WORK_SECTIONS), 3749 getThreadID(CGF, Loc)}; 3750 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_for_static_fini), 3751 Args); 3752 } 3753 3754 void CGOpenMPRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 3755 SourceLocation Loc, 3756 unsigned IVSize, 3757 bool IVSigned) { 3758 if (!CGF.HaveInsertPoint()) 3759 return; 3760 // Call __kmpc_for_dynamic_fini_(4|8)[u](ident_t *loc, kmp_int32 tid); 3761 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 3762 CGF.EmitRuntimeCall(createDispatchFiniFunction(IVSize, IVSigned), Args); 3763 } 3764 3765 llvm::Value *CGOpenMPRuntime::emitForNext(CodeGenFunction &CGF, 3766 SourceLocation Loc, unsigned IVSize, 3767 bool IVSigned, Address IL, 3768 Address LB, Address UB, 3769 Address ST) { 3770 // Call __kmpc_dispatch_next( 3771 // ident_t *loc, kmp_int32 tid, kmp_int32 *p_lastiter, 3772 // kmp_int[32|64] *p_lower, kmp_int[32|64] *p_upper, 3773 // kmp_int[32|64] *p_stride); 3774 llvm::Value *Args[] = { 3775 emitUpdateLocation(CGF, Loc), 3776 getThreadID(CGF, Loc), 3777 IL.getPointer(), // &isLastIter 3778 LB.getPointer(), // &Lower 3779 UB.getPointer(), // &Upper 3780 ST.getPointer() // &Stride 3781 }; 3782 llvm::Value *Call = 3783 CGF.EmitRuntimeCall(createDispatchNextFunction(IVSize, IVSigned), Args); 3784 return CGF.EmitScalarConversion( 3785 Call, CGF.getContext().getIntTypeForBitwidth(32, /*Signed=*/1), 3786 CGF.getContext().BoolTy, Loc); 3787 } 3788 3789 void CGOpenMPRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 3790 llvm::Value *NumThreads, 3791 SourceLocation Loc) { 3792 if (!CGF.HaveInsertPoint()) 3793 return; 3794 // Build call __kmpc_push_num_threads(&loc, global_tid, num_threads) 3795 llvm::Value *Args[] = { 3796 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3797 CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned*/ true)}; 3798 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_threads), 3799 Args); 3800 } 3801 3802 void CGOpenMPRuntime::emitProcBindClause(CodeGenFunction &CGF, 3803 OpenMPProcBindClauseKind ProcBind, 3804 SourceLocation Loc) { 3805 if (!CGF.HaveInsertPoint()) 3806 return; 3807 // Constants for proc bind value accepted by the runtime. 3808 enum ProcBindTy { 3809 ProcBindFalse = 0, 3810 ProcBindTrue, 3811 ProcBindMaster, 3812 ProcBindClose, 3813 ProcBindSpread, 3814 ProcBindIntel, 3815 ProcBindDefault 3816 } RuntimeProcBind; 3817 switch (ProcBind) { 3818 case OMPC_PROC_BIND_master: 3819 RuntimeProcBind = ProcBindMaster; 3820 break; 3821 case OMPC_PROC_BIND_close: 3822 RuntimeProcBind = ProcBindClose; 3823 break; 3824 case OMPC_PROC_BIND_spread: 3825 RuntimeProcBind = ProcBindSpread; 3826 break; 3827 case OMPC_PROC_BIND_unknown: 3828 llvm_unreachable("Unsupported proc_bind value."); 3829 } 3830 // Build call __kmpc_push_proc_bind(&loc, global_tid, proc_bind) 3831 llvm::Value *Args[] = { 3832 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 3833 llvm::ConstantInt::get(CGM.IntTy, RuntimeProcBind, /*isSigned=*/true)}; 3834 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_proc_bind), Args); 3835 } 3836 3837 void CGOpenMPRuntime::emitFlush(CodeGenFunction &CGF, ArrayRef<const Expr *>, 3838 SourceLocation Loc) { 3839 if (!CGF.HaveInsertPoint()) 3840 return; 3841 // Build call void __kmpc_flush(ident_t *loc) 3842 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_flush), 3843 emitUpdateLocation(CGF, Loc)); 3844 } 3845 3846 namespace { 3847 /// Indexes of fields for type kmp_task_t. 3848 enum KmpTaskTFields { 3849 /// List of shared variables. 3850 KmpTaskTShareds, 3851 /// Task routine. 3852 KmpTaskTRoutine, 3853 /// Partition id for the untied tasks. 3854 KmpTaskTPartId, 3855 /// Function with call of destructors for private variables. 3856 Data1, 3857 /// Task priority. 3858 Data2, 3859 /// (Taskloops only) Lower bound. 3860 KmpTaskTLowerBound, 3861 /// (Taskloops only) Upper bound. 3862 KmpTaskTUpperBound, 3863 /// (Taskloops only) Stride. 3864 KmpTaskTStride, 3865 /// (Taskloops only) Is last iteration flag. 3866 KmpTaskTLastIter, 3867 /// (Taskloops only) Reduction data. 3868 KmpTaskTReductions, 3869 }; 3870 } // anonymous namespace 3871 3872 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::empty() const { 3873 return OffloadEntriesTargetRegion.empty() && 3874 OffloadEntriesDeviceGlobalVar.empty(); 3875 } 3876 3877 /// Initialize target region entry. 3878 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3879 initializeTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3880 StringRef ParentName, unsigned LineNum, 3881 unsigned Order) { 3882 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3883 "only required for the device " 3884 "code generation."); 3885 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = 3886 OffloadEntryInfoTargetRegion(Order, /*Addr=*/nullptr, /*ID=*/nullptr, 3887 OMPTargetRegionEntryTargetRegion); 3888 ++OffloadingEntriesNum; 3889 } 3890 3891 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3892 registerTargetRegionEntryInfo(unsigned DeviceID, unsigned FileID, 3893 StringRef ParentName, unsigned LineNum, 3894 llvm::Constant *Addr, llvm::Constant *ID, 3895 OMPTargetRegionEntryKind Flags) { 3896 // If we are emitting code for a target, the entry is already initialized, 3897 // only has to be registered. 3898 if (CGM.getLangOpts().OpenMPIsDevice) { 3899 if (!hasTargetRegionEntryInfo(DeviceID, FileID, ParentName, LineNum)) { 3900 unsigned DiagID = CGM.getDiags().getCustomDiagID( 3901 DiagnosticsEngine::Error, 3902 "Unable to find target region on line '%0' in the device code."); 3903 CGM.getDiags().Report(DiagID) << LineNum; 3904 return; 3905 } 3906 auto &Entry = 3907 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum]; 3908 assert(Entry.isValid() && "Entry not initialized!"); 3909 Entry.setAddress(Addr); 3910 Entry.setID(ID); 3911 Entry.setFlags(Flags); 3912 } else { 3913 OffloadEntryInfoTargetRegion Entry(OffloadingEntriesNum, Addr, ID, Flags); 3914 OffloadEntriesTargetRegion[DeviceID][FileID][ParentName][LineNum] = Entry; 3915 ++OffloadingEntriesNum; 3916 } 3917 } 3918 3919 bool CGOpenMPRuntime::OffloadEntriesInfoManagerTy::hasTargetRegionEntryInfo( 3920 unsigned DeviceID, unsigned FileID, StringRef ParentName, 3921 unsigned LineNum) const { 3922 auto PerDevice = OffloadEntriesTargetRegion.find(DeviceID); 3923 if (PerDevice == OffloadEntriesTargetRegion.end()) 3924 return false; 3925 auto PerFile = PerDevice->second.find(FileID); 3926 if (PerFile == PerDevice->second.end()) 3927 return false; 3928 auto PerParentName = PerFile->second.find(ParentName); 3929 if (PerParentName == PerFile->second.end()) 3930 return false; 3931 auto PerLine = PerParentName->second.find(LineNum); 3932 if (PerLine == PerParentName->second.end()) 3933 return false; 3934 // Fail if this entry is already registered. 3935 if (PerLine->second.getAddress() || PerLine->second.getID()) 3936 return false; 3937 return true; 3938 } 3939 3940 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy::actOnTargetRegionEntriesInfo( 3941 const OffloadTargetRegionEntryInfoActTy &Action) { 3942 // Scan all target region entries and perform the provided action. 3943 for (const auto &D : OffloadEntriesTargetRegion) 3944 for (const auto &F : D.second) 3945 for (const auto &P : F.second) 3946 for (const auto &L : P.second) 3947 Action(D.first, F.first, P.first(), L.first, L.second); 3948 } 3949 3950 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3951 initializeDeviceGlobalVarEntryInfo(StringRef Name, 3952 OMPTargetGlobalVarEntryKind Flags, 3953 unsigned Order) { 3954 assert(CGM.getLangOpts().OpenMPIsDevice && "Initialization of entries is " 3955 "only required for the device " 3956 "code generation."); 3957 OffloadEntriesDeviceGlobalVar.try_emplace(Name, Order, Flags); 3958 ++OffloadingEntriesNum; 3959 } 3960 3961 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 3962 registerDeviceGlobalVarEntryInfo(StringRef VarName, llvm::Constant *Addr, 3963 CharUnits VarSize, 3964 OMPTargetGlobalVarEntryKind Flags, 3965 llvm::GlobalValue::LinkageTypes Linkage) { 3966 if (CGM.getLangOpts().OpenMPIsDevice) { 3967 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3968 assert(Entry.isValid() && Entry.getFlags() == Flags && 3969 "Entry not initialized!"); 3970 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3971 "Resetting with the new address."); 3972 if (Entry.getAddress() && hasDeviceGlobalVarEntryInfo(VarName)) { 3973 if (Entry.getVarSize().isZero()) { 3974 Entry.setVarSize(VarSize); 3975 Entry.setLinkage(Linkage); 3976 } 3977 return; 3978 } 3979 Entry.setVarSize(VarSize); 3980 Entry.setLinkage(Linkage); 3981 Entry.setAddress(Addr); 3982 } else { 3983 if (hasDeviceGlobalVarEntryInfo(VarName)) { 3984 auto &Entry = OffloadEntriesDeviceGlobalVar[VarName]; 3985 assert(Entry.isValid() && Entry.getFlags() == Flags && 3986 "Entry not initialized!"); 3987 assert((!Entry.getAddress() || Entry.getAddress() == Addr) && 3988 "Resetting with the new address."); 3989 if (Entry.getVarSize().isZero()) { 3990 Entry.setVarSize(VarSize); 3991 Entry.setLinkage(Linkage); 3992 } 3993 return; 3994 } 3995 OffloadEntriesDeviceGlobalVar.try_emplace( 3996 VarName, OffloadingEntriesNum, Addr, VarSize, Flags, Linkage); 3997 ++OffloadingEntriesNum; 3998 } 3999 } 4000 4001 void CGOpenMPRuntime::OffloadEntriesInfoManagerTy:: 4002 actOnDeviceGlobalVarEntriesInfo( 4003 const OffloadDeviceGlobalVarEntryInfoActTy &Action) { 4004 // Scan all target region entries and perform the provided action. 4005 for (const auto &E : OffloadEntriesDeviceGlobalVar) 4006 Action(E.getKey(), E.getValue()); 4007 } 4008 4009 void CGOpenMPRuntime::createOffloadEntry( 4010 llvm::Constant *ID, llvm::Constant *Addr, uint64_t Size, int32_t Flags, 4011 llvm::GlobalValue::LinkageTypes Linkage) { 4012 StringRef Name = Addr->getName(); 4013 llvm::Module &M = CGM.getModule(); 4014 llvm::LLVMContext &C = M.getContext(); 4015 4016 // Create constant string with the name. 4017 llvm::Constant *StrPtrInit = llvm::ConstantDataArray::getString(C, Name); 4018 4019 std::string StringName = getName({"omp_offloading", "entry_name"}); 4020 auto *Str = new llvm::GlobalVariable( 4021 M, StrPtrInit->getType(), /*isConstant=*/true, 4022 llvm::GlobalValue::InternalLinkage, StrPtrInit, StringName); 4023 Str->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 4024 4025 llvm::Constant *Data[] = {llvm::ConstantExpr::getBitCast(ID, CGM.VoidPtrTy), 4026 llvm::ConstantExpr::getBitCast(Str, CGM.Int8PtrTy), 4027 llvm::ConstantInt::get(CGM.SizeTy, Size), 4028 llvm::ConstantInt::get(CGM.Int32Ty, Flags), 4029 llvm::ConstantInt::get(CGM.Int32Ty, 0)}; 4030 std::string EntryName = getName({"omp_offloading", "entry", ""}); 4031 llvm::GlobalVariable *Entry = createGlobalStruct( 4032 CGM, getTgtOffloadEntryQTy(), /*IsConstant=*/true, Data, 4033 Twine(EntryName).concat(Name), llvm::GlobalValue::WeakAnyLinkage); 4034 4035 // The entry has to be created in the section the linker expects it to be. 4036 Entry->setSection("omp_offloading_entries"); 4037 } 4038 4039 void CGOpenMPRuntime::createOffloadEntriesAndInfoMetadata() { 4040 // Emit the offloading entries and metadata so that the device codegen side 4041 // can easily figure out what to emit. The produced metadata looks like 4042 // this: 4043 // 4044 // !omp_offload.info = !{!1, ...} 4045 // 4046 // Right now we only generate metadata for function that contain target 4047 // regions. 4048 4049 // If we are in simd mode or there are no entries, we don't need to do 4050 // anything. 4051 if (CGM.getLangOpts().OpenMPSimd || OffloadEntriesInfoManager.empty()) 4052 return; 4053 4054 llvm::Module &M = CGM.getModule(); 4055 llvm::LLVMContext &C = M.getContext(); 4056 SmallVector<std::tuple<const OffloadEntriesInfoManagerTy::OffloadEntryInfo *, 4057 SourceLocation, StringRef>, 4058 16> 4059 OrderedEntries(OffloadEntriesInfoManager.size()); 4060 llvm::SmallVector<StringRef, 16> ParentFunctions( 4061 OffloadEntriesInfoManager.size()); 4062 4063 // Auxiliary methods to create metadata values and strings. 4064 auto &&GetMDInt = [this](unsigned V) { 4065 return llvm::ConstantAsMetadata::get( 4066 llvm::ConstantInt::get(CGM.Int32Ty, V)); 4067 }; 4068 4069 auto &&GetMDString = [&C](StringRef V) { return llvm::MDString::get(C, V); }; 4070 4071 // Create the offloading info metadata node. 4072 llvm::NamedMDNode *MD = M.getOrInsertNamedMetadata("omp_offload.info"); 4073 4074 // Create function that emits metadata for each target region entry; 4075 auto &&TargetRegionMetadataEmitter = 4076 [this, &C, MD, &OrderedEntries, &ParentFunctions, &GetMDInt, 4077 &GetMDString]( 4078 unsigned DeviceID, unsigned FileID, StringRef ParentName, 4079 unsigned Line, 4080 const OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion &E) { 4081 // Generate metadata for target regions. Each entry of this metadata 4082 // contains: 4083 // - Entry 0 -> Kind of this type of metadata (0). 4084 // - Entry 1 -> Device ID of the file where the entry was identified. 4085 // - Entry 2 -> File ID of the file where the entry was identified. 4086 // - Entry 3 -> Mangled name of the function where the entry was 4087 // identified. 4088 // - Entry 4 -> Line in the file where the entry was identified. 4089 // - Entry 5 -> Order the entry was created. 4090 // The first element of the metadata node is the kind. 4091 llvm::Metadata *Ops[] = {GetMDInt(E.getKind()), GetMDInt(DeviceID), 4092 GetMDInt(FileID), GetMDString(ParentName), 4093 GetMDInt(Line), GetMDInt(E.getOrder())}; 4094 4095 SourceLocation Loc; 4096 for (auto I = CGM.getContext().getSourceManager().fileinfo_begin(), 4097 E = CGM.getContext().getSourceManager().fileinfo_end(); 4098 I != E; ++I) { 4099 if (I->getFirst()->getUniqueID().getDevice() == DeviceID && 4100 I->getFirst()->getUniqueID().getFile() == FileID) { 4101 Loc = CGM.getContext().getSourceManager().translateFileLineCol( 4102 I->getFirst(), Line, 1); 4103 break; 4104 } 4105 } 4106 // Save this entry in the right position of the ordered entries array. 4107 OrderedEntries[E.getOrder()] = std::make_tuple(&E, Loc, ParentName); 4108 ParentFunctions[E.getOrder()] = ParentName; 4109 4110 // Add metadata to the named metadata node. 4111 MD->addOperand(llvm::MDNode::get(C, Ops)); 4112 }; 4113 4114 OffloadEntriesInfoManager.actOnTargetRegionEntriesInfo( 4115 TargetRegionMetadataEmitter); 4116 4117 // Create function that emits metadata for each device global variable entry; 4118 auto &&DeviceGlobalVarMetadataEmitter = 4119 [&C, &OrderedEntries, &GetMDInt, &GetMDString, 4120 MD](StringRef MangledName, 4121 const OffloadEntriesInfoManagerTy::OffloadEntryInfoDeviceGlobalVar 4122 &E) { 4123 // Generate metadata for global variables. Each entry of this metadata 4124 // contains: 4125 // - Entry 0 -> Kind of this type of metadata (1). 4126 // - Entry 1 -> Mangled name of the variable. 4127 // - Entry 2 -> Declare target kind. 4128 // - Entry 3 -> Order the entry was created. 4129 // The first element of the metadata node is the kind. 4130 llvm::Metadata *Ops[] = { 4131 GetMDInt(E.getKind()), GetMDString(MangledName), 4132 GetMDInt(E.getFlags()), GetMDInt(E.getOrder())}; 4133 4134 // Save this entry in the right position of the ordered entries array. 4135 OrderedEntries[E.getOrder()] = 4136 std::make_tuple(&E, SourceLocation(), MangledName); 4137 4138 // Add metadata to the named metadata node. 4139 MD->addOperand(llvm::MDNode::get(C, Ops)); 4140 }; 4141 4142 OffloadEntriesInfoManager.actOnDeviceGlobalVarEntriesInfo( 4143 DeviceGlobalVarMetadataEmitter); 4144 4145 for (const auto &E : OrderedEntries) { 4146 assert(std::get<0>(E) && "All ordered entries must exist!"); 4147 if (const auto *CE = 4148 dyn_cast<OffloadEntriesInfoManagerTy::OffloadEntryInfoTargetRegion>( 4149 std::get<0>(E))) { 4150 if (!CE->getID() || !CE->getAddress()) { 4151 // Do not blame the entry if the parent funtion is not emitted. 4152 StringRef FnName = ParentFunctions[CE->getOrder()]; 4153 if (!CGM.GetGlobalValue(FnName)) 4154 continue; 4155 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4156 DiagnosticsEngine::Error, 4157 "Offloading entry for target region in %0 is incorrect: either the " 4158 "address or the ID is invalid."); 4159 CGM.getDiags().Report(std::get<1>(E), DiagID) << FnName; 4160 continue; 4161 } 4162 createOffloadEntry(CE->getID(), CE->getAddress(), /*Size=*/0, 4163 CE->getFlags(), llvm::GlobalValue::WeakAnyLinkage); 4164 } else if (const auto *CE = dyn_cast<OffloadEntriesInfoManagerTy:: 4165 OffloadEntryInfoDeviceGlobalVar>( 4166 std::get<0>(E))) { 4167 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags = 4168 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4169 CE->getFlags()); 4170 switch (Flags) { 4171 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo: { 4172 if (CGM.getLangOpts().OpenMPIsDevice && 4173 CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()) 4174 continue; 4175 if (!CE->getAddress()) { 4176 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4177 DiagnosticsEngine::Error, "Offloading entry for declare target " 4178 "variable %0 is incorrect: the " 4179 "address is invalid."); 4180 CGM.getDiags().Report(std::get<1>(E), DiagID) << std::get<2>(E); 4181 continue; 4182 } 4183 // The vaiable has no definition - no need to add the entry. 4184 if (CE->getVarSize().isZero()) 4185 continue; 4186 break; 4187 } 4188 case OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink: 4189 assert(((CGM.getLangOpts().OpenMPIsDevice && !CE->getAddress()) || 4190 (!CGM.getLangOpts().OpenMPIsDevice && CE->getAddress())) && 4191 "Declaret target link address is set."); 4192 if (CGM.getLangOpts().OpenMPIsDevice) 4193 continue; 4194 if (!CE->getAddress()) { 4195 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4196 DiagnosticsEngine::Error, 4197 "Offloading entry for declare target variable is incorrect: the " 4198 "address is invalid."); 4199 CGM.getDiags().Report(DiagID); 4200 continue; 4201 } 4202 break; 4203 } 4204 createOffloadEntry(CE->getAddress(), CE->getAddress(), 4205 CE->getVarSize().getQuantity(), Flags, 4206 CE->getLinkage()); 4207 } else { 4208 llvm_unreachable("Unsupported entry kind."); 4209 } 4210 } 4211 } 4212 4213 /// Loads all the offload entries information from the host IR 4214 /// metadata. 4215 void CGOpenMPRuntime::loadOffloadInfoMetadata() { 4216 // If we are in target mode, load the metadata from the host IR. This code has 4217 // to match the metadaata creation in createOffloadEntriesAndInfoMetadata(). 4218 4219 if (!CGM.getLangOpts().OpenMPIsDevice) 4220 return; 4221 4222 if (CGM.getLangOpts().OMPHostIRFile.empty()) 4223 return; 4224 4225 auto Buf = llvm::MemoryBuffer::getFile(CGM.getLangOpts().OMPHostIRFile); 4226 if (auto EC = Buf.getError()) { 4227 CGM.getDiags().Report(diag::err_cannot_open_file) 4228 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4229 return; 4230 } 4231 4232 llvm::LLVMContext C; 4233 auto ME = expectedToErrorOrAndEmitErrors( 4234 C, llvm::parseBitcodeFile(Buf.get()->getMemBufferRef(), C)); 4235 4236 if (auto EC = ME.getError()) { 4237 unsigned DiagID = CGM.getDiags().getCustomDiagID( 4238 DiagnosticsEngine::Error, "Unable to parse host IR file '%0':'%1'"); 4239 CGM.getDiags().Report(DiagID) 4240 << CGM.getLangOpts().OMPHostIRFile << EC.message(); 4241 return; 4242 } 4243 4244 llvm::NamedMDNode *MD = ME.get()->getNamedMetadata("omp_offload.info"); 4245 if (!MD) 4246 return; 4247 4248 for (llvm::MDNode *MN : MD->operands()) { 4249 auto &&GetMDInt = [MN](unsigned Idx) { 4250 auto *V = cast<llvm::ConstantAsMetadata>(MN->getOperand(Idx)); 4251 return cast<llvm::ConstantInt>(V->getValue())->getZExtValue(); 4252 }; 4253 4254 auto &&GetMDString = [MN](unsigned Idx) { 4255 auto *V = cast<llvm::MDString>(MN->getOperand(Idx)); 4256 return V->getString(); 4257 }; 4258 4259 switch (GetMDInt(0)) { 4260 default: 4261 llvm_unreachable("Unexpected metadata!"); 4262 break; 4263 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4264 OffloadingEntryInfoTargetRegion: 4265 OffloadEntriesInfoManager.initializeTargetRegionEntryInfo( 4266 /*DeviceID=*/GetMDInt(1), /*FileID=*/GetMDInt(2), 4267 /*ParentName=*/GetMDString(3), /*Line=*/GetMDInt(4), 4268 /*Order=*/GetMDInt(5)); 4269 break; 4270 case OffloadEntriesInfoManagerTy::OffloadEntryInfo:: 4271 OffloadingEntryInfoDeviceGlobalVar: 4272 OffloadEntriesInfoManager.initializeDeviceGlobalVarEntryInfo( 4273 /*MangledName=*/GetMDString(1), 4274 static_cast<OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind>( 4275 /*Flags=*/GetMDInt(2)), 4276 /*Order=*/GetMDInt(3)); 4277 break; 4278 } 4279 } 4280 } 4281 4282 void CGOpenMPRuntime::emitKmpRoutineEntryT(QualType KmpInt32Ty) { 4283 if (!KmpRoutineEntryPtrTy) { 4284 // Build typedef kmp_int32 (* kmp_routine_entry_t)(kmp_int32, void *); type. 4285 ASTContext &C = CGM.getContext(); 4286 QualType KmpRoutineEntryTyArgs[] = {KmpInt32Ty, C.VoidPtrTy}; 4287 FunctionProtoType::ExtProtoInfo EPI; 4288 KmpRoutineEntryPtrQTy = C.getPointerType( 4289 C.getFunctionType(KmpInt32Ty, KmpRoutineEntryTyArgs, EPI)); 4290 KmpRoutineEntryPtrTy = CGM.getTypes().ConvertType(KmpRoutineEntryPtrQTy); 4291 } 4292 } 4293 4294 QualType CGOpenMPRuntime::getTgtOffloadEntryQTy() { 4295 // Make sure the type of the entry is already created. This is the type we 4296 // have to create: 4297 // struct __tgt_offload_entry{ 4298 // void *addr; // Pointer to the offload entry info. 4299 // // (function or global) 4300 // char *name; // Name of the function or global. 4301 // size_t size; // Size of the entry info (0 if it a function). 4302 // int32_t flags; // Flags associated with the entry, e.g. 'link'. 4303 // int32_t reserved; // Reserved, to use by the runtime library. 4304 // }; 4305 if (TgtOffloadEntryQTy.isNull()) { 4306 ASTContext &C = CGM.getContext(); 4307 RecordDecl *RD = C.buildImplicitRecord("__tgt_offload_entry"); 4308 RD->startDefinition(); 4309 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4310 addFieldToRecordDecl(C, RD, C.getPointerType(C.CharTy)); 4311 addFieldToRecordDecl(C, RD, C.getSizeType()); 4312 addFieldToRecordDecl( 4313 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4314 addFieldToRecordDecl( 4315 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4316 RD->completeDefinition(); 4317 RD->addAttr(PackedAttr::CreateImplicit(C)); 4318 TgtOffloadEntryQTy = C.getRecordType(RD); 4319 } 4320 return TgtOffloadEntryQTy; 4321 } 4322 4323 QualType CGOpenMPRuntime::getTgtDeviceImageQTy() { 4324 // These are the types we need to build: 4325 // struct __tgt_device_image{ 4326 // void *ImageStart; // Pointer to the target code start. 4327 // void *ImageEnd; // Pointer to the target code end. 4328 // // We also add the host entries to the device image, as it may be useful 4329 // // for the target runtime to have access to that information. 4330 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all 4331 // // the entries. 4332 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4333 // // entries (non inclusive). 4334 // }; 4335 if (TgtDeviceImageQTy.isNull()) { 4336 ASTContext &C = CGM.getContext(); 4337 RecordDecl *RD = C.buildImplicitRecord("__tgt_device_image"); 4338 RD->startDefinition(); 4339 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4340 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4341 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4342 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4343 RD->completeDefinition(); 4344 TgtDeviceImageQTy = C.getRecordType(RD); 4345 } 4346 return TgtDeviceImageQTy; 4347 } 4348 4349 QualType CGOpenMPRuntime::getTgtBinaryDescriptorQTy() { 4350 // struct __tgt_bin_desc{ 4351 // int32_t NumDevices; // Number of devices supported. 4352 // __tgt_device_image *DeviceImages; // Arrays of device images 4353 // // (one per device). 4354 // __tgt_offload_entry *EntriesBegin; // Begin of the table with all the 4355 // // entries. 4356 // __tgt_offload_entry *EntriesEnd; // End of the table with all the 4357 // // entries (non inclusive). 4358 // }; 4359 if (TgtBinaryDescriptorQTy.isNull()) { 4360 ASTContext &C = CGM.getContext(); 4361 RecordDecl *RD = C.buildImplicitRecord("__tgt_bin_desc"); 4362 RD->startDefinition(); 4363 addFieldToRecordDecl( 4364 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/true)); 4365 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtDeviceImageQTy())); 4366 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4367 addFieldToRecordDecl(C, RD, C.getPointerType(getTgtOffloadEntryQTy())); 4368 RD->completeDefinition(); 4369 TgtBinaryDescriptorQTy = C.getRecordType(RD); 4370 } 4371 return TgtBinaryDescriptorQTy; 4372 } 4373 4374 namespace { 4375 struct PrivateHelpersTy { 4376 PrivateHelpersTy(const VarDecl *Original, const VarDecl *PrivateCopy, 4377 const VarDecl *PrivateElemInit) 4378 : Original(Original), PrivateCopy(PrivateCopy), 4379 PrivateElemInit(PrivateElemInit) {} 4380 const VarDecl *Original; 4381 const VarDecl *PrivateCopy; 4382 const VarDecl *PrivateElemInit; 4383 }; 4384 typedef std::pair<CharUnits /*Align*/, PrivateHelpersTy> PrivateDataTy; 4385 } // anonymous namespace 4386 4387 static RecordDecl * 4388 createPrivatesRecordDecl(CodeGenModule &CGM, ArrayRef<PrivateDataTy> Privates) { 4389 if (!Privates.empty()) { 4390 ASTContext &C = CGM.getContext(); 4391 // Build struct .kmp_privates_t. { 4392 // /* private vars */ 4393 // }; 4394 RecordDecl *RD = C.buildImplicitRecord(".kmp_privates.t"); 4395 RD->startDefinition(); 4396 for (const auto &Pair : Privates) { 4397 const VarDecl *VD = Pair.second.Original; 4398 QualType Type = VD->getType().getNonReferenceType(); 4399 FieldDecl *FD = addFieldToRecordDecl(C, RD, Type); 4400 if (VD->hasAttrs()) { 4401 for (specific_attr_iterator<AlignedAttr> I(VD->getAttrs().begin()), 4402 E(VD->getAttrs().end()); 4403 I != E; ++I) 4404 FD->addAttr(*I); 4405 } 4406 } 4407 RD->completeDefinition(); 4408 return RD; 4409 } 4410 return nullptr; 4411 } 4412 4413 static RecordDecl * 4414 createKmpTaskTRecordDecl(CodeGenModule &CGM, OpenMPDirectiveKind Kind, 4415 QualType KmpInt32Ty, 4416 QualType KmpRoutineEntryPointerQTy) { 4417 ASTContext &C = CGM.getContext(); 4418 // Build struct kmp_task_t { 4419 // void * shareds; 4420 // kmp_routine_entry_t routine; 4421 // kmp_int32 part_id; 4422 // kmp_cmplrdata_t data1; 4423 // kmp_cmplrdata_t data2; 4424 // For taskloops additional fields: 4425 // kmp_uint64 lb; 4426 // kmp_uint64 ub; 4427 // kmp_int64 st; 4428 // kmp_int32 liter; 4429 // void * reductions; 4430 // }; 4431 RecordDecl *UD = C.buildImplicitRecord("kmp_cmplrdata_t", TTK_Union); 4432 UD->startDefinition(); 4433 addFieldToRecordDecl(C, UD, KmpInt32Ty); 4434 addFieldToRecordDecl(C, UD, KmpRoutineEntryPointerQTy); 4435 UD->completeDefinition(); 4436 QualType KmpCmplrdataTy = C.getRecordType(UD); 4437 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t"); 4438 RD->startDefinition(); 4439 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4440 addFieldToRecordDecl(C, RD, KmpRoutineEntryPointerQTy); 4441 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4442 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4443 addFieldToRecordDecl(C, RD, KmpCmplrdataTy); 4444 if (isOpenMPTaskLoopDirective(Kind)) { 4445 QualType KmpUInt64Ty = 4446 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/0); 4447 QualType KmpInt64Ty = 4448 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 4449 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4450 addFieldToRecordDecl(C, RD, KmpUInt64Ty); 4451 addFieldToRecordDecl(C, RD, KmpInt64Ty); 4452 addFieldToRecordDecl(C, RD, KmpInt32Ty); 4453 addFieldToRecordDecl(C, RD, C.VoidPtrTy); 4454 } 4455 RD->completeDefinition(); 4456 return RD; 4457 } 4458 4459 static RecordDecl * 4460 createKmpTaskTWithPrivatesRecordDecl(CodeGenModule &CGM, QualType KmpTaskTQTy, 4461 ArrayRef<PrivateDataTy> Privates) { 4462 ASTContext &C = CGM.getContext(); 4463 // Build struct kmp_task_t_with_privates { 4464 // kmp_task_t task_data; 4465 // .kmp_privates_t. privates; 4466 // }; 4467 RecordDecl *RD = C.buildImplicitRecord("kmp_task_t_with_privates"); 4468 RD->startDefinition(); 4469 addFieldToRecordDecl(C, RD, KmpTaskTQTy); 4470 if (const RecordDecl *PrivateRD = createPrivatesRecordDecl(CGM, Privates)) 4471 addFieldToRecordDecl(C, RD, C.getRecordType(PrivateRD)); 4472 RD->completeDefinition(); 4473 return RD; 4474 } 4475 4476 /// Emit a proxy function which accepts kmp_task_t as the second 4477 /// argument. 4478 /// \code 4479 /// kmp_int32 .omp_task_entry.(kmp_int32 gtid, kmp_task_t *tt) { 4480 /// TaskFunction(gtid, tt->part_id, &tt->privates, task_privates_map, tt, 4481 /// For taskloops: 4482 /// tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4483 /// tt->reductions, tt->shareds); 4484 /// return 0; 4485 /// } 4486 /// \endcode 4487 static llvm::Function * 4488 emitProxyTaskFunction(CodeGenModule &CGM, SourceLocation Loc, 4489 OpenMPDirectiveKind Kind, QualType KmpInt32Ty, 4490 QualType KmpTaskTWithPrivatesPtrQTy, 4491 QualType KmpTaskTWithPrivatesQTy, QualType KmpTaskTQTy, 4492 QualType SharedsPtrTy, llvm::Function *TaskFunction, 4493 llvm::Value *TaskPrivatesMap) { 4494 ASTContext &C = CGM.getContext(); 4495 FunctionArgList Args; 4496 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4497 ImplicitParamDecl::Other); 4498 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4499 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4500 ImplicitParamDecl::Other); 4501 Args.push_back(&GtidArg); 4502 Args.push_back(&TaskTypeArg); 4503 const auto &TaskEntryFnInfo = 4504 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4505 llvm::FunctionType *TaskEntryTy = 4506 CGM.getTypes().GetFunctionType(TaskEntryFnInfo); 4507 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_entry", ""}); 4508 auto *TaskEntry = llvm::Function::Create( 4509 TaskEntryTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4510 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskEntry, TaskEntryFnInfo); 4511 TaskEntry->setDoesNotRecurse(); 4512 CodeGenFunction CGF(CGM); 4513 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, TaskEntry, TaskEntryFnInfo, Args, 4514 Loc, Loc); 4515 4516 // TaskFunction(gtid, tt->task_data.part_id, &tt->privates, task_privates_map, 4517 // tt, 4518 // For taskloops: 4519 // tt->task_data.lb, tt->task_data.ub, tt->task_data.st, tt->task_data.liter, 4520 // tt->task_data.shareds); 4521 llvm::Value *GtidParam = CGF.EmitLoadOfScalar( 4522 CGF.GetAddrOfLocalVar(&GtidArg), /*Volatile=*/false, KmpInt32Ty, Loc); 4523 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4524 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4525 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4526 const auto *KmpTaskTWithPrivatesQTyRD = 4527 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4528 LValue Base = 4529 CGF.EmitLValueForField(TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4530 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 4531 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 4532 LValue PartIdLVal = CGF.EmitLValueForField(Base, *PartIdFI); 4533 llvm::Value *PartidParam = PartIdLVal.getPointer(); 4534 4535 auto SharedsFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTShareds); 4536 LValue SharedsLVal = CGF.EmitLValueForField(Base, *SharedsFI); 4537 llvm::Value *SharedsParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4538 CGF.EmitLoadOfScalar(SharedsLVal, Loc), 4539 CGF.ConvertTypeForMem(SharedsPtrTy)); 4540 4541 auto PrivatesFI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4542 llvm::Value *PrivatesParam; 4543 if (PrivatesFI != KmpTaskTWithPrivatesQTyRD->field_end()) { 4544 LValue PrivatesLVal = CGF.EmitLValueForField(TDBase, *PrivatesFI); 4545 PrivatesParam = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4546 PrivatesLVal.getPointer(), CGF.VoidPtrTy); 4547 } else { 4548 PrivatesParam = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 4549 } 4550 4551 llvm::Value *CommonArgs[] = {GtidParam, PartidParam, PrivatesParam, 4552 TaskPrivatesMap, 4553 CGF.Builder 4554 .CreatePointerBitCastOrAddrSpaceCast( 4555 TDBase.getAddress(), CGF.VoidPtrTy) 4556 .getPointer()}; 4557 SmallVector<llvm::Value *, 16> CallArgs(std::begin(CommonArgs), 4558 std::end(CommonArgs)); 4559 if (isOpenMPTaskLoopDirective(Kind)) { 4560 auto LBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound); 4561 LValue LBLVal = CGF.EmitLValueForField(Base, *LBFI); 4562 llvm::Value *LBParam = CGF.EmitLoadOfScalar(LBLVal, Loc); 4563 auto UBFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound); 4564 LValue UBLVal = CGF.EmitLValueForField(Base, *UBFI); 4565 llvm::Value *UBParam = CGF.EmitLoadOfScalar(UBLVal, Loc); 4566 auto StFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTStride); 4567 LValue StLVal = CGF.EmitLValueForField(Base, *StFI); 4568 llvm::Value *StParam = CGF.EmitLoadOfScalar(StLVal, Loc); 4569 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4570 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4571 llvm::Value *LIParam = CGF.EmitLoadOfScalar(LILVal, Loc); 4572 auto RFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTReductions); 4573 LValue RLVal = CGF.EmitLValueForField(Base, *RFI); 4574 llvm::Value *RParam = CGF.EmitLoadOfScalar(RLVal, Loc); 4575 CallArgs.push_back(LBParam); 4576 CallArgs.push_back(UBParam); 4577 CallArgs.push_back(StParam); 4578 CallArgs.push_back(LIParam); 4579 CallArgs.push_back(RParam); 4580 } 4581 CallArgs.push_back(SharedsParam); 4582 4583 CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskFunction, 4584 CallArgs); 4585 CGF.EmitStoreThroughLValue(RValue::get(CGF.Builder.getInt32(/*C=*/0)), 4586 CGF.MakeAddrLValue(CGF.ReturnValue, KmpInt32Ty)); 4587 CGF.FinishFunction(); 4588 return TaskEntry; 4589 } 4590 4591 static llvm::Value *emitDestructorsFunction(CodeGenModule &CGM, 4592 SourceLocation Loc, 4593 QualType KmpInt32Ty, 4594 QualType KmpTaskTWithPrivatesPtrQTy, 4595 QualType KmpTaskTWithPrivatesQTy) { 4596 ASTContext &C = CGM.getContext(); 4597 FunctionArgList Args; 4598 ImplicitParamDecl GtidArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, KmpInt32Ty, 4599 ImplicitParamDecl::Other); 4600 ImplicitParamDecl TaskTypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4601 KmpTaskTWithPrivatesPtrQTy.withRestrict(), 4602 ImplicitParamDecl::Other); 4603 Args.push_back(&GtidArg); 4604 Args.push_back(&TaskTypeArg); 4605 const auto &DestructorFnInfo = 4606 CGM.getTypes().arrangeBuiltinFunctionDeclaration(KmpInt32Ty, Args); 4607 llvm::FunctionType *DestructorFnTy = 4608 CGM.getTypes().GetFunctionType(DestructorFnInfo); 4609 std::string Name = 4610 CGM.getOpenMPRuntime().getName({"omp_task_destructor", ""}); 4611 auto *DestructorFn = 4612 llvm::Function::Create(DestructorFnTy, llvm::GlobalValue::InternalLinkage, 4613 Name, &CGM.getModule()); 4614 CGM.SetInternalFunctionAttributes(GlobalDecl(), DestructorFn, 4615 DestructorFnInfo); 4616 DestructorFn->setDoesNotRecurse(); 4617 CodeGenFunction CGF(CGM); 4618 CGF.StartFunction(GlobalDecl(), KmpInt32Ty, DestructorFn, DestructorFnInfo, 4619 Args, Loc, Loc); 4620 4621 LValue Base = CGF.EmitLoadOfPointerLValue( 4622 CGF.GetAddrOfLocalVar(&TaskTypeArg), 4623 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4624 const auto *KmpTaskTWithPrivatesQTyRD = 4625 cast<RecordDecl>(KmpTaskTWithPrivatesQTy->getAsTagDecl()); 4626 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4627 Base = CGF.EmitLValueForField(Base, *FI); 4628 for (const auto *Field : 4629 cast<RecordDecl>(FI->getType()->getAsTagDecl())->fields()) { 4630 if (QualType::DestructionKind DtorKind = 4631 Field->getType().isDestructedType()) { 4632 LValue FieldLValue = CGF.EmitLValueForField(Base, Field); 4633 CGF.pushDestroy(DtorKind, FieldLValue.getAddress(), Field->getType()); 4634 } 4635 } 4636 CGF.FinishFunction(); 4637 return DestructorFn; 4638 } 4639 4640 /// Emit a privates mapping function for correct handling of private and 4641 /// firstprivate variables. 4642 /// \code 4643 /// void .omp_task_privates_map.(const .privates. *noalias privs, <ty1> 4644 /// **noalias priv1,..., <tyn> **noalias privn) { 4645 /// *priv1 = &.privates.priv1; 4646 /// ...; 4647 /// *privn = &.privates.privn; 4648 /// } 4649 /// \endcode 4650 static llvm::Value * 4651 emitTaskPrivateMappingFunction(CodeGenModule &CGM, SourceLocation Loc, 4652 ArrayRef<const Expr *> PrivateVars, 4653 ArrayRef<const Expr *> FirstprivateVars, 4654 ArrayRef<const Expr *> LastprivateVars, 4655 QualType PrivatesQTy, 4656 ArrayRef<PrivateDataTy> Privates) { 4657 ASTContext &C = CGM.getContext(); 4658 FunctionArgList Args; 4659 ImplicitParamDecl TaskPrivatesArg( 4660 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4661 C.getPointerType(PrivatesQTy).withConst().withRestrict(), 4662 ImplicitParamDecl::Other); 4663 Args.push_back(&TaskPrivatesArg); 4664 llvm::DenseMap<const VarDecl *, unsigned> PrivateVarsPos; 4665 unsigned Counter = 1; 4666 for (const Expr *E : PrivateVars) { 4667 Args.push_back(ImplicitParamDecl::Create( 4668 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4669 C.getPointerType(C.getPointerType(E->getType())) 4670 .withConst() 4671 .withRestrict(), 4672 ImplicitParamDecl::Other)); 4673 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4674 PrivateVarsPos[VD] = Counter; 4675 ++Counter; 4676 } 4677 for (const Expr *E : FirstprivateVars) { 4678 Args.push_back(ImplicitParamDecl::Create( 4679 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4680 C.getPointerType(C.getPointerType(E->getType())) 4681 .withConst() 4682 .withRestrict(), 4683 ImplicitParamDecl::Other)); 4684 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4685 PrivateVarsPos[VD] = Counter; 4686 ++Counter; 4687 } 4688 for (const Expr *E : LastprivateVars) { 4689 Args.push_back(ImplicitParamDecl::Create( 4690 C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4691 C.getPointerType(C.getPointerType(E->getType())) 4692 .withConst() 4693 .withRestrict(), 4694 ImplicitParamDecl::Other)); 4695 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4696 PrivateVarsPos[VD] = Counter; 4697 ++Counter; 4698 } 4699 const auto &TaskPrivatesMapFnInfo = 4700 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4701 llvm::FunctionType *TaskPrivatesMapTy = 4702 CGM.getTypes().GetFunctionType(TaskPrivatesMapFnInfo); 4703 std::string Name = 4704 CGM.getOpenMPRuntime().getName({"omp_task_privates_map", ""}); 4705 auto *TaskPrivatesMap = llvm::Function::Create( 4706 TaskPrivatesMapTy, llvm::GlobalValue::InternalLinkage, Name, 4707 &CGM.getModule()); 4708 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskPrivatesMap, 4709 TaskPrivatesMapFnInfo); 4710 if (CGM.getLangOpts().Optimize) { 4711 TaskPrivatesMap->removeFnAttr(llvm::Attribute::NoInline); 4712 TaskPrivatesMap->removeFnAttr(llvm::Attribute::OptimizeNone); 4713 TaskPrivatesMap->addFnAttr(llvm::Attribute::AlwaysInline); 4714 } 4715 CodeGenFunction CGF(CGM); 4716 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskPrivatesMap, 4717 TaskPrivatesMapFnInfo, Args, Loc, Loc); 4718 4719 // *privi = &.privates.privi; 4720 LValue Base = CGF.EmitLoadOfPointerLValue( 4721 CGF.GetAddrOfLocalVar(&TaskPrivatesArg), 4722 TaskPrivatesArg.getType()->castAs<PointerType>()); 4723 const auto *PrivatesQTyRD = cast<RecordDecl>(PrivatesQTy->getAsTagDecl()); 4724 Counter = 0; 4725 for (const FieldDecl *Field : PrivatesQTyRD->fields()) { 4726 LValue FieldLVal = CGF.EmitLValueForField(Base, Field); 4727 const VarDecl *VD = Args[PrivateVarsPos[Privates[Counter].second.Original]]; 4728 LValue RefLVal = 4729 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(VD), VD->getType()); 4730 LValue RefLoadLVal = CGF.EmitLoadOfPointerLValue( 4731 RefLVal.getAddress(), RefLVal.getType()->castAs<PointerType>()); 4732 CGF.EmitStoreOfScalar(FieldLVal.getPointer(), RefLoadLVal); 4733 ++Counter; 4734 } 4735 CGF.FinishFunction(); 4736 return TaskPrivatesMap; 4737 } 4738 4739 /// Emit initialization for private variables in task-based directives. 4740 static void emitPrivatesInit(CodeGenFunction &CGF, 4741 const OMPExecutableDirective &D, 4742 Address KmpTaskSharedsPtr, LValue TDBase, 4743 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4744 QualType SharedsTy, QualType SharedsPtrTy, 4745 const OMPTaskDataTy &Data, 4746 ArrayRef<PrivateDataTy> Privates, bool ForDup) { 4747 ASTContext &C = CGF.getContext(); 4748 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 4749 LValue PrivatesBase = CGF.EmitLValueForField(TDBase, *FI); 4750 OpenMPDirectiveKind Kind = isOpenMPTaskLoopDirective(D.getDirectiveKind()) 4751 ? OMPD_taskloop 4752 : OMPD_task; 4753 const CapturedStmt &CS = *D.getCapturedStmt(Kind); 4754 CodeGenFunction::CGCapturedStmtInfo CapturesInfo(CS); 4755 LValue SrcBase; 4756 bool IsTargetTask = 4757 isOpenMPTargetDataManagementDirective(D.getDirectiveKind()) || 4758 isOpenMPTargetExecutionDirective(D.getDirectiveKind()); 4759 // For target-based directives skip 3 firstprivate arrays BasePointersArray, 4760 // PointersArray and SizesArray. The original variables for these arrays are 4761 // not captured and we get their addresses explicitly. 4762 if ((!IsTargetTask && !Data.FirstprivateVars.empty()) || 4763 (IsTargetTask && KmpTaskSharedsPtr.isValid())) { 4764 SrcBase = CGF.MakeAddrLValue( 4765 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 4766 KmpTaskSharedsPtr, CGF.ConvertTypeForMem(SharedsPtrTy)), 4767 SharedsTy); 4768 } 4769 FI = cast<RecordDecl>(FI->getType()->getAsTagDecl())->field_begin(); 4770 for (const PrivateDataTy &Pair : Privates) { 4771 const VarDecl *VD = Pair.second.PrivateCopy; 4772 const Expr *Init = VD->getAnyInitializer(); 4773 if (Init && (!ForDup || (isa<CXXConstructExpr>(Init) && 4774 !CGF.isTrivialInitializer(Init)))) { 4775 LValue PrivateLValue = CGF.EmitLValueForField(PrivatesBase, *FI); 4776 if (const VarDecl *Elem = Pair.second.PrivateElemInit) { 4777 const VarDecl *OriginalVD = Pair.second.Original; 4778 // Check if the variable is the target-based BasePointersArray, 4779 // PointersArray or SizesArray. 4780 LValue SharedRefLValue; 4781 QualType Type = PrivateLValue.getType(); 4782 const FieldDecl *SharedField = CapturesInfo.lookup(OriginalVD); 4783 if (IsTargetTask && !SharedField) { 4784 assert(isa<ImplicitParamDecl>(OriginalVD) && 4785 isa<CapturedDecl>(OriginalVD->getDeclContext()) && 4786 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4787 ->getNumParams() == 0 && 4788 isa<TranslationUnitDecl>( 4789 cast<CapturedDecl>(OriginalVD->getDeclContext()) 4790 ->getDeclContext()) && 4791 "Expected artificial target data variable."); 4792 SharedRefLValue = 4793 CGF.MakeAddrLValue(CGF.GetAddrOfLocalVar(OriginalVD), Type); 4794 } else { 4795 SharedRefLValue = CGF.EmitLValueForField(SrcBase, SharedField); 4796 SharedRefLValue = CGF.MakeAddrLValue( 4797 Address(SharedRefLValue.getPointer(), C.getDeclAlign(OriginalVD)), 4798 SharedRefLValue.getType(), LValueBaseInfo(AlignmentSource::Decl), 4799 SharedRefLValue.getTBAAInfo()); 4800 } 4801 if (Type->isArrayType()) { 4802 // Initialize firstprivate array. 4803 if (!isa<CXXConstructExpr>(Init) || CGF.isTrivialInitializer(Init)) { 4804 // Perform simple memcpy. 4805 CGF.EmitAggregateAssign(PrivateLValue, SharedRefLValue, Type); 4806 } else { 4807 // Initialize firstprivate array using element-by-element 4808 // initialization. 4809 CGF.EmitOMPAggregateAssign( 4810 PrivateLValue.getAddress(), SharedRefLValue.getAddress(), Type, 4811 [&CGF, Elem, Init, &CapturesInfo](Address DestElement, 4812 Address SrcElement) { 4813 // Clean up any temporaries needed by the initialization. 4814 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4815 InitScope.addPrivate( 4816 Elem, [SrcElement]() -> Address { return SrcElement; }); 4817 (void)InitScope.Privatize(); 4818 // Emit initialization for single element. 4819 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII( 4820 CGF, &CapturesInfo); 4821 CGF.EmitAnyExprToMem(Init, DestElement, 4822 Init->getType().getQualifiers(), 4823 /*IsInitializer=*/false); 4824 }); 4825 } 4826 } else { 4827 CodeGenFunction::OMPPrivateScope InitScope(CGF); 4828 InitScope.addPrivate(Elem, [SharedRefLValue]() -> Address { 4829 return SharedRefLValue.getAddress(); 4830 }); 4831 (void)InitScope.Privatize(); 4832 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CapturesInfo); 4833 CGF.EmitExprAsInit(Init, VD, PrivateLValue, 4834 /*capturedByInit=*/false); 4835 } 4836 } else { 4837 CGF.EmitExprAsInit(Init, VD, PrivateLValue, /*capturedByInit=*/false); 4838 } 4839 } 4840 ++FI; 4841 } 4842 } 4843 4844 /// Check if duplication function is required for taskloops. 4845 static bool checkInitIsRequired(CodeGenFunction &CGF, 4846 ArrayRef<PrivateDataTy> Privates) { 4847 bool InitRequired = false; 4848 for (const PrivateDataTy &Pair : Privates) { 4849 const VarDecl *VD = Pair.second.PrivateCopy; 4850 const Expr *Init = VD->getAnyInitializer(); 4851 InitRequired = InitRequired || (Init && isa<CXXConstructExpr>(Init) && 4852 !CGF.isTrivialInitializer(Init)); 4853 if (InitRequired) 4854 break; 4855 } 4856 return InitRequired; 4857 } 4858 4859 4860 /// Emit task_dup function (for initialization of 4861 /// private/firstprivate/lastprivate vars and last_iter flag) 4862 /// \code 4863 /// void __task_dup_entry(kmp_task_t *task_dst, const kmp_task_t *task_src, int 4864 /// lastpriv) { 4865 /// // setup lastprivate flag 4866 /// task_dst->last = lastpriv; 4867 /// // could be constructor calls here... 4868 /// } 4869 /// \endcode 4870 static llvm::Value * 4871 emitTaskDupFunction(CodeGenModule &CGM, SourceLocation Loc, 4872 const OMPExecutableDirective &D, 4873 QualType KmpTaskTWithPrivatesPtrQTy, 4874 const RecordDecl *KmpTaskTWithPrivatesQTyRD, 4875 const RecordDecl *KmpTaskTQTyRD, QualType SharedsTy, 4876 QualType SharedsPtrTy, const OMPTaskDataTy &Data, 4877 ArrayRef<PrivateDataTy> Privates, bool WithLastIter) { 4878 ASTContext &C = CGM.getContext(); 4879 FunctionArgList Args; 4880 ImplicitParamDecl DstArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4881 KmpTaskTWithPrivatesPtrQTy, 4882 ImplicitParamDecl::Other); 4883 ImplicitParamDecl SrcArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 4884 KmpTaskTWithPrivatesPtrQTy, 4885 ImplicitParamDecl::Other); 4886 ImplicitParamDecl LastprivArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.IntTy, 4887 ImplicitParamDecl::Other); 4888 Args.push_back(&DstArg); 4889 Args.push_back(&SrcArg); 4890 Args.push_back(&LastprivArg); 4891 const auto &TaskDupFnInfo = 4892 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 4893 llvm::FunctionType *TaskDupTy = CGM.getTypes().GetFunctionType(TaskDupFnInfo); 4894 std::string Name = CGM.getOpenMPRuntime().getName({"omp_task_dup", ""}); 4895 auto *TaskDup = llvm::Function::Create( 4896 TaskDupTy, llvm::GlobalValue::InternalLinkage, Name, &CGM.getModule()); 4897 CGM.SetInternalFunctionAttributes(GlobalDecl(), TaskDup, TaskDupFnInfo); 4898 TaskDup->setDoesNotRecurse(); 4899 CodeGenFunction CGF(CGM); 4900 CGF.StartFunction(GlobalDecl(), C.VoidTy, TaskDup, TaskDupFnInfo, Args, Loc, 4901 Loc); 4902 4903 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4904 CGF.GetAddrOfLocalVar(&DstArg), 4905 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4906 // task_dst->liter = lastpriv; 4907 if (WithLastIter) { 4908 auto LIFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTLastIter); 4909 LValue Base = CGF.EmitLValueForField( 4910 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4911 LValue LILVal = CGF.EmitLValueForField(Base, *LIFI); 4912 llvm::Value *Lastpriv = CGF.EmitLoadOfScalar( 4913 CGF.GetAddrOfLocalVar(&LastprivArg), /*Volatile=*/false, C.IntTy, Loc); 4914 CGF.EmitStoreOfScalar(Lastpriv, LILVal); 4915 } 4916 4917 // Emit initial values for private copies (if any). 4918 assert(!Privates.empty()); 4919 Address KmpTaskSharedsPtr = Address::invalid(); 4920 if (!Data.FirstprivateVars.empty()) { 4921 LValue TDBase = CGF.EmitLoadOfPointerLValue( 4922 CGF.GetAddrOfLocalVar(&SrcArg), 4923 KmpTaskTWithPrivatesPtrQTy->castAs<PointerType>()); 4924 LValue Base = CGF.EmitLValueForField( 4925 TDBase, *KmpTaskTWithPrivatesQTyRD->field_begin()); 4926 KmpTaskSharedsPtr = Address( 4927 CGF.EmitLoadOfScalar(CGF.EmitLValueForField( 4928 Base, *std::next(KmpTaskTQTyRD->field_begin(), 4929 KmpTaskTShareds)), 4930 Loc), 4931 CGF.getNaturalTypeAlignment(SharedsTy)); 4932 } 4933 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, TDBase, KmpTaskTWithPrivatesQTyRD, 4934 SharedsTy, SharedsPtrTy, Data, Privates, /*ForDup=*/true); 4935 CGF.FinishFunction(); 4936 return TaskDup; 4937 } 4938 4939 /// Checks if destructor function is required to be generated. 4940 /// \return true if cleanups are required, false otherwise. 4941 static bool 4942 checkDestructorsRequired(const RecordDecl *KmpTaskTWithPrivatesQTyRD) { 4943 bool NeedsCleanup = false; 4944 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin(), 1); 4945 const auto *PrivateRD = cast<RecordDecl>(FI->getType()->getAsTagDecl()); 4946 for (const FieldDecl *FD : PrivateRD->fields()) { 4947 NeedsCleanup = NeedsCleanup || FD->getType().isDestructedType(); 4948 if (NeedsCleanup) 4949 break; 4950 } 4951 return NeedsCleanup; 4952 } 4953 4954 CGOpenMPRuntime::TaskResultTy 4955 CGOpenMPRuntime::emitTaskInit(CodeGenFunction &CGF, SourceLocation Loc, 4956 const OMPExecutableDirective &D, 4957 llvm::Function *TaskFunction, QualType SharedsTy, 4958 Address Shareds, const OMPTaskDataTy &Data) { 4959 ASTContext &C = CGM.getContext(); 4960 llvm::SmallVector<PrivateDataTy, 4> Privates; 4961 // Aggregate privates and sort them by the alignment. 4962 auto I = Data.PrivateCopies.begin(); 4963 for (const Expr *E : Data.PrivateVars) { 4964 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4965 Privates.emplace_back( 4966 C.getDeclAlign(VD), 4967 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4968 /*PrivateElemInit=*/nullptr)); 4969 ++I; 4970 } 4971 I = Data.FirstprivateCopies.begin(); 4972 auto IElemInitRef = Data.FirstprivateInits.begin(); 4973 for (const Expr *E : Data.FirstprivateVars) { 4974 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4975 Privates.emplace_back( 4976 C.getDeclAlign(VD), 4977 PrivateHelpersTy( 4978 VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4979 cast<VarDecl>(cast<DeclRefExpr>(*IElemInitRef)->getDecl()))); 4980 ++I; 4981 ++IElemInitRef; 4982 } 4983 I = Data.LastprivateCopies.begin(); 4984 for (const Expr *E : Data.LastprivateVars) { 4985 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl()); 4986 Privates.emplace_back( 4987 C.getDeclAlign(VD), 4988 PrivateHelpersTy(VD, cast<VarDecl>(cast<DeclRefExpr>(*I)->getDecl()), 4989 /*PrivateElemInit=*/nullptr)); 4990 ++I; 4991 } 4992 llvm::stable_sort(Privates, [](PrivateDataTy L, PrivateDataTy R) { 4993 return L.first > R.first; 4994 }); 4995 QualType KmpInt32Ty = C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/1); 4996 // Build type kmp_routine_entry_t (if not built yet). 4997 emitKmpRoutineEntryT(KmpInt32Ty); 4998 // Build type kmp_task_t (if not built yet). 4999 if (isOpenMPTaskLoopDirective(D.getDirectiveKind())) { 5000 if (SavedKmpTaskloopTQTy.isNull()) { 5001 SavedKmpTaskloopTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5002 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5003 } 5004 KmpTaskTQTy = SavedKmpTaskloopTQTy; 5005 } else { 5006 assert((D.getDirectiveKind() == OMPD_task || 5007 isOpenMPTargetExecutionDirective(D.getDirectiveKind()) || 5008 isOpenMPTargetDataManagementDirective(D.getDirectiveKind())) && 5009 "Expected taskloop, task or target directive"); 5010 if (SavedKmpTaskTQTy.isNull()) { 5011 SavedKmpTaskTQTy = C.getRecordType(createKmpTaskTRecordDecl( 5012 CGM, D.getDirectiveKind(), KmpInt32Ty, KmpRoutineEntryPtrQTy)); 5013 } 5014 KmpTaskTQTy = SavedKmpTaskTQTy; 5015 } 5016 const auto *KmpTaskTQTyRD = cast<RecordDecl>(KmpTaskTQTy->getAsTagDecl()); 5017 // Build particular struct kmp_task_t for the given task. 5018 const RecordDecl *KmpTaskTWithPrivatesQTyRD = 5019 createKmpTaskTWithPrivatesRecordDecl(CGM, KmpTaskTQTy, Privates); 5020 QualType KmpTaskTWithPrivatesQTy = C.getRecordType(KmpTaskTWithPrivatesQTyRD); 5021 QualType KmpTaskTWithPrivatesPtrQTy = 5022 C.getPointerType(KmpTaskTWithPrivatesQTy); 5023 llvm::Type *KmpTaskTWithPrivatesTy = CGF.ConvertType(KmpTaskTWithPrivatesQTy); 5024 llvm::Type *KmpTaskTWithPrivatesPtrTy = 5025 KmpTaskTWithPrivatesTy->getPointerTo(); 5026 llvm::Value *KmpTaskTWithPrivatesTySize = 5027 CGF.getTypeSize(KmpTaskTWithPrivatesQTy); 5028 QualType SharedsPtrTy = C.getPointerType(SharedsTy); 5029 5030 // Emit initial values for private copies (if any). 5031 llvm::Value *TaskPrivatesMap = nullptr; 5032 llvm::Type *TaskPrivatesMapTy = 5033 std::next(TaskFunction->arg_begin(), 3)->getType(); 5034 if (!Privates.empty()) { 5035 auto FI = std::next(KmpTaskTWithPrivatesQTyRD->field_begin()); 5036 TaskPrivatesMap = emitTaskPrivateMappingFunction( 5037 CGM, Loc, Data.PrivateVars, Data.FirstprivateVars, Data.LastprivateVars, 5038 FI->getType(), Privates); 5039 TaskPrivatesMap = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5040 TaskPrivatesMap, TaskPrivatesMapTy); 5041 } else { 5042 TaskPrivatesMap = llvm::ConstantPointerNull::get( 5043 cast<llvm::PointerType>(TaskPrivatesMapTy)); 5044 } 5045 // Build a proxy function kmp_int32 .omp_task_entry.(kmp_int32 gtid, 5046 // kmp_task_t *tt); 5047 llvm::Function *TaskEntry = emitProxyTaskFunction( 5048 CGM, Loc, D.getDirectiveKind(), KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5049 KmpTaskTWithPrivatesQTy, KmpTaskTQTy, SharedsPtrTy, TaskFunction, 5050 TaskPrivatesMap); 5051 5052 // Build call kmp_task_t * __kmpc_omp_task_alloc(ident_t *, kmp_int32 gtid, 5053 // kmp_int32 flags, size_t sizeof_kmp_task_t, size_t sizeof_shareds, 5054 // kmp_routine_entry_t *task_entry); 5055 // Task flags. Format is taken from 5056 // https://github.com/llvm/llvm-project/blob/master/openmp/runtime/src/kmp.h, 5057 // description of kmp_tasking_flags struct. 5058 enum { 5059 TiedFlag = 0x1, 5060 FinalFlag = 0x2, 5061 DestructorsFlag = 0x8, 5062 PriorityFlag = 0x20 5063 }; 5064 unsigned Flags = Data.Tied ? TiedFlag : 0; 5065 bool NeedsCleanup = false; 5066 if (!Privates.empty()) { 5067 NeedsCleanup = checkDestructorsRequired(KmpTaskTWithPrivatesQTyRD); 5068 if (NeedsCleanup) 5069 Flags = Flags | DestructorsFlag; 5070 } 5071 if (Data.Priority.getInt()) 5072 Flags = Flags | PriorityFlag; 5073 llvm::Value *TaskFlags = 5074 Data.Final.getPointer() 5075 ? CGF.Builder.CreateSelect(Data.Final.getPointer(), 5076 CGF.Builder.getInt32(FinalFlag), 5077 CGF.Builder.getInt32(/*C=*/0)) 5078 : CGF.Builder.getInt32(Data.Final.getInt() ? FinalFlag : 0); 5079 TaskFlags = CGF.Builder.CreateOr(TaskFlags, CGF.Builder.getInt32(Flags)); 5080 llvm::Value *SharedsSize = CGM.getSize(C.getTypeSizeInChars(SharedsTy)); 5081 SmallVector<llvm::Value *, 8> AllocArgs = {emitUpdateLocation(CGF, Loc), 5082 getThreadID(CGF, Loc), TaskFlags, KmpTaskTWithPrivatesTySize, 5083 SharedsSize, CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5084 TaskEntry, KmpRoutineEntryPtrTy)}; 5085 llvm::Value *NewTask; 5086 if (D.hasClausesOfKind<OMPNowaitClause>()) { 5087 // Check if we have any device clause associated with the directive. 5088 const Expr *Device = nullptr; 5089 if (auto *C = D.getSingleClause<OMPDeviceClause>()) 5090 Device = C->getDevice(); 5091 // Emit device ID if any otherwise use default value. 5092 llvm::Value *DeviceID; 5093 if (Device) 5094 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 5095 CGF.Int64Ty, /*isSigned=*/true); 5096 else 5097 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 5098 AllocArgs.push_back(DeviceID); 5099 NewTask = CGF.EmitRuntimeCall( 5100 createRuntimeFunction(OMPRTL__kmpc_omp_target_task_alloc), AllocArgs); 5101 } else { 5102 NewTask = CGF.EmitRuntimeCall( 5103 createRuntimeFunction(OMPRTL__kmpc_omp_task_alloc), AllocArgs); 5104 } 5105 llvm::Value *NewTaskNewTaskTTy = 5106 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5107 NewTask, KmpTaskTWithPrivatesPtrTy); 5108 LValue Base = CGF.MakeNaturalAlignAddrLValue(NewTaskNewTaskTTy, 5109 KmpTaskTWithPrivatesQTy); 5110 LValue TDBase = 5111 CGF.EmitLValueForField(Base, *KmpTaskTWithPrivatesQTyRD->field_begin()); 5112 // Fill the data in the resulting kmp_task_t record. 5113 // Copy shareds if there are any. 5114 Address KmpTaskSharedsPtr = Address::invalid(); 5115 if (!SharedsTy->getAsStructureType()->getDecl()->field_empty()) { 5116 KmpTaskSharedsPtr = 5117 Address(CGF.EmitLoadOfScalar( 5118 CGF.EmitLValueForField( 5119 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), 5120 KmpTaskTShareds)), 5121 Loc), 5122 CGF.getNaturalTypeAlignment(SharedsTy)); 5123 LValue Dest = CGF.MakeAddrLValue(KmpTaskSharedsPtr, SharedsTy); 5124 LValue Src = CGF.MakeAddrLValue(Shareds, SharedsTy); 5125 CGF.EmitAggregateCopy(Dest, Src, SharedsTy, AggValueSlot::DoesNotOverlap); 5126 } 5127 // Emit initial values for private copies (if any). 5128 TaskResultTy Result; 5129 if (!Privates.empty()) { 5130 emitPrivatesInit(CGF, D, KmpTaskSharedsPtr, Base, KmpTaskTWithPrivatesQTyRD, 5131 SharedsTy, SharedsPtrTy, Data, Privates, 5132 /*ForDup=*/false); 5133 if (isOpenMPTaskLoopDirective(D.getDirectiveKind()) && 5134 (!Data.LastprivateVars.empty() || checkInitIsRequired(CGF, Privates))) { 5135 Result.TaskDupFn = emitTaskDupFunction( 5136 CGM, Loc, D, KmpTaskTWithPrivatesPtrQTy, KmpTaskTWithPrivatesQTyRD, 5137 KmpTaskTQTyRD, SharedsTy, SharedsPtrTy, Data, Privates, 5138 /*WithLastIter=*/!Data.LastprivateVars.empty()); 5139 } 5140 } 5141 // Fields of union "kmp_cmplrdata_t" for destructors and priority. 5142 enum { Priority = 0, Destructors = 1 }; 5143 // Provide pointer to function with destructors for privates. 5144 auto FI = std::next(KmpTaskTQTyRD->field_begin(), Data1); 5145 const RecordDecl *KmpCmplrdataUD = 5146 (*FI)->getType()->getAsUnionType()->getDecl(); 5147 if (NeedsCleanup) { 5148 llvm::Value *DestructorFn = emitDestructorsFunction( 5149 CGM, Loc, KmpInt32Ty, KmpTaskTWithPrivatesPtrQTy, 5150 KmpTaskTWithPrivatesQTy); 5151 LValue Data1LV = CGF.EmitLValueForField(TDBase, *FI); 5152 LValue DestructorsLV = CGF.EmitLValueForField( 5153 Data1LV, *std::next(KmpCmplrdataUD->field_begin(), Destructors)); 5154 CGF.EmitStoreOfScalar(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5155 DestructorFn, KmpRoutineEntryPtrTy), 5156 DestructorsLV); 5157 } 5158 // Set priority. 5159 if (Data.Priority.getInt()) { 5160 LValue Data2LV = CGF.EmitLValueForField( 5161 TDBase, *std::next(KmpTaskTQTyRD->field_begin(), Data2)); 5162 LValue PriorityLV = CGF.EmitLValueForField( 5163 Data2LV, *std::next(KmpCmplrdataUD->field_begin(), Priority)); 5164 CGF.EmitStoreOfScalar(Data.Priority.getPointer(), PriorityLV); 5165 } 5166 Result.NewTask = NewTask; 5167 Result.TaskEntry = TaskEntry; 5168 Result.NewTaskNewTaskTTy = NewTaskNewTaskTTy; 5169 Result.TDBase = TDBase; 5170 Result.KmpTaskTQTyRD = KmpTaskTQTyRD; 5171 return Result; 5172 } 5173 5174 void CGOpenMPRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 5175 const OMPExecutableDirective &D, 5176 llvm::Function *TaskFunction, 5177 QualType SharedsTy, Address Shareds, 5178 const Expr *IfCond, 5179 const OMPTaskDataTy &Data) { 5180 if (!CGF.HaveInsertPoint()) 5181 return; 5182 5183 TaskResultTy Result = 5184 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5185 llvm::Value *NewTask = Result.NewTask; 5186 llvm::Function *TaskEntry = Result.TaskEntry; 5187 llvm::Value *NewTaskNewTaskTTy = Result.NewTaskNewTaskTTy; 5188 LValue TDBase = Result.TDBase; 5189 const RecordDecl *KmpTaskTQTyRD = Result.KmpTaskTQTyRD; 5190 ASTContext &C = CGM.getContext(); 5191 // Process list of dependences. 5192 Address DependenciesArray = Address::invalid(); 5193 unsigned NumDependencies = Data.Dependences.size(); 5194 if (NumDependencies) { 5195 // Dependence kind for RTL. 5196 enum RTLDependenceKindTy { DepIn = 0x01, DepInOut = 0x3, DepMutexInOutSet = 0x4 }; 5197 enum RTLDependInfoFieldsTy { BaseAddr, Len, Flags }; 5198 RecordDecl *KmpDependInfoRD; 5199 QualType FlagsTy = 5200 C.getIntTypeForBitwidth(C.getTypeSize(C.BoolTy), /*Signed=*/false); 5201 llvm::Type *LLVMFlagsTy = CGF.ConvertTypeForMem(FlagsTy); 5202 if (KmpDependInfoTy.isNull()) { 5203 KmpDependInfoRD = C.buildImplicitRecord("kmp_depend_info"); 5204 KmpDependInfoRD->startDefinition(); 5205 addFieldToRecordDecl(C, KmpDependInfoRD, C.getIntPtrType()); 5206 addFieldToRecordDecl(C, KmpDependInfoRD, C.getSizeType()); 5207 addFieldToRecordDecl(C, KmpDependInfoRD, FlagsTy); 5208 KmpDependInfoRD->completeDefinition(); 5209 KmpDependInfoTy = C.getRecordType(KmpDependInfoRD); 5210 } else { 5211 KmpDependInfoRD = cast<RecordDecl>(KmpDependInfoTy->getAsTagDecl()); 5212 } 5213 // Define type kmp_depend_info[<Dependences.size()>]; 5214 QualType KmpDependInfoArrayTy = C.getConstantArrayType( 5215 KmpDependInfoTy, llvm::APInt(/*numBits=*/64, NumDependencies), 5216 nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 5217 // kmp_depend_info[<Dependences.size()>] deps; 5218 DependenciesArray = 5219 CGF.CreateMemTemp(KmpDependInfoArrayTy, ".dep.arr.addr"); 5220 for (unsigned I = 0; I < NumDependencies; ++I) { 5221 const Expr *E = Data.Dependences[I].second; 5222 LValue Addr = CGF.EmitLValue(E); 5223 llvm::Value *Size; 5224 QualType Ty = E->getType(); 5225 if (const auto *ASE = 5226 dyn_cast<OMPArraySectionExpr>(E->IgnoreParenImpCasts())) { 5227 LValue UpAddrLVal = 5228 CGF.EmitOMPArraySectionExpr(ASE, /*IsLowerBound=*/false); 5229 llvm::Value *UpAddr = 5230 CGF.Builder.CreateConstGEP1_32(UpAddrLVal.getPointer(), /*Idx0=*/1); 5231 llvm::Value *LowIntPtr = 5232 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGM.SizeTy); 5233 llvm::Value *UpIntPtr = CGF.Builder.CreatePtrToInt(UpAddr, CGM.SizeTy); 5234 Size = CGF.Builder.CreateNUWSub(UpIntPtr, LowIntPtr); 5235 } else { 5236 Size = CGF.getTypeSize(Ty); 5237 } 5238 LValue Base = CGF.MakeAddrLValue( 5239 CGF.Builder.CreateConstArrayGEP(DependenciesArray, I), 5240 KmpDependInfoTy); 5241 // deps[i].base_addr = &<Dependences[i].second>; 5242 LValue BaseAddrLVal = CGF.EmitLValueForField( 5243 Base, *std::next(KmpDependInfoRD->field_begin(), BaseAddr)); 5244 CGF.EmitStoreOfScalar( 5245 CGF.Builder.CreatePtrToInt(Addr.getPointer(), CGF.IntPtrTy), 5246 BaseAddrLVal); 5247 // deps[i].len = sizeof(<Dependences[i].second>); 5248 LValue LenLVal = CGF.EmitLValueForField( 5249 Base, *std::next(KmpDependInfoRD->field_begin(), Len)); 5250 CGF.EmitStoreOfScalar(Size, LenLVal); 5251 // deps[i].flags = <Dependences[i].first>; 5252 RTLDependenceKindTy DepKind; 5253 switch (Data.Dependences[I].first) { 5254 case OMPC_DEPEND_in: 5255 DepKind = DepIn; 5256 break; 5257 // Out and InOut dependencies must use the same code. 5258 case OMPC_DEPEND_out: 5259 case OMPC_DEPEND_inout: 5260 DepKind = DepInOut; 5261 break; 5262 case OMPC_DEPEND_mutexinoutset: 5263 DepKind = DepMutexInOutSet; 5264 break; 5265 case OMPC_DEPEND_source: 5266 case OMPC_DEPEND_sink: 5267 case OMPC_DEPEND_unknown: 5268 llvm_unreachable("Unknown task dependence type"); 5269 } 5270 LValue FlagsLVal = CGF.EmitLValueForField( 5271 Base, *std::next(KmpDependInfoRD->field_begin(), Flags)); 5272 CGF.EmitStoreOfScalar(llvm::ConstantInt::get(LLVMFlagsTy, DepKind), 5273 FlagsLVal); 5274 } 5275 DependenciesArray = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5276 CGF.Builder.CreateConstArrayGEP(DependenciesArray, 0), CGF.VoidPtrTy); 5277 } 5278 5279 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5280 // libcall. 5281 // Build kmp_int32 __kmpc_omp_task_with_deps(ident_t *, kmp_int32 gtid, 5282 // kmp_task_t *new_task, kmp_int32 ndeps, kmp_depend_info_t *dep_list, 5283 // kmp_int32 ndeps_noalias, kmp_depend_info_t *noalias_dep_list) if dependence 5284 // list is not empty 5285 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5286 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5287 llvm::Value *TaskArgs[] = { UpLoc, ThreadID, NewTask }; 5288 llvm::Value *DepTaskArgs[7]; 5289 if (NumDependencies) { 5290 DepTaskArgs[0] = UpLoc; 5291 DepTaskArgs[1] = ThreadID; 5292 DepTaskArgs[2] = NewTask; 5293 DepTaskArgs[3] = CGF.Builder.getInt32(NumDependencies); 5294 DepTaskArgs[4] = DependenciesArray.getPointer(); 5295 DepTaskArgs[5] = CGF.Builder.getInt32(0); 5296 DepTaskArgs[6] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5297 } 5298 auto &&ThenCodeGen = [this, &Data, TDBase, KmpTaskTQTyRD, NumDependencies, 5299 &TaskArgs, 5300 &DepTaskArgs](CodeGenFunction &CGF, PrePostActionTy &) { 5301 if (!Data.Tied) { 5302 auto PartIdFI = std::next(KmpTaskTQTyRD->field_begin(), KmpTaskTPartId); 5303 LValue PartIdLVal = CGF.EmitLValueForField(TDBase, *PartIdFI); 5304 CGF.EmitStoreOfScalar(CGF.Builder.getInt32(0), PartIdLVal); 5305 } 5306 if (NumDependencies) { 5307 CGF.EmitRuntimeCall( 5308 createRuntimeFunction(OMPRTL__kmpc_omp_task_with_deps), DepTaskArgs); 5309 } else { 5310 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_task), 5311 TaskArgs); 5312 } 5313 // Check if parent region is untied and build return for untied task; 5314 if (auto *Region = 5315 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 5316 Region->emitUntiedSwitch(CGF); 5317 }; 5318 5319 llvm::Value *DepWaitTaskArgs[6]; 5320 if (NumDependencies) { 5321 DepWaitTaskArgs[0] = UpLoc; 5322 DepWaitTaskArgs[1] = ThreadID; 5323 DepWaitTaskArgs[2] = CGF.Builder.getInt32(NumDependencies); 5324 DepWaitTaskArgs[3] = DependenciesArray.getPointer(); 5325 DepWaitTaskArgs[4] = CGF.Builder.getInt32(0); 5326 DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy); 5327 } 5328 auto &&ElseCodeGen = [&TaskArgs, ThreadID, NewTaskNewTaskTTy, TaskEntry, 5329 NumDependencies, &DepWaitTaskArgs, 5330 Loc](CodeGenFunction &CGF, PrePostActionTy &) { 5331 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5332 CodeGenFunction::RunCleanupsScope LocalScope(CGF); 5333 // Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid, 5334 // kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32 5335 // ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info 5336 // is specified. 5337 if (NumDependencies) 5338 CGF.EmitRuntimeCall(RT.createRuntimeFunction(OMPRTL__kmpc_omp_wait_deps), 5339 DepWaitTaskArgs); 5340 // Call proxy_task_entry(gtid, new_task); 5341 auto &&CodeGen = [TaskEntry, ThreadID, NewTaskNewTaskTTy, 5342 Loc](CodeGenFunction &CGF, PrePostActionTy &Action) { 5343 Action.Enter(CGF); 5344 llvm::Value *OutlinedFnArgs[] = {ThreadID, NewTaskNewTaskTTy}; 5345 CGF.CGM.getOpenMPRuntime().emitOutlinedFunctionCall(CGF, Loc, TaskEntry, 5346 OutlinedFnArgs); 5347 }; 5348 5349 // Build void __kmpc_omp_task_begin_if0(ident_t *, kmp_int32 gtid, 5350 // kmp_task_t *new_task); 5351 // Build void __kmpc_omp_task_complete_if0(ident_t *, kmp_int32 gtid, 5352 // kmp_task_t *new_task); 5353 RegionCodeGenTy RCG(CodeGen); 5354 CommonActionTy Action( 5355 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_begin_if0), TaskArgs, 5356 RT.createRuntimeFunction(OMPRTL__kmpc_omp_task_complete_if0), TaskArgs); 5357 RCG.setAction(Action); 5358 RCG(CGF); 5359 }; 5360 5361 if (IfCond) { 5362 emitOMPIfClause(CGF, IfCond, ThenCodeGen, ElseCodeGen); 5363 } else { 5364 RegionCodeGenTy ThenRCG(ThenCodeGen); 5365 ThenRCG(CGF); 5366 } 5367 } 5368 5369 void CGOpenMPRuntime::emitTaskLoopCall(CodeGenFunction &CGF, SourceLocation Loc, 5370 const OMPLoopDirective &D, 5371 llvm::Function *TaskFunction, 5372 QualType SharedsTy, Address Shareds, 5373 const Expr *IfCond, 5374 const OMPTaskDataTy &Data) { 5375 if (!CGF.HaveInsertPoint()) 5376 return; 5377 TaskResultTy Result = 5378 emitTaskInit(CGF, Loc, D, TaskFunction, SharedsTy, Shareds, Data); 5379 // NOTE: routine and part_id fields are initialized by __kmpc_omp_task_alloc() 5380 // libcall. 5381 // Call to void __kmpc_taskloop(ident_t *loc, int gtid, kmp_task_t *task, int 5382 // if_val, kmp_uint64 *lb, kmp_uint64 *ub, kmp_int64 st, int nogroup, int 5383 // sched, kmp_uint64 grainsize, void *task_dup); 5384 llvm::Value *ThreadID = getThreadID(CGF, Loc); 5385 llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc); 5386 llvm::Value *IfVal; 5387 if (IfCond) { 5388 IfVal = CGF.Builder.CreateIntCast(CGF.EvaluateExprAsBool(IfCond), CGF.IntTy, 5389 /*isSigned=*/true); 5390 } else { 5391 IfVal = llvm::ConstantInt::getSigned(CGF.IntTy, /*V=*/1); 5392 } 5393 5394 LValue LBLVal = CGF.EmitLValueForField( 5395 Result.TDBase, 5396 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTLowerBound)); 5397 const auto *LBVar = 5398 cast<VarDecl>(cast<DeclRefExpr>(D.getLowerBoundVariable())->getDecl()); 5399 CGF.EmitAnyExprToMem(LBVar->getInit(), LBLVal.getAddress(), LBLVal.getQuals(), 5400 /*IsInitializer=*/true); 5401 LValue UBLVal = CGF.EmitLValueForField( 5402 Result.TDBase, 5403 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTUpperBound)); 5404 const auto *UBVar = 5405 cast<VarDecl>(cast<DeclRefExpr>(D.getUpperBoundVariable())->getDecl()); 5406 CGF.EmitAnyExprToMem(UBVar->getInit(), UBLVal.getAddress(), UBLVal.getQuals(), 5407 /*IsInitializer=*/true); 5408 LValue StLVal = CGF.EmitLValueForField( 5409 Result.TDBase, 5410 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTStride)); 5411 const auto *StVar = 5412 cast<VarDecl>(cast<DeclRefExpr>(D.getStrideVariable())->getDecl()); 5413 CGF.EmitAnyExprToMem(StVar->getInit(), StLVal.getAddress(), StLVal.getQuals(), 5414 /*IsInitializer=*/true); 5415 // Store reductions address. 5416 LValue RedLVal = CGF.EmitLValueForField( 5417 Result.TDBase, 5418 *std::next(Result.KmpTaskTQTyRD->field_begin(), KmpTaskTReductions)); 5419 if (Data.Reductions) { 5420 CGF.EmitStoreOfScalar(Data.Reductions, RedLVal); 5421 } else { 5422 CGF.EmitNullInitialization(RedLVal.getAddress(), 5423 CGF.getContext().VoidPtrTy); 5424 } 5425 enum { NoSchedule = 0, Grainsize = 1, NumTasks = 2 }; 5426 llvm::Value *TaskArgs[] = { 5427 UpLoc, 5428 ThreadID, 5429 Result.NewTask, 5430 IfVal, 5431 LBLVal.getPointer(), 5432 UBLVal.getPointer(), 5433 CGF.EmitLoadOfScalar(StLVal, Loc), 5434 llvm::ConstantInt::getSigned( 5435 CGF.IntTy, 1), // Always 1 because taskgroup emitted by the compiler 5436 llvm::ConstantInt::getSigned( 5437 CGF.IntTy, Data.Schedule.getPointer() 5438 ? Data.Schedule.getInt() ? NumTasks : Grainsize 5439 : NoSchedule), 5440 Data.Schedule.getPointer() 5441 ? CGF.Builder.CreateIntCast(Data.Schedule.getPointer(), CGF.Int64Ty, 5442 /*isSigned=*/false) 5443 : llvm::ConstantInt::get(CGF.Int64Ty, /*V=*/0), 5444 Result.TaskDupFn ? CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5445 Result.TaskDupFn, CGF.VoidPtrTy) 5446 : llvm::ConstantPointerNull::get(CGF.VoidPtrTy)}; 5447 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_taskloop), TaskArgs); 5448 } 5449 5450 /// Emit reduction operation for each element of array (required for 5451 /// array sections) LHS op = RHS. 5452 /// \param Type Type of array. 5453 /// \param LHSVar Variable on the left side of the reduction operation 5454 /// (references element of array in original variable). 5455 /// \param RHSVar Variable on the right side of the reduction operation 5456 /// (references element of array in original variable). 5457 /// \param RedOpGen Generator of reduction operation with use of LHSVar and 5458 /// RHSVar. 5459 static void EmitOMPAggregateReduction( 5460 CodeGenFunction &CGF, QualType Type, const VarDecl *LHSVar, 5461 const VarDecl *RHSVar, 5462 const llvm::function_ref<void(CodeGenFunction &CGF, const Expr *, 5463 const Expr *, const Expr *)> &RedOpGen, 5464 const Expr *XExpr = nullptr, const Expr *EExpr = nullptr, 5465 const Expr *UpExpr = nullptr) { 5466 // Perform element-by-element initialization. 5467 QualType ElementTy; 5468 Address LHSAddr = CGF.GetAddrOfLocalVar(LHSVar); 5469 Address RHSAddr = CGF.GetAddrOfLocalVar(RHSVar); 5470 5471 // Drill down to the base element type on both arrays. 5472 const ArrayType *ArrayTy = Type->getAsArrayTypeUnsafe(); 5473 llvm::Value *NumElements = CGF.emitArrayLength(ArrayTy, ElementTy, LHSAddr); 5474 5475 llvm::Value *RHSBegin = RHSAddr.getPointer(); 5476 llvm::Value *LHSBegin = LHSAddr.getPointer(); 5477 // Cast from pointer to array type to pointer to single element. 5478 llvm::Value *LHSEnd = CGF.Builder.CreateGEP(LHSBegin, NumElements); 5479 // The basic structure here is a while-do loop. 5480 llvm::BasicBlock *BodyBB = CGF.createBasicBlock("omp.arraycpy.body"); 5481 llvm::BasicBlock *DoneBB = CGF.createBasicBlock("omp.arraycpy.done"); 5482 llvm::Value *IsEmpty = 5483 CGF.Builder.CreateICmpEQ(LHSBegin, LHSEnd, "omp.arraycpy.isempty"); 5484 CGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 5485 5486 // Enter the loop body, making that address the current address. 5487 llvm::BasicBlock *EntryBB = CGF.Builder.GetInsertBlock(); 5488 CGF.EmitBlock(BodyBB); 5489 5490 CharUnits ElementSize = CGF.getContext().getTypeSizeInChars(ElementTy); 5491 5492 llvm::PHINode *RHSElementPHI = CGF.Builder.CreatePHI( 5493 RHSBegin->getType(), 2, "omp.arraycpy.srcElementPast"); 5494 RHSElementPHI->addIncoming(RHSBegin, EntryBB); 5495 Address RHSElementCurrent = 5496 Address(RHSElementPHI, 5497 RHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5498 5499 llvm::PHINode *LHSElementPHI = CGF.Builder.CreatePHI( 5500 LHSBegin->getType(), 2, "omp.arraycpy.destElementPast"); 5501 LHSElementPHI->addIncoming(LHSBegin, EntryBB); 5502 Address LHSElementCurrent = 5503 Address(LHSElementPHI, 5504 LHSAddr.getAlignment().alignmentOfArrayElement(ElementSize)); 5505 5506 // Emit copy. 5507 CodeGenFunction::OMPPrivateScope Scope(CGF); 5508 Scope.addPrivate(LHSVar, [=]() { return LHSElementCurrent; }); 5509 Scope.addPrivate(RHSVar, [=]() { return RHSElementCurrent; }); 5510 Scope.Privatize(); 5511 RedOpGen(CGF, XExpr, EExpr, UpExpr); 5512 Scope.ForceCleanup(); 5513 5514 // Shift the address forward by one element. 5515 llvm::Value *LHSElementNext = CGF.Builder.CreateConstGEP1_32( 5516 LHSElementPHI, /*Idx0=*/1, "omp.arraycpy.dest.element"); 5517 llvm::Value *RHSElementNext = CGF.Builder.CreateConstGEP1_32( 5518 RHSElementPHI, /*Idx0=*/1, "omp.arraycpy.src.element"); 5519 // Check whether we've reached the end. 5520 llvm::Value *Done = 5521 CGF.Builder.CreateICmpEQ(LHSElementNext, LHSEnd, "omp.arraycpy.done"); 5522 CGF.Builder.CreateCondBr(Done, DoneBB, BodyBB); 5523 LHSElementPHI->addIncoming(LHSElementNext, CGF.Builder.GetInsertBlock()); 5524 RHSElementPHI->addIncoming(RHSElementNext, CGF.Builder.GetInsertBlock()); 5525 5526 // Done. 5527 CGF.EmitBlock(DoneBB, /*IsFinished=*/true); 5528 } 5529 5530 /// Emit reduction combiner. If the combiner is a simple expression emit it as 5531 /// is, otherwise consider it as combiner of UDR decl and emit it as a call of 5532 /// UDR combiner function. 5533 static void emitReductionCombiner(CodeGenFunction &CGF, 5534 const Expr *ReductionOp) { 5535 if (const auto *CE = dyn_cast<CallExpr>(ReductionOp)) 5536 if (const auto *OVE = dyn_cast<OpaqueValueExpr>(CE->getCallee())) 5537 if (const auto *DRE = 5538 dyn_cast<DeclRefExpr>(OVE->getSourceExpr()->IgnoreImpCasts())) 5539 if (const auto *DRD = 5540 dyn_cast<OMPDeclareReductionDecl>(DRE->getDecl())) { 5541 std::pair<llvm::Function *, llvm::Function *> Reduction = 5542 CGF.CGM.getOpenMPRuntime().getUserDefinedReduction(DRD); 5543 RValue Func = RValue::get(Reduction.first); 5544 CodeGenFunction::OpaqueValueMapping Map(CGF, OVE, Func); 5545 CGF.EmitIgnoredExpr(ReductionOp); 5546 return; 5547 } 5548 CGF.EmitIgnoredExpr(ReductionOp); 5549 } 5550 5551 llvm::Function *CGOpenMPRuntime::emitReductionFunction( 5552 SourceLocation Loc, llvm::Type *ArgsType, ArrayRef<const Expr *> Privates, 5553 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 5554 ArrayRef<const Expr *> ReductionOps) { 5555 ASTContext &C = CGM.getContext(); 5556 5557 // void reduction_func(void *LHSArg, void *RHSArg); 5558 FunctionArgList Args; 5559 ImplicitParamDecl LHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5560 ImplicitParamDecl::Other); 5561 ImplicitParamDecl RHSArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5562 ImplicitParamDecl::Other); 5563 Args.push_back(&LHSArg); 5564 Args.push_back(&RHSArg); 5565 const auto &CGFI = 5566 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 5567 std::string Name = getName({"omp", "reduction", "reduction_func"}); 5568 auto *Fn = llvm::Function::Create(CGM.getTypes().GetFunctionType(CGFI), 5569 llvm::GlobalValue::InternalLinkage, Name, 5570 &CGM.getModule()); 5571 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, CGFI); 5572 Fn->setDoesNotRecurse(); 5573 CodeGenFunction CGF(CGM); 5574 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, CGFI, Args, Loc, Loc); 5575 5576 // Dst = (void*[n])(LHSArg); 5577 // Src = (void*[n])(RHSArg); 5578 Address LHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5579 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&LHSArg)), 5580 ArgsType), CGF.getPointerAlign()); 5581 Address RHS(CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5582 CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&RHSArg)), 5583 ArgsType), CGF.getPointerAlign()); 5584 5585 // ... 5586 // *(Type<i>*)lhs[i] = RedOp<i>(*(Type<i>*)lhs[i], *(Type<i>*)rhs[i]); 5587 // ... 5588 CodeGenFunction::OMPPrivateScope Scope(CGF); 5589 auto IPriv = Privates.begin(); 5590 unsigned Idx = 0; 5591 for (unsigned I = 0, E = ReductionOps.size(); I < E; ++I, ++IPriv, ++Idx) { 5592 const auto *RHSVar = 5593 cast<VarDecl>(cast<DeclRefExpr>(RHSExprs[I])->getDecl()); 5594 Scope.addPrivate(RHSVar, [&CGF, RHS, Idx, RHSVar]() { 5595 return emitAddrOfVarFromArray(CGF, RHS, Idx, RHSVar); 5596 }); 5597 const auto *LHSVar = 5598 cast<VarDecl>(cast<DeclRefExpr>(LHSExprs[I])->getDecl()); 5599 Scope.addPrivate(LHSVar, [&CGF, LHS, Idx, LHSVar]() { 5600 return emitAddrOfVarFromArray(CGF, LHS, Idx, LHSVar); 5601 }); 5602 QualType PrivTy = (*IPriv)->getType(); 5603 if (PrivTy->isVariablyModifiedType()) { 5604 // Get array size and emit VLA type. 5605 ++Idx; 5606 Address Elem = CGF.Builder.CreateConstArrayGEP(LHS, Idx); 5607 llvm::Value *Ptr = CGF.Builder.CreateLoad(Elem); 5608 const VariableArrayType *VLA = 5609 CGF.getContext().getAsVariableArrayType(PrivTy); 5610 const auto *OVE = cast<OpaqueValueExpr>(VLA->getSizeExpr()); 5611 CodeGenFunction::OpaqueValueMapping OpaqueMap( 5612 CGF, OVE, RValue::get(CGF.Builder.CreatePtrToInt(Ptr, CGF.SizeTy))); 5613 CGF.EmitVariablyModifiedType(PrivTy); 5614 } 5615 } 5616 Scope.Privatize(); 5617 IPriv = Privates.begin(); 5618 auto ILHS = LHSExprs.begin(); 5619 auto IRHS = RHSExprs.begin(); 5620 for (const Expr *E : ReductionOps) { 5621 if ((*IPriv)->getType()->isArrayType()) { 5622 // Emit reduction for array section. 5623 const auto *LHSVar = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5624 const auto *RHSVar = cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5625 EmitOMPAggregateReduction( 5626 CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5627 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5628 emitReductionCombiner(CGF, E); 5629 }); 5630 } else { 5631 // Emit reduction for array subscript or single variable. 5632 emitReductionCombiner(CGF, E); 5633 } 5634 ++IPriv; 5635 ++ILHS; 5636 ++IRHS; 5637 } 5638 Scope.ForceCleanup(); 5639 CGF.FinishFunction(); 5640 return Fn; 5641 } 5642 5643 void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, 5644 const Expr *ReductionOp, 5645 const Expr *PrivateRef, 5646 const DeclRefExpr *LHS, 5647 const DeclRefExpr *RHS) { 5648 if (PrivateRef->getType()->isArrayType()) { 5649 // Emit reduction for array section. 5650 const auto *LHSVar = cast<VarDecl>(LHS->getDecl()); 5651 const auto *RHSVar = cast<VarDecl>(RHS->getDecl()); 5652 EmitOMPAggregateReduction( 5653 CGF, PrivateRef->getType(), LHSVar, RHSVar, 5654 [=](CodeGenFunction &CGF, const Expr *, const Expr *, const Expr *) { 5655 emitReductionCombiner(CGF, ReductionOp); 5656 }); 5657 } else { 5658 // Emit reduction for array subscript or single variable. 5659 emitReductionCombiner(CGF, ReductionOp); 5660 } 5661 } 5662 5663 void CGOpenMPRuntime::emitReduction(CodeGenFunction &CGF, SourceLocation Loc, 5664 ArrayRef<const Expr *> Privates, 5665 ArrayRef<const Expr *> LHSExprs, 5666 ArrayRef<const Expr *> RHSExprs, 5667 ArrayRef<const Expr *> ReductionOps, 5668 ReductionOptionsTy Options) { 5669 if (!CGF.HaveInsertPoint()) 5670 return; 5671 5672 bool WithNowait = Options.WithNowait; 5673 bool SimpleReduction = Options.SimpleReduction; 5674 5675 // Next code should be emitted for reduction: 5676 // 5677 // static kmp_critical_name lock = { 0 }; 5678 // 5679 // void reduce_func(void *lhs[<n>], void *rhs[<n>]) { 5680 // *(Type0*)lhs[0] = ReductionOperation0(*(Type0*)lhs[0], *(Type0*)rhs[0]); 5681 // ... 5682 // *(Type<n>-1*)lhs[<n>-1] = ReductionOperation<n>-1(*(Type<n>-1*)lhs[<n>-1], 5683 // *(Type<n>-1*)rhs[<n>-1]); 5684 // } 5685 // 5686 // ... 5687 // void *RedList[<n>] = {&<RHSExprs>[0], ..., &<RHSExprs>[<n>-1]}; 5688 // switch (__kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5689 // RedList, reduce_func, &<lock>)) { 5690 // case 1: 5691 // ... 5692 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5693 // ... 5694 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5695 // break; 5696 // case 2: 5697 // ... 5698 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5699 // ... 5700 // [__kmpc_end_reduce(<loc>, <gtid>, &<lock>);] 5701 // break; 5702 // default:; 5703 // } 5704 // 5705 // if SimpleReduction is true, only the next code is generated: 5706 // ... 5707 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5708 // ... 5709 5710 ASTContext &C = CGM.getContext(); 5711 5712 if (SimpleReduction) { 5713 CodeGenFunction::RunCleanupsScope Scope(CGF); 5714 auto IPriv = Privates.begin(); 5715 auto ILHS = LHSExprs.begin(); 5716 auto IRHS = RHSExprs.begin(); 5717 for (const Expr *E : ReductionOps) { 5718 emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5719 cast<DeclRefExpr>(*IRHS)); 5720 ++IPriv; 5721 ++ILHS; 5722 ++IRHS; 5723 } 5724 return; 5725 } 5726 5727 // 1. Build a list of reduction variables. 5728 // void *RedList[<n>] = {<ReductionVars>[0], ..., <ReductionVars>[<n>-1]}; 5729 auto Size = RHSExprs.size(); 5730 for (const Expr *E : Privates) { 5731 if (E->getType()->isVariablyModifiedType()) 5732 // Reserve place for array size. 5733 ++Size; 5734 } 5735 llvm::APInt ArraySize(/*unsigned int numBits=*/32, Size); 5736 QualType ReductionArrayTy = 5737 C.getConstantArrayType(C.VoidPtrTy, ArraySize, nullptr, ArrayType::Normal, 5738 /*IndexTypeQuals=*/0); 5739 Address ReductionList = 5740 CGF.CreateMemTemp(ReductionArrayTy, ".omp.reduction.red_list"); 5741 auto IPriv = Privates.begin(); 5742 unsigned Idx = 0; 5743 for (unsigned I = 0, E = RHSExprs.size(); I < E; ++I, ++IPriv, ++Idx) { 5744 Address Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5745 CGF.Builder.CreateStore( 5746 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5747 CGF.EmitLValue(RHSExprs[I]).getPointer(), CGF.VoidPtrTy), 5748 Elem); 5749 if ((*IPriv)->getType()->isVariablyModifiedType()) { 5750 // Store array size. 5751 ++Idx; 5752 Elem = CGF.Builder.CreateConstArrayGEP(ReductionList, Idx); 5753 llvm::Value *Size = CGF.Builder.CreateIntCast( 5754 CGF.getVLASize( 5755 CGF.getContext().getAsVariableArrayType((*IPriv)->getType())) 5756 .NumElts, 5757 CGF.SizeTy, /*isSigned=*/false); 5758 CGF.Builder.CreateStore(CGF.Builder.CreateIntToPtr(Size, CGF.VoidPtrTy), 5759 Elem); 5760 } 5761 } 5762 5763 // 2. Emit reduce_func(). 5764 llvm::Function *ReductionFn = emitReductionFunction( 5765 Loc, CGF.ConvertTypeForMem(ReductionArrayTy)->getPointerTo(), Privates, 5766 LHSExprs, RHSExprs, ReductionOps); 5767 5768 // 3. Create static kmp_critical_name lock = { 0 }; 5769 std::string Name = getName({"reduction"}); 5770 llvm::Value *Lock = getCriticalRegionLock(Name); 5771 5772 // 4. Build res = __kmpc_reduce{_nowait}(<loc>, <gtid>, <n>, sizeof(RedList), 5773 // RedList, reduce_func, &<lock>); 5774 llvm::Value *IdentTLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); 5775 llvm::Value *ThreadId = getThreadID(CGF, Loc); 5776 llvm::Value *ReductionArrayTySize = CGF.getTypeSize(ReductionArrayTy); 5777 llvm::Value *RL = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 5778 ReductionList.getPointer(), CGF.VoidPtrTy); 5779 llvm::Value *Args[] = { 5780 IdentTLoc, // ident_t *<loc> 5781 ThreadId, // i32 <gtid> 5782 CGF.Builder.getInt32(RHSExprs.size()), // i32 <n> 5783 ReductionArrayTySize, // size_type sizeof(RedList) 5784 RL, // void *RedList 5785 ReductionFn, // void (*) (void *, void *) <reduce_func> 5786 Lock // kmp_critical_name *&<lock> 5787 }; 5788 llvm::Value *Res = CGF.EmitRuntimeCall( 5789 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_reduce_nowait 5790 : OMPRTL__kmpc_reduce), 5791 Args); 5792 5793 // 5. Build switch(res) 5794 llvm::BasicBlock *DefaultBB = CGF.createBasicBlock(".omp.reduction.default"); 5795 llvm::SwitchInst *SwInst = 5796 CGF.Builder.CreateSwitch(Res, DefaultBB, /*NumCases=*/2); 5797 5798 // 6. Build case 1: 5799 // ... 5800 // <LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i]); 5801 // ... 5802 // __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5803 // break; 5804 llvm::BasicBlock *Case1BB = CGF.createBasicBlock(".omp.reduction.case1"); 5805 SwInst->addCase(CGF.Builder.getInt32(1), Case1BB); 5806 CGF.EmitBlock(Case1BB); 5807 5808 // Add emission of __kmpc_end_reduce{_nowait}(<loc>, <gtid>, &<lock>); 5809 llvm::Value *EndArgs[] = { 5810 IdentTLoc, // ident_t *<loc> 5811 ThreadId, // i32 <gtid> 5812 Lock // kmp_critical_name *&<lock> 5813 }; 5814 auto &&CodeGen = [Privates, LHSExprs, RHSExprs, ReductionOps]( 5815 CodeGenFunction &CGF, PrePostActionTy &Action) { 5816 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5817 auto IPriv = Privates.begin(); 5818 auto ILHS = LHSExprs.begin(); 5819 auto IRHS = RHSExprs.begin(); 5820 for (const Expr *E : ReductionOps) { 5821 RT.emitSingleReductionCombiner(CGF, E, *IPriv, cast<DeclRefExpr>(*ILHS), 5822 cast<DeclRefExpr>(*IRHS)); 5823 ++IPriv; 5824 ++ILHS; 5825 ++IRHS; 5826 } 5827 }; 5828 RegionCodeGenTy RCG(CodeGen); 5829 CommonActionTy Action( 5830 nullptr, llvm::None, 5831 createRuntimeFunction(WithNowait ? OMPRTL__kmpc_end_reduce_nowait 5832 : OMPRTL__kmpc_end_reduce), 5833 EndArgs); 5834 RCG.setAction(Action); 5835 RCG(CGF); 5836 5837 CGF.EmitBranch(DefaultBB); 5838 5839 // 7. Build case 2: 5840 // ... 5841 // Atomic(<LHSExprs>[i] = RedOp<i>(*<LHSExprs>[i], *<RHSExprs>[i])); 5842 // ... 5843 // break; 5844 llvm::BasicBlock *Case2BB = CGF.createBasicBlock(".omp.reduction.case2"); 5845 SwInst->addCase(CGF.Builder.getInt32(2), Case2BB); 5846 CGF.EmitBlock(Case2BB); 5847 5848 auto &&AtomicCodeGen = [Loc, Privates, LHSExprs, RHSExprs, ReductionOps]( 5849 CodeGenFunction &CGF, PrePostActionTy &Action) { 5850 auto ILHS = LHSExprs.begin(); 5851 auto IRHS = RHSExprs.begin(); 5852 auto IPriv = Privates.begin(); 5853 for (const Expr *E : ReductionOps) { 5854 const Expr *XExpr = nullptr; 5855 const Expr *EExpr = nullptr; 5856 const Expr *UpExpr = nullptr; 5857 BinaryOperatorKind BO = BO_Comma; 5858 if (const auto *BO = dyn_cast<BinaryOperator>(E)) { 5859 if (BO->getOpcode() == BO_Assign) { 5860 XExpr = BO->getLHS(); 5861 UpExpr = BO->getRHS(); 5862 } 5863 } 5864 // Try to emit update expression as a simple atomic. 5865 const Expr *RHSExpr = UpExpr; 5866 if (RHSExpr) { 5867 // Analyze RHS part of the whole expression. 5868 if (const auto *ACO = dyn_cast<AbstractConditionalOperator>( 5869 RHSExpr->IgnoreParenImpCasts())) { 5870 // If this is a conditional operator, analyze its condition for 5871 // min/max reduction operator. 5872 RHSExpr = ACO->getCond(); 5873 } 5874 if (const auto *BORHS = 5875 dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { 5876 EExpr = BORHS->getRHS(); 5877 BO = BORHS->getOpcode(); 5878 } 5879 } 5880 if (XExpr) { 5881 const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5882 auto &&AtomicRedGen = [BO, VD, 5883 Loc](CodeGenFunction &CGF, const Expr *XExpr, 5884 const Expr *EExpr, const Expr *UpExpr) { 5885 LValue X = CGF.EmitLValue(XExpr); 5886 RValue E; 5887 if (EExpr) 5888 E = CGF.EmitAnyExpr(EExpr); 5889 CGF.EmitOMPAtomicSimpleUpdateExpr( 5890 X, E, BO, /*IsXLHSInRHSPart=*/true, 5891 llvm::AtomicOrdering::Monotonic, Loc, 5892 [&CGF, UpExpr, VD, Loc](RValue XRValue) { 5893 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 5894 PrivateScope.addPrivate( 5895 VD, [&CGF, VD, XRValue, Loc]() { 5896 Address LHSTemp = CGF.CreateMemTemp(VD->getType()); 5897 CGF.emitOMPSimpleStore( 5898 CGF.MakeAddrLValue(LHSTemp, VD->getType()), XRValue, 5899 VD->getType().getNonReferenceType(), Loc); 5900 return LHSTemp; 5901 }); 5902 (void)PrivateScope.Privatize(); 5903 return CGF.EmitAnyExpr(UpExpr); 5904 }); 5905 }; 5906 if ((*IPriv)->getType()->isArrayType()) { 5907 // Emit atomic reduction for array section. 5908 const auto *RHSVar = 5909 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5910 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), VD, RHSVar, 5911 AtomicRedGen, XExpr, EExpr, UpExpr); 5912 } else { 5913 // Emit atomic reduction for array subscript or single variable. 5914 AtomicRedGen(CGF, XExpr, EExpr, UpExpr); 5915 } 5916 } else { 5917 // Emit as a critical region. 5918 auto &&CritRedGen = [E, Loc](CodeGenFunction &CGF, const Expr *, 5919 const Expr *, const Expr *) { 5920 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 5921 std::string Name = RT.getName({"atomic_reduction"}); 5922 RT.emitCriticalRegion( 5923 CGF, Name, 5924 [=](CodeGenFunction &CGF, PrePostActionTy &Action) { 5925 Action.Enter(CGF); 5926 emitReductionCombiner(CGF, E); 5927 }, 5928 Loc); 5929 }; 5930 if ((*IPriv)->getType()->isArrayType()) { 5931 const auto *LHSVar = 5932 cast<VarDecl>(cast<DeclRefExpr>(*ILHS)->getDecl()); 5933 const auto *RHSVar = 5934 cast<VarDecl>(cast<DeclRefExpr>(*IRHS)->getDecl()); 5935 EmitOMPAggregateReduction(CGF, (*IPriv)->getType(), LHSVar, RHSVar, 5936 CritRedGen); 5937 } else { 5938 CritRedGen(CGF, nullptr, nullptr, nullptr); 5939 } 5940 } 5941 ++ILHS; 5942 ++IRHS; 5943 ++IPriv; 5944 } 5945 }; 5946 RegionCodeGenTy AtomicRCG(AtomicCodeGen); 5947 if (!WithNowait) { 5948 // Add emission of __kmpc_end_reduce(<loc>, <gtid>, &<lock>); 5949 llvm::Value *EndArgs[] = { 5950 IdentTLoc, // ident_t *<loc> 5951 ThreadId, // i32 <gtid> 5952 Lock // kmp_critical_name *&<lock> 5953 }; 5954 CommonActionTy Action(nullptr, llvm::None, 5955 createRuntimeFunction(OMPRTL__kmpc_end_reduce), 5956 EndArgs); 5957 AtomicRCG.setAction(Action); 5958 AtomicRCG(CGF); 5959 } else { 5960 AtomicRCG(CGF); 5961 } 5962 5963 CGF.EmitBranch(DefaultBB); 5964 CGF.EmitBlock(DefaultBB, /*IsFinished=*/true); 5965 } 5966 5967 /// Generates unique name for artificial threadprivate variables. 5968 /// Format is: <Prefix> "." <Decl_mangled_name> "_" "<Decl_start_loc_raw_enc>" 5969 static std::string generateUniqueName(CodeGenModule &CGM, StringRef Prefix, 5970 const Expr *Ref) { 5971 SmallString<256> Buffer; 5972 llvm::raw_svector_ostream Out(Buffer); 5973 const clang::DeclRefExpr *DE; 5974 const VarDecl *D = ::getBaseDecl(Ref, DE); 5975 if (!D) 5976 D = cast<VarDecl>(cast<DeclRefExpr>(Ref)->getDecl()); 5977 D = D->getCanonicalDecl(); 5978 std::string Name = CGM.getOpenMPRuntime().getName( 5979 {D->isLocalVarDeclOrParm() ? D->getName() : CGM.getMangledName(D)}); 5980 Out << Prefix << Name << "_" 5981 << D->getCanonicalDecl()->getBeginLoc().getRawEncoding(); 5982 return Out.str(); 5983 } 5984 5985 /// Emits reduction initializer function: 5986 /// \code 5987 /// void @.red_init(void* %arg) { 5988 /// %0 = bitcast void* %arg to <type>* 5989 /// store <type> <init>, <type>* %0 5990 /// ret void 5991 /// } 5992 /// \endcode 5993 static llvm::Value *emitReduceInitFunction(CodeGenModule &CGM, 5994 SourceLocation Loc, 5995 ReductionCodeGen &RCG, unsigned N) { 5996 ASTContext &C = CGM.getContext(); 5997 FunctionArgList Args; 5998 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 5999 ImplicitParamDecl::Other); 6000 Args.emplace_back(&Param); 6001 const auto &FnInfo = 6002 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6003 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6004 std::string Name = CGM.getOpenMPRuntime().getName({"red_init", ""}); 6005 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6006 Name, &CGM.getModule()); 6007 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6008 Fn->setDoesNotRecurse(); 6009 CodeGenFunction CGF(CGM); 6010 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6011 Address PrivateAddr = CGF.EmitLoadOfPointer( 6012 CGF.GetAddrOfLocalVar(&Param), 6013 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6014 llvm::Value *Size = nullptr; 6015 // If the size of the reduction item is non-constant, load it from global 6016 // threadprivate variable. 6017 if (RCG.getSizes(N).second) { 6018 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6019 CGF, CGM.getContext().getSizeType(), 6020 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6021 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6022 CGM.getContext().getSizeType(), Loc); 6023 } 6024 RCG.emitAggregateType(CGF, N, Size); 6025 LValue SharedLVal; 6026 // If initializer uses initializer from declare reduction construct, emit a 6027 // pointer to the address of the original reduction item (reuired by reduction 6028 // initializer) 6029 if (RCG.usesReductionInitializer(N)) { 6030 Address SharedAddr = 6031 CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6032 CGF, CGM.getContext().VoidPtrTy, 6033 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6034 SharedAddr = CGF.EmitLoadOfPointer( 6035 SharedAddr, 6036 CGM.getContext().VoidPtrTy.castAs<PointerType>()->getTypePtr()); 6037 SharedLVal = CGF.MakeAddrLValue(SharedAddr, CGM.getContext().VoidPtrTy); 6038 } else { 6039 SharedLVal = CGF.MakeNaturalAlignAddrLValue( 6040 llvm::ConstantPointerNull::get(CGM.VoidPtrTy), 6041 CGM.getContext().VoidPtrTy); 6042 } 6043 // Emit the initializer: 6044 // %0 = bitcast void* %arg to <type>* 6045 // store <type> <init>, <type>* %0 6046 RCG.emitInitialization(CGF, N, PrivateAddr, SharedLVal, 6047 [](CodeGenFunction &) { return false; }); 6048 CGF.FinishFunction(); 6049 return Fn; 6050 } 6051 6052 /// Emits reduction combiner function: 6053 /// \code 6054 /// void @.red_comb(void* %arg0, void* %arg1) { 6055 /// %lhs = bitcast void* %arg0 to <type>* 6056 /// %rhs = bitcast void* %arg1 to <type>* 6057 /// %2 = <ReductionOp>(<type>* %lhs, <type>* %rhs) 6058 /// store <type> %2, <type>* %lhs 6059 /// ret void 6060 /// } 6061 /// \endcode 6062 static llvm::Value *emitReduceCombFunction(CodeGenModule &CGM, 6063 SourceLocation Loc, 6064 ReductionCodeGen &RCG, unsigned N, 6065 const Expr *ReductionOp, 6066 const Expr *LHS, const Expr *RHS, 6067 const Expr *PrivateRef) { 6068 ASTContext &C = CGM.getContext(); 6069 const auto *LHSVD = cast<VarDecl>(cast<DeclRefExpr>(LHS)->getDecl()); 6070 const auto *RHSVD = cast<VarDecl>(cast<DeclRefExpr>(RHS)->getDecl()); 6071 FunctionArgList Args; 6072 ImplicitParamDecl ParamInOut(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 6073 C.VoidPtrTy, ImplicitParamDecl::Other); 6074 ImplicitParamDecl ParamIn(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6075 ImplicitParamDecl::Other); 6076 Args.emplace_back(&ParamInOut); 6077 Args.emplace_back(&ParamIn); 6078 const auto &FnInfo = 6079 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6080 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6081 std::string Name = CGM.getOpenMPRuntime().getName({"red_comb", ""}); 6082 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6083 Name, &CGM.getModule()); 6084 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6085 Fn->setDoesNotRecurse(); 6086 CodeGenFunction CGF(CGM); 6087 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6088 llvm::Value *Size = nullptr; 6089 // If the size of the reduction item is non-constant, load it from global 6090 // threadprivate variable. 6091 if (RCG.getSizes(N).second) { 6092 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6093 CGF, CGM.getContext().getSizeType(), 6094 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6095 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6096 CGM.getContext().getSizeType(), Loc); 6097 } 6098 RCG.emitAggregateType(CGF, N, Size); 6099 // Remap lhs and rhs variables to the addresses of the function arguments. 6100 // %lhs = bitcast void* %arg0 to <type>* 6101 // %rhs = bitcast void* %arg1 to <type>* 6102 CodeGenFunction::OMPPrivateScope PrivateScope(CGF); 6103 PrivateScope.addPrivate(LHSVD, [&C, &CGF, &ParamInOut, LHSVD]() { 6104 // Pull out the pointer to the variable. 6105 Address PtrAddr = CGF.EmitLoadOfPointer( 6106 CGF.GetAddrOfLocalVar(&ParamInOut), 6107 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6108 return CGF.Builder.CreateElementBitCast( 6109 PtrAddr, CGF.ConvertTypeForMem(LHSVD->getType())); 6110 }); 6111 PrivateScope.addPrivate(RHSVD, [&C, &CGF, &ParamIn, RHSVD]() { 6112 // Pull out the pointer to the variable. 6113 Address PtrAddr = CGF.EmitLoadOfPointer( 6114 CGF.GetAddrOfLocalVar(&ParamIn), 6115 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6116 return CGF.Builder.CreateElementBitCast( 6117 PtrAddr, CGF.ConvertTypeForMem(RHSVD->getType())); 6118 }); 6119 PrivateScope.Privatize(); 6120 // Emit the combiner body: 6121 // %2 = <ReductionOp>(<type> *%lhs, <type> *%rhs) 6122 // store <type> %2, <type>* %lhs 6123 CGM.getOpenMPRuntime().emitSingleReductionCombiner( 6124 CGF, ReductionOp, PrivateRef, cast<DeclRefExpr>(LHS), 6125 cast<DeclRefExpr>(RHS)); 6126 CGF.FinishFunction(); 6127 return Fn; 6128 } 6129 6130 /// Emits reduction finalizer function: 6131 /// \code 6132 /// void @.red_fini(void* %arg) { 6133 /// %0 = bitcast void* %arg to <type>* 6134 /// <destroy>(<type>* %0) 6135 /// ret void 6136 /// } 6137 /// \endcode 6138 static llvm::Value *emitReduceFiniFunction(CodeGenModule &CGM, 6139 SourceLocation Loc, 6140 ReductionCodeGen &RCG, unsigned N) { 6141 if (!RCG.needCleanups(N)) 6142 return nullptr; 6143 ASTContext &C = CGM.getContext(); 6144 FunctionArgList Args; 6145 ImplicitParamDecl Param(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 6146 ImplicitParamDecl::Other); 6147 Args.emplace_back(&Param); 6148 const auto &FnInfo = 6149 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 6150 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 6151 std::string Name = CGM.getOpenMPRuntime().getName({"red_fini", ""}); 6152 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 6153 Name, &CGM.getModule()); 6154 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 6155 Fn->setDoesNotRecurse(); 6156 CodeGenFunction CGF(CGM); 6157 CGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 6158 Address PrivateAddr = CGF.EmitLoadOfPointer( 6159 CGF.GetAddrOfLocalVar(&Param), 6160 C.getPointerType(C.VoidPtrTy).castAs<PointerType>()); 6161 llvm::Value *Size = nullptr; 6162 // If the size of the reduction item is non-constant, load it from global 6163 // threadprivate variable. 6164 if (RCG.getSizes(N).second) { 6165 Address SizeAddr = CGM.getOpenMPRuntime().getAddrOfArtificialThreadPrivate( 6166 CGF, CGM.getContext().getSizeType(), 6167 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6168 Size = CGF.EmitLoadOfScalar(SizeAddr, /*Volatile=*/false, 6169 CGM.getContext().getSizeType(), Loc); 6170 } 6171 RCG.emitAggregateType(CGF, N, Size); 6172 // Emit the finalizer body: 6173 // <destroy>(<type>* %0) 6174 RCG.emitCleanups(CGF, N, PrivateAddr); 6175 CGF.FinishFunction(); 6176 return Fn; 6177 } 6178 6179 llvm::Value *CGOpenMPRuntime::emitTaskReductionInit( 6180 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 6181 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 6182 if (!CGF.HaveInsertPoint() || Data.ReductionVars.empty()) 6183 return nullptr; 6184 6185 // Build typedef struct: 6186 // kmp_task_red_input { 6187 // void *reduce_shar; // shared reduction item 6188 // size_t reduce_size; // size of data item 6189 // void *reduce_init; // data initialization routine 6190 // void *reduce_fini; // data finalization routine 6191 // void *reduce_comb; // data combiner routine 6192 // kmp_task_red_flags_t flags; // flags for additional info from compiler 6193 // } kmp_task_red_input_t; 6194 ASTContext &C = CGM.getContext(); 6195 RecordDecl *RD = C.buildImplicitRecord("kmp_task_red_input_t"); 6196 RD->startDefinition(); 6197 const FieldDecl *SharedFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6198 const FieldDecl *SizeFD = addFieldToRecordDecl(C, RD, C.getSizeType()); 6199 const FieldDecl *InitFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6200 const FieldDecl *FiniFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6201 const FieldDecl *CombFD = addFieldToRecordDecl(C, RD, C.VoidPtrTy); 6202 const FieldDecl *FlagsFD = addFieldToRecordDecl( 6203 C, RD, C.getIntTypeForBitwidth(/*DestWidth=*/32, /*Signed=*/false)); 6204 RD->completeDefinition(); 6205 QualType RDType = C.getRecordType(RD); 6206 unsigned Size = Data.ReductionVars.size(); 6207 llvm::APInt ArraySize(/*numBits=*/64, Size); 6208 QualType ArrayRDType = C.getConstantArrayType( 6209 RDType, ArraySize, nullptr, ArrayType::Normal, /*IndexTypeQuals=*/0); 6210 // kmp_task_red_input_t .rd_input.[Size]; 6211 Address TaskRedInput = CGF.CreateMemTemp(ArrayRDType, ".rd_input."); 6212 ReductionCodeGen RCG(Data.ReductionVars, Data.ReductionCopies, 6213 Data.ReductionOps); 6214 for (unsigned Cnt = 0; Cnt < Size; ++Cnt) { 6215 // kmp_task_red_input_t &ElemLVal = .rd_input.[Cnt]; 6216 llvm::Value *Idxs[] = {llvm::ConstantInt::get(CGM.SizeTy, /*V=*/0), 6217 llvm::ConstantInt::get(CGM.SizeTy, Cnt)}; 6218 llvm::Value *GEP = CGF.EmitCheckedInBoundsGEP( 6219 TaskRedInput.getPointer(), Idxs, 6220 /*SignedIndices=*/false, /*IsSubtraction=*/false, Loc, 6221 ".rd_input.gep."); 6222 LValue ElemLVal = CGF.MakeNaturalAlignAddrLValue(GEP, RDType); 6223 // ElemLVal.reduce_shar = &Shareds[Cnt]; 6224 LValue SharedLVal = CGF.EmitLValueForField(ElemLVal, SharedFD); 6225 RCG.emitSharedLValue(CGF, Cnt); 6226 llvm::Value *CastedShared = 6227 CGF.EmitCastToVoidPtr(RCG.getSharedLValue(Cnt).getPointer()); 6228 CGF.EmitStoreOfScalar(CastedShared, SharedLVal); 6229 RCG.emitAggregateType(CGF, Cnt); 6230 llvm::Value *SizeValInChars; 6231 llvm::Value *SizeVal; 6232 std::tie(SizeValInChars, SizeVal) = RCG.getSizes(Cnt); 6233 // We use delayed creation/initialization for VLAs, array sections and 6234 // custom reduction initializations. It is required because runtime does not 6235 // provide the way to pass the sizes of VLAs/array sections to 6236 // initializer/combiner/finalizer functions and does not pass the pointer to 6237 // original reduction item to the initializer. Instead threadprivate global 6238 // variables are used to store these values and use them in the functions. 6239 bool DelayedCreation = !!SizeVal; 6240 SizeValInChars = CGF.Builder.CreateIntCast(SizeValInChars, CGM.SizeTy, 6241 /*isSigned=*/false); 6242 LValue SizeLVal = CGF.EmitLValueForField(ElemLVal, SizeFD); 6243 CGF.EmitStoreOfScalar(SizeValInChars, SizeLVal); 6244 // ElemLVal.reduce_init = init; 6245 LValue InitLVal = CGF.EmitLValueForField(ElemLVal, InitFD); 6246 llvm::Value *InitAddr = 6247 CGF.EmitCastToVoidPtr(emitReduceInitFunction(CGM, Loc, RCG, Cnt)); 6248 CGF.EmitStoreOfScalar(InitAddr, InitLVal); 6249 DelayedCreation = DelayedCreation || RCG.usesReductionInitializer(Cnt); 6250 // ElemLVal.reduce_fini = fini; 6251 LValue FiniLVal = CGF.EmitLValueForField(ElemLVal, FiniFD); 6252 llvm::Value *Fini = emitReduceFiniFunction(CGM, Loc, RCG, Cnt); 6253 llvm::Value *FiniAddr = Fini 6254 ? CGF.EmitCastToVoidPtr(Fini) 6255 : llvm::ConstantPointerNull::get(CGM.VoidPtrTy); 6256 CGF.EmitStoreOfScalar(FiniAddr, FiniLVal); 6257 // ElemLVal.reduce_comb = comb; 6258 LValue CombLVal = CGF.EmitLValueForField(ElemLVal, CombFD); 6259 llvm::Value *CombAddr = CGF.EmitCastToVoidPtr(emitReduceCombFunction( 6260 CGM, Loc, RCG, Cnt, Data.ReductionOps[Cnt], LHSExprs[Cnt], 6261 RHSExprs[Cnt], Data.ReductionCopies[Cnt])); 6262 CGF.EmitStoreOfScalar(CombAddr, CombLVal); 6263 // ElemLVal.flags = 0; 6264 LValue FlagsLVal = CGF.EmitLValueForField(ElemLVal, FlagsFD); 6265 if (DelayedCreation) { 6266 CGF.EmitStoreOfScalar( 6267 llvm::ConstantInt::get(CGM.Int32Ty, /*V=*/1, /*isSigned=*/true), 6268 FlagsLVal); 6269 } else 6270 CGF.EmitNullInitialization(FlagsLVal.getAddress(), FlagsLVal.getType()); 6271 } 6272 // Build call void *__kmpc_task_reduction_init(int gtid, int num_data, void 6273 // *data); 6274 llvm::Value *Args[] = { 6275 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6276 /*isSigned=*/true), 6277 llvm::ConstantInt::get(CGM.IntTy, Size, /*isSigned=*/true), 6278 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(TaskRedInput.getPointer(), 6279 CGM.VoidPtrTy)}; 6280 return CGF.EmitRuntimeCall( 6281 createRuntimeFunction(OMPRTL__kmpc_task_reduction_init), Args); 6282 } 6283 6284 void CGOpenMPRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 6285 SourceLocation Loc, 6286 ReductionCodeGen &RCG, 6287 unsigned N) { 6288 auto Sizes = RCG.getSizes(N); 6289 // Emit threadprivate global variable if the type is non-constant 6290 // (Sizes.second = nullptr). 6291 if (Sizes.second) { 6292 llvm::Value *SizeVal = CGF.Builder.CreateIntCast(Sizes.second, CGM.SizeTy, 6293 /*isSigned=*/false); 6294 Address SizeAddr = getAddrOfArtificialThreadPrivate( 6295 CGF, CGM.getContext().getSizeType(), 6296 generateUniqueName(CGM, "reduction_size", RCG.getRefExpr(N))); 6297 CGF.Builder.CreateStore(SizeVal, SizeAddr, /*IsVolatile=*/false); 6298 } 6299 // Store address of the original reduction item if custom initializer is used. 6300 if (RCG.usesReductionInitializer(N)) { 6301 Address SharedAddr = getAddrOfArtificialThreadPrivate( 6302 CGF, CGM.getContext().VoidPtrTy, 6303 generateUniqueName(CGM, "reduction", RCG.getRefExpr(N))); 6304 CGF.Builder.CreateStore( 6305 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 6306 RCG.getSharedLValue(N).getPointer(), CGM.VoidPtrTy), 6307 SharedAddr, /*IsVolatile=*/false); 6308 } 6309 } 6310 6311 Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF, 6312 SourceLocation Loc, 6313 llvm::Value *ReductionsPtr, 6314 LValue SharedLVal) { 6315 // Build call void *__kmpc_task_reduction_get_th_data(int gtid, void *tg, void 6316 // *d); 6317 llvm::Value *Args[] = { 6318 CGF.Builder.CreateIntCast(getThreadID(CGF, Loc), CGM.IntTy, 6319 /*isSigned=*/true), 6320 ReductionsPtr, 6321 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(SharedLVal.getPointer(), 6322 CGM.VoidPtrTy)}; 6323 return Address( 6324 CGF.EmitRuntimeCall( 6325 createRuntimeFunction(OMPRTL__kmpc_task_reduction_get_th_data), Args), 6326 SharedLVal.getAlignment()); 6327 } 6328 6329 void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 6330 SourceLocation Loc) { 6331 if (!CGF.HaveInsertPoint()) 6332 return; 6333 // Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32 6334 // global_tid); 6335 llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)}; 6336 // Ignore return result until untied tasks are supported. 6337 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_omp_taskwait), Args); 6338 if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) 6339 Region->emitUntiedSwitch(CGF); 6340 } 6341 6342 void CGOpenMPRuntime::emitInlinedDirective(CodeGenFunction &CGF, 6343 OpenMPDirectiveKind InnerKind, 6344 const RegionCodeGenTy &CodeGen, 6345 bool HasCancel) { 6346 if (!CGF.HaveInsertPoint()) 6347 return; 6348 InlinedOpenMPRegionRAII Region(CGF, CodeGen, InnerKind, HasCancel); 6349 CGF.CapturedStmtInfo->EmitBody(CGF, /*S=*/nullptr); 6350 } 6351 6352 namespace { 6353 enum RTCancelKind { 6354 CancelNoreq = 0, 6355 CancelParallel = 1, 6356 CancelLoop = 2, 6357 CancelSections = 3, 6358 CancelTaskgroup = 4 6359 }; 6360 } // anonymous namespace 6361 6362 static RTCancelKind getCancellationKind(OpenMPDirectiveKind CancelRegion) { 6363 RTCancelKind CancelKind = CancelNoreq; 6364 if (CancelRegion == OMPD_parallel) 6365 CancelKind = CancelParallel; 6366 else if (CancelRegion == OMPD_for) 6367 CancelKind = CancelLoop; 6368 else if (CancelRegion == OMPD_sections) 6369 CancelKind = CancelSections; 6370 else { 6371 assert(CancelRegion == OMPD_taskgroup); 6372 CancelKind = CancelTaskgroup; 6373 } 6374 return CancelKind; 6375 } 6376 6377 void CGOpenMPRuntime::emitCancellationPointCall( 6378 CodeGenFunction &CGF, SourceLocation Loc, 6379 OpenMPDirectiveKind CancelRegion) { 6380 if (!CGF.HaveInsertPoint()) 6381 return; 6382 // Build call kmp_int32 __kmpc_cancellationpoint(ident_t *loc, kmp_int32 6383 // global_tid, kmp_int32 cncl_kind); 6384 if (auto *OMPRegionInfo = 6385 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6386 // For 'cancellation point taskgroup', the task region info may not have a 6387 // cancel. This may instead happen in another adjacent task. 6388 if (CancelRegion == OMPD_taskgroup || OMPRegionInfo->hasCancel()) { 6389 llvm::Value *Args[] = { 6390 emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc), 6391 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6392 // Ignore return result until untied tasks are supported. 6393 llvm::Value *Result = CGF.EmitRuntimeCall( 6394 createRuntimeFunction(OMPRTL__kmpc_cancellationpoint), Args); 6395 // if (__kmpc_cancellationpoint()) { 6396 // exit from construct; 6397 // } 6398 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6399 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6400 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6401 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6402 CGF.EmitBlock(ExitBB); 6403 // exit from construct; 6404 CodeGenFunction::JumpDest CancelDest = 6405 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6406 CGF.EmitBranchThroughCleanup(CancelDest); 6407 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6408 } 6409 } 6410 } 6411 6412 void CGOpenMPRuntime::emitCancelCall(CodeGenFunction &CGF, SourceLocation Loc, 6413 const Expr *IfCond, 6414 OpenMPDirectiveKind CancelRegion) { 6415 if (!CGF.HaveInsertPoint()) 6416 return; 6417 // Build call kmp_int32 __kmpc_cancel(ident_t *loc, kmp_int32 global_tid, 6418 // kmp_int32 cncl_kind); 6419 if (auto *OMPRegionInfo = 6420 dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo)) { 6421 auto &&ThenGen = [Loc, CancelRegion, OMPRegionInfo](CodeGenFunction &CGF, 6422 PrePostActionTy &) { 6423 CGOpenMPRuntime &RT = CGF.CGM.getOpenMPRuntime(); 6424 llvm::Value *Args[] = { 6425 RT.emitUpdateLocation(CGF, Loc), RT.getThreadID(CGF, Loc), 6426 CGF.Builder.getInt32(getCancellationKind(CancelRegion))}; 6427 // Ignore return result until untied tasks are supported. 6428 llvm::Value *Result = CGF.EmitRuntimeCall( 6429 RT.createRuntimeFunction(OMPRTL__kmpc_cancel), Args); 6430 // if (__kmpc_cancel()) { 6431 // exit from construct; 6432 // } 6433 llvm::BasicBlock *ExitBB = CGF.createBasicBlock(".cancel.exit"); 6434 llvm::BasicBlock *ContBB = CGF.createBasicBlock(".cancel.continue"); 6435 llvm::Value *Cmp = CGF.Builder.CreateIsNotNull(Result); 6436 CGF.Builder.CreateCondBr(Cmp, ExitBB, ContBB); 6437 CGF.EmitBlock(ExitBB); 6438 // exit from construct; 6439 CodeGenFunction::JumpDest CancelDest = 6440 CGF.getOMPCancelDestination(OMPRegionInfo->getDirectiveKind()); 6441 CGF.EmitBranchThroughCleanup(CancelDest); 6442 CGF.EmitBlock(ContBB, /*IsFinished=*/true); 6443 }; 6444 if (IfCond) { 6445 emitOMPIfClause(CGF, IfCond, ThenGen, 6446 [](CodeGenFunction &, PrePostActionTy &) {}); 6447 } else { 6448 RegionCodeGenTy ThenRCG(ThenGen); 6449 ThenRCG(CGF); 6450 } 6451 } 6452 } 6453 6454 void CGOpenMPRuntime::emitTargetOutlinedFunction( 6455 const OMPExecutableDirective &D, StringRef ParentName, 6456 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6457 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6458 assert(!ParentName.empty() && "Invalid target region parent name!"); 6459 HasEmittedTargetRegion = true; 6460 emitTargetOutlinedFunctionHelper(D, ParentName, OutlinedFn, OutlinedFnID, 6461 IsOffloadEntry, CodeGen); 6462 } 6463 6464 void CGOpenMPRuntime::emitTargetOutlinedFunctionHelper( 6465 const OMPExecutableDirective &D, StringRef ParentName, 6466 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 6467 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 6468 // Create a unique name for the entry function using the source location 6469 // information of the current target region. The name will be something like: 6470 // 6471 // __omp_offloading_DD_FFFF_PP_lBB 6472 // 6473 // where DD_FFFF is an ID unique to the file (device and file IDs), PP is the 6474 // mangled name of the function that encloses the target region and BB is the 6475 // line number of the target region. 6476 6477 unsigned DeviceID; 6478 unsigned FileID; 6479 unsigned Line; 6480 getTargetEntryUniqueInfo(CGM.getContext(), D.getBeginLoc(), DeviceID, FileID, 6481 Line); 6482 SmallString<64> EntryFnName; 6483 { 6484 llvm::raw_svector_ostream OS(EntryFnName); 6485 OS << "__omp_offloading" << llvm::format("_%x", DeviceID) 6486 << llvm::format("_%x_", FileID) << ParentName << "_l" << Line; 6487 } 6488 6489 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 6490 6491 CodeGenFunction CGF(CGM, true); 6492 CGOpenMPTargetRegionInfo CGInfo(CS, CodeGen, EntryFnName); 6493 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6494 6495 OutlinedFn = CGF.GenerateOpenMPCapturedStmtFunction(CS); 6496 6497 // If this target outline function is not an offload entry, we don't need to 6498 // register it. 6499 if (!IsOffloadEntry) 6500 return; 6501 6502 // The target region ID is used by the runtime library to identify the current 6503 // target region, so it only has to be unique and not necessarily point to 6504 // anything. It could be the pointer to the outlined function that implements 6505 // the target region, but we aren't using that so that the compiler doesn't 6506 // need to keep that, and could therefore inline the host function if proven 6507 // worthwhile during optimization. In the other hand, if emitting code for the 6508 // device, the ID has to be the function address so that it can retrieved from 6509 // the offloading entry and launched by the runtime library. We also mark the 6510 // outlined function to have external linkage in case we are emitting code for 6511 // the device, because these functions will be entry points to the device. 6512 6513 if (CGM.getLangOpts().OpenMPIsDevice) { 6514 OutlinedFnID = llvm::ConstantExpr::getBitCast(OutlinedFn, CGM.Int8PtrTy); 6515 OutlinedFn->setLinkage(llvm::GlobalValue::WeakAnyLinkage); 6516 OutlinedFn->setDSOLocal(false); 6517 } else { 6518 std::string Name = getName({EntryFnName, "region_id"}); 6519 OutlinedFnID = new llvm::GlobalVariable( 6520 CGM.getModule(), CGM.Int8Ty, /*isConstant=*/true, 6521 llvm::GlobalValue::WeakAnyLinkage, 6522 llvm::Constant::getNullValue(CGM.Int8Ty), Name); 6523 } 6524 6525 // Register the information for the entry associated with this target region. 6526 OffloadEntriesInfoManager.registerTargetRegionEntryInfo( 6527 DeviceID, FileID, ParentName, Line, OutlinedFn, OutlinedFnID, 6528 OffloadEntriesInfoManagerTy::OMPTargetRegionEntryTargetRegion); 6529 } 6530 6531 /// Checks if the expression is constant or does not have non-trivial function 6532 /// calls. 6533 static bool isTrivial(ASTContext &Ctx, const Expr * E) { 6534 // We can skip constant expressions. 6535 // We can skip expressions with trivial calls or simple expressions. 6536 return (E->isEvaluatable(Ctx, Expr::SE_AllowUndefinedBehavior) || 6537 !E->hasNonTrivialCall(Ctx)) && 6538 !E->HasSideEffects(Ctx, /*IncludePossibleEffects=*/true); 6539 } 6540 6541 const Stmt *CGOpenMPRuntime::getSingleCompoundChild(ASTContext &Ctx, 6542 const Stmt *Body) { 6543 const Stmt *Child = Body->IgnoreContainers(); 6544 while (const auto *C = dyn_cast_or_null<CompoundStmt>(Child)) { 6545 Child = nullptr; 6546 for (const Stmt *S : C->body()) { 6547 if (const auto *E = dyn_cast<Expr>(S)) { 6548 if (isTrivial(Ctx, E)) 6549 continue; 6550 } 6551 // Some of the statements can be ignored. 6552 if (isa<AsmStmt>(S) || isa<NullStmt>(S) || isa<OMPFlushDirective>(S) || 6553 isa<OMPBarrierDirective>(S) || isa<OMPTaskyieldDirective>(S)) 6554 continue; 6555 // Analyze declarations. 6556 if (const auto *DS = dyn_cast<DeclStmt>(S)) { 6557 if (llvm::all_of(DS->decls(), [&Ctx](const Decl *D) { 6558 if (isa<EmptyDecl>(D) || isa<DeclContext>(D) || 6559 isa<TypeDecl>(D) || isa<PragmaCommentDecl>(D) || 6560 isa<PragmaDetectMismatchDecl>(D) || isa<UsingDecl>(D) || 6561 isa<UsingDirectiveDecl>(D) || 6562 isa<OMPDeclareReductionDecl>(D) || 6563 isa<OMPThreadPrivateDecl>(D) || isa<OMPAllocateDecl>(D)) 6564 return true; 6565 const auto *VD = dyn_cast<VarDecl>(D); 6566 if (!VD) 6567 return false; 6568 return VD->isConstexpr() || 6569 ((VD->getType().isTrivialType(Ctx) || 6570 VD->getType()->isReferenceType()) && 6571 (!VD->hasInit() || isTrivial(Ctx, VD->getInit()))); 6572 })) 6573 continue; 6574 } 6575 // Found multiple children - cannot get the one child only. 6576 if (Child) 6577 return nullptr; 6578 Child = S; 6579 } 6580 if (Child) 6581 Child = Child->IgnoreContainers(); 6582 } 6583 return Child; 6584 } 6585 6586 /// Emit the number of teams for a target directive. Inspect the num_teams 6587 /// clause associated with a teams construct combined or closely nested 6588 /// with the target directive. 6589 /// 6590 /// Emit a team of size one for directives such as 'target parallel' that 6591 /// have no associated teams construct. 6592 /// 6593 /// Otherwise, return nullptr. 6594 static llvm::Value * 6595 emitNumTeamsForTargetDirective(CodeGenFunction &CGF, 6596 const OMPExecutableDirective &D) { 6597 assert(!CGF.getLangOpts().OpenMPIsDevice && 6598 "Clauses associated with the teams directive expected to be emitted " 6599 "only for the host!"); 6600 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6601 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6602 "Expected target-based executable directive."); 6603 CGBuilderTy &Bld = CGF.Builder; 6604 switch (DirectiveKind) { 6605 case OMPD_target: { 6606 const auto *CS = D.getInnermostCapturedStmt(); 6607 const auto *Body = 6608 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 6609 const Stmt *ChildStmt = 6610 CGOpenMPRuntime::getSingleCompoundChild(CGF.getContext(), Body); 6611 if (const auto *NestedDir = 6612 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 6613 if (isOpenMPTeamsDirective(NestedDir->getDirectiveKind())) { 6614 if (NestedDir->hasClausesOfKind<OMPNumTeamsClause>()) { 6615 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6616 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6617 const Expr *NumTeams = 6618 NestedDir->getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6619 llvm::Value *NumTeamsVal = 6620 CGF.EmitScalarExpr(NumTeams, 6621 /*IgnoreResultAssign*/ true); 6622 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6623 /*isSigned=*/true); 6624 } 6625 return Bld.getInt32(0); 6626 } 6627 if (isOpenMPParallelDirective(NestedDir->getDirectiveKind()) || 6628 isOpenMPSimdDirective(NestedDir->getDirectiveKind())) 6629 return Bld.getInt32(1); 6630 return Bld.getInt32(0); 6631 } 6632 return nullptr; 6633 } 6634 case OMPD_target_teams: 6635 case OMPD_target_teams_distribute: 6636 case OMPD_target_teams_distribute_simd: 6637 case OMPD_target_teams_distribute_parallel_for: 6638 case OMPD_target_teams_distribute_parallel_for_simd: { 6639 if (D.hasClausesOfKind<OMPNumTeamsClause>()) { 6640 CodeGenFunction::RunCleanupsScope NumTeamsScope(CGF); 6641 const Expr *NumTeams = 6642 D.getSingleClause<OMPNumTeamsClause>()->getNumTeams(); 6643 llvm::Value *NumTeamsVal = 6644 CGF.EmitScalarExpr(NumTeams, 6645 /*IgnoreResultAssign*/ true); 6646 return Bld.CreateIntCast(NumTeamsVal, CGF.Int32Ty, 6647 /*isSigned=*/true); 6648 } 6649 return Bld.getInt32(0); 6650 } 6651 case OMPD_target_parallel: 6652 case OMPD_target_parallel_for: 6653 case OMPD_target_parallel_for_simd: 6654 case OMPD_target_simd: 6655 return Bld.getInt32(1); 6656 case OMPD_parallel: 6657 case OMPD_for: 6658 case OMPD_parallel_for: 6659 case OMPD_parallel_sections: 6660 case OMPD_for_simd: 6661 case OMPD_parallel_for_simd: 6662 case OMPD_cancel: 6663 case OMPD_cancellation_point: 6664 case OMPD_ordered: 6665 case OMPD_threadprivate: 6666 case OMPD_allocate: 6667 case OMPD_task: 6668 case OMPD_simd: 6669 case OMPD_sections: 6670 case OMPD_section: 6671 case OMPD_single: 6672 case OMPD_master: 6673 case OMPD_critical: 6674 case OMPD_taskyield: 6675 case OMPD_barrier: 6676 case OMPD_taskwait: 6677 case OMPD_taskgroup: 6678 case OMPD_atomic: 6679 case OMPD_flush: 6680 case OMPD_teams: 6681 case OMPD_target_data: 6682 case OMPD_target_exit_data: 6683 case OMPD_target_enter_data: 6684 case OMPD_distribute: 6685 case OMPD_distribute_simd: 6686 case OMPD_distribute_parallel_for: 6687 case OMPD_distribute_parallel_for_simd: 6688 case OMPD_teams_distribute: 6689 case OMPD_teams_distribute_simd: 6690 case OMPD_teams_distribute_parallel_for: 6691 case OMPD_teams_distribute_parallel_for_simd: 6692 case OMPD_target_update: 6693 case OMPD_declare_simd: 6694 case OMPD_declare_variant: 6695 case OMPD_declare_target: 6696 case OMPD_end_declare_target: 6697 case OMPD_declare_reduction: 6698 case OMPD_declare_mapper: 6699 case OMPD_taskloop: 6700 case OMPD_taskloop_simd: 6701 case OMPD_master_taskloop: 6702 case OMPD_parallel_master_taskloop: 6703 case OMPD_requires: 6704 case OMPD_unknown: 6705 break; 6706 } 6707 llvm_unreachable("Unexpected directive kind."); 6708 } 6709 6710 static llvm::Value *getNumThreads(CodeGenFunction &CGF, const CapturedStmt *CS, 6711 llvm::Value *DefaultThreadLimitVal) { 6712 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6713 CGF.getContext(), CS->getCapturedStmt()); 6714 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6715 if (isOpenMPParallelDirective(Dir->getDirectiveKind())) { 6716 llvm::Value *NumThreads = nullptr; 6717 llvm::Value *CondVal = nullptr; 6718 // Handle if clause. If if clause present, the number of threads is 6719 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6720 if (Dir->hasClausesOfKind<OMPIfClause>()) { 6721 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6722 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6723 const OMPIfClause *IfClause = nullptr; 6724 for (const auto *C : Dir->getClausesOfKind<OMPIfClause>()) { 6725 if (C->getNameModifier() == OMPD_unknown || 6726 C->getNameModifier() == OMPD_parallel) { 6727 IfClause = C; 6728 break; 6729 } 6730 } 6731 if (IfClause) { 6732 const Expr *Cond = IfClause->getCondition(); 6733 bool Result; 6734 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6735 if (!Result) 6736 return CGF.Builder.getInt32(1); 6737 } else { 6738 CodeGenFunction::LexicalScope Scope(CGF, Cond->getSourceRange()); 6739 if (const auto *PreInit = 6740 cast_or_null<DeclStmt>(IfClause->getPreInitStmt())) { 6741 for (const auto *I : PreInit->decls()) { 6742 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6743 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6744 } else { 6745 CodeGenFunction::AutoVarEmission Emission = 6746 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6747 CGF.EmitAutoVarCleanups(Emission); 6748 } 6749 } 6750 } 6751 CondVal = CGF.EvaluateExprAsBool(Cond); 6752 } 6753 } 6754 } 6755 // Check the value of num_threads clause iff if clause was not specified 6756 // or is not evaluated to false. 6757 if (Dir->hasClausesOfKind<OMPNumThreadsClause>()) { 6758 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6759 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6760 const auto *NumThreadsClause = 6761 Dir->getSingleClause<OMPNumThreadsClause>(); 6762 CodeGenFunction::LexicalScope Scope( 6763 CGF, NumThreadsClause->getNumThreads()->getSourceRange()); 6764 if (const auto *PreInit = 6765 cast_or_null<DeclStmt>(NumThreadsClause->getPreInitStmt())) { 6766 for (const auto *I : PreInit->decls()) { 6767 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6768 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6769 } else { 6770 CodeGenFunction::AutoVarEmission Emission = 6771 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6772 CGF.EmitAutoVarCleanups(Emission); 6773 } 6774 } 6775 } 6776 NumThreads = CGF.EmitScalarExpr(NumThreadsClause->getNumThreads()); 6777 NumThreads = CGF.Builder.CreateIntCast(NumThreads, CGF.Int32Ty, 6778 /*isSigned=*/false); 6779 if (DefaultThreadLimitVal) 6780 NumThreads = CGF.Builder.CreateSelect( 6781 CGF.Builder.CreateICmpULT(DefaultThreadLimitVal, NumThreads), 6782 DefaultThreadLimitVal, NumThreads); 6783 } else { 6784 NumThreads = DefaultThreadLimitVal ? DefaultThreadLimitVal 6785 : CGF.Builder.getInt32(0); 6786 } 6787 // Process condition of the if clause. 6788 if (CondVal) { 6789 NumThreads = CGF.Builder.CreateSelect(CondVal, NumThreads, 6790 CGF.Builder.getInt32(1)); 6791 } 6792 return NumThreads; 6793 } 6794 if (isOpenMPSimdDirective(Dir->getDirectiveKind())) 6795 return CGF.Builder.getInt32(1); 6796 return DefaultThreadLimitVal; 6797 } 6798 return DefaultThreadLimitVal ? DefaultThreadLimitVal 6799 : CGF.Builder.getInt32(0); 6800 } 6801 6802 /// Emit the number of threads for a target directive. Inspect the 6803 /// thread_limit clause associated with a teams construct combined or closely 6804 /// nested with the target directive. 6805 /// 6806 /// Emit the num_threads clause for directives such as 'target parallel' that 6807 /// have no associated teams construct. 6808 /// 6809 /// Otherwise, return nullptr. 6810 static llvm::Value * 6811 emitNumThreadsForTargetDirective(CodeGenFunction &CGF, 6812 const OMPExecutableDirective &D) { 6813 assert(!CGF.getLangOpts().OpenMPIsDevice && 6814 "Clauses associated with the teams directive expected to be emitted " 6815 "only for the host!"); 6816 OpenMPDirectiveKind DirectiveKind = D.getDirectiveKind(); 6817 assert(isOpenMPTargetExecutionDirective(DirectiveKind) && 6818 "Expected target-based executable directive."); 6819 CGBuilderTy &Bld = CGF.Builder; 6820 llvm::Value *ThreadLimitVal = nullptr; 6821 llvm::Value *NumThreadsVal = nullptr; 6822 switch (DirectiveKind) { 6823 case OMPD_target: { 6824 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6825 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6826 return NumThreads; 6827 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6828 CGF.getContext(), CS->getCapturedStmt()); 6829 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6830 if (Dir->hasClausesOfKind<OMPThreadLimitClause>()) { 6831 CGOpenMPInnerExprInfo CGInfo(CGF, *CS); 6832 CodeGenFunction::CGCapturedStmtRAII CapInfoRAII(CGF, &CGInfo); 6833 const auto *ThreadLimitClause = 6834 Dir->getSingleClause<OMPThreadLimitClause>(); 6835 CodeGenFunction::LexicalScope Scope( 6836 CGF, ThreadLimitClause->getThreadLimit()->getSourceRange()); 6837 if (const auto *PreInit = 6838 cast_or_null<DeclStmt>(ThreadLimitClause->getPreInitStmt())) { 6839 for (const auto *I : PreInit->decls()) { 6840 if (!I->hasAttr<OMPCaptureNoInitAttr>()) { 6841 CGF.EmitVarDecl(cast<VarDecl>(*I)); 6842 } else { 6843 CodeGenFunction::AutoVarEmission Emission = 6844 CGF.EmitAutoVarAlloca(cast<VarDecl>(*I)); 6845 CGF.EmitAutoVarCleanups(Emission); 6846 } 6847 } 6848 } 6849 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6850 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6851 ThreadLimitVal = 6852 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6853 } 6854 if (isOpenMPTeamsDirective(Dir->getDirectiveKind()) && 6855 !isOpenMPDistributeDirective(Dir->getDirectiveKind())) { 6856 CS = Dir->getInnermostCapturedStmt(); 6857 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6858 CGF.getContext(), CS->getCapturedStmt()); 6859 Dir = dyn_cast_or_null<OMPExecutableDirective>(Child); 6860 } 6861 if (Dir && isOpenMPDistributeDirective(Dir->getDirectiveKind()) && 6862 !isOpenMPSimdDirective(Dir->getDirectiveKind())) { 6863 CS = Dir->getInnermostCapturedStmt(); 6864 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6865 return NumThreads; 6866 } 6867 if (Dir && isOpenMPSimdDirective(Dir->getDirectiveKind())) 6868 return Bld.getInt32(1); 6869 } 6870 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6871 } 6872 case OMPD_target_teams: { 6873 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6874 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6875 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6876 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6877 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6878 ThreadLimitVal = 6879 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6880 } 6881 const CapturedStmt *CS = D.getInnermostCapturedStmt(); 6882 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6883 return NumThreads; 6884 const Stmt *Child = CGOpenMPRuntime::getSingleCompoundChild( 6885 CGF.getContext(), CS->getCapturedStmt()); 6886 if (const auto *Dir = dyn_cast_or_null<OMPExecutableDirective>(Child)) { 6887 if (Dir->getDirectiveKind() == OMPD_distribute) { 6888 CS = Dir->getInnermostCapturedStmt(); 6889 if (llvm::Value *NumThreads = getNumThreads(CGF, CS, ThreadLimitVal)) 6890 return NumThreads; 6891 } 6892 } 6893 return ThreadLimitVal ? ThreadLimitVal : Bld.getInt32(0); 6894 } 6895 case OMPD_target_teams_distribute: 6896 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6897 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6898 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6899 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6900 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6901 ThreadLimitVal = 6902 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6903 } 6904 return getNumThreads(CGF, D.getInnermostCapturedStmt(), ThreadLimitVal); 6905 case OMPD_target_parallel: 6906 case OMPD_target_parallel_for: 6907 case OMPD_target_parallel_for_simd: 6908 case OMPD_target_teams_distribute_parallel_for: 6909 case OMPD_target_teams_distribute_parallel_for_simd: { 6910 llvm::Value *CondVal = nullptr; 6911 // Handle if clause. If if clause present, the number of threads is 6912 // calculated as <cond> ? (<numthreads> ? <numthreads> : 0 ) : 1. 6913 if (D.hasClausesOfKind<OMPIfClause>()) { 6914 const OMPIfClause *IfClause = nullptr; 6915 for (const auto *C : D.getClausesOfKind<OMPIfClause>()) { 6916 if (C->getNameModifier() == OMPD_unknown || 6917 C->getNameModifier() == OMPD_parallel) { 6918 IfClause = C; 6919 break; 6920 } 6921 } 6922 if (IfClause) { 6923 const Expr *Cond = IfClause->getCondition(); 6924 bool Result; 6925 if (Cond->EvaluateAsBooleanCondition(Result, CGF.getContext())) { 6926 if (!Result) 6927 return Bld.getInt32(1); 6928 } else { 6929 CodeGenFunction::RunCleanupsScope Scope(CGF); 6930 CondVal = CGF.EvaluateExprAsBool(Cond); 6931 } 6932 } 6933 } 6934 if (D.hasClausesOfKind<OMPThreadLimitClause>()) { 6935 CodeGenFunction::RunCleanupsScope ThreadLimitScope(CGF); 6936 const auto *ThreadLimitClause = D.getSingleClause<OMPThreadLimitClause>(); 6937 llvm::Value *ThreadLimit = CGF.EmitScalarExpr( 6938 ThreadLimitClause->getThreadLimit(), /*IgnoreResultAssign=*/true); 6939 ThreadLimitVal = 6940 Bld.CreateIntCast(ThreadLimit, CGF.Int32Ty, /*isSigned=*/false); 6941 } 6942 if (D.hasClausesOfKind<OMPNumThreadsClause>()) { 6943 CodeGenFunction::RunCleanupsScope NumThreadsScope(CGF); 6944 const auto *NumThreadsClause = D.getSingleClause<OMPNumThreadsClause>(); 6945 llvm::Value *NumThreads = CGF.EmitScalarExpr( 6946 NumThreadsClause->getNumThreads(), /*IgnoreResultAssign=*/true); 6947 NumThreadsVal = 6948 Bld.CreateIntCast(NumThreads, CGF.Int32Ty, /*isSigned=*/false); 6949 ThreadLimitVal = ThreadLimitVal 6950 ? Bld.CreateSelect(Bld.CreateICmpULT(NumThreadsVal, 6951 ThreadLimitVal), 6952 NumThreadsVal, ThreadLimitVal) 6953 : NumThreadsVal; 6954 } 6955 if (!ThreadLimitVal) 6956 ThreadLimitVal = Bld.getInt32(0); 6957 if (CondVal) 6958 return Bld.CreateSelect(CondVal, ThreadLimitVal, Bld.getInt32(1)); 6959 return ThreadLimitVal; 6960 } 6961 case OMPD_target_teams_distribute_simd: 6962 case OMPD_target_simd: 6963 return Bld.getInt32(1); 6964 case OMPD_parallel: 6965 case OMPD_for: 6966 case OMPD_parallel_for: 6967 case OMPD_parallel_sections: 6968 case OMPD_for_simd: 6969 case OMPD_parallel_for_simd: 6970 case OMPD_cancel: 6971 case OMPD_cancellation_point: 6972 case OMPD_ordered: 6973 case OMPD_threadprivate: 6974 case OMPD_allocate: 6975 case OMPD_task: 6976 case OMPD_simd: 6977 case OMPD_sections: 6978 case OMPD_section: 6979 case OMPD_single: 6980 case OMPD_master: 6981 case OMPD_critical: 6982 case OMPD_taskyield: 6983 case OMPD_barrier: 6984 case OMPD_taskwait: 6985 case OMPD_taskgroup: 6986 case OMPD_atomic: 6987 case OMPD_flush: 6988 case OMPD_teams: 6989 case OMPD_target_data: 6990 case OMPD_target_exit_data: 6991 case OMPD_target_enter_data: 6992 case OMPD_distribute: 6993 case OMPD_distribute_simd: 6994 case OMPD_distribute_parallel_for: 6995 case OMPD_distribute_parallel_for_simd: 6996 case OMPD_teams_distribute: 6997 case OMPD_teams_distribute_simd: 6998 case OMPD_teams_distribute_parallel_for: 6999 case OMPD_teams_distribute_parallel_for_simd: 7000 case OMPD_target_update: 7001 case OMPD_declare_simd: 7002 case OMPD_declare_variant: 7003 case OMPD_declare_target: 7004 case OMPD_end_declare_target: 7005 case OMPD_declare_reduction: 7006 case OMPD_declare_mapper: 7007 case OMPD_taskloop: 7008 case OMPD_taskloop_simd: 7009 case OMPD_master_taskloop: 7010 case OMPD_parallel_master_taskloop: 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(); 7504 } else { 7505 // The base is the reference to the variable. 7506 // BP = &Var. 7507 BP = CGF.EmitOMPSharedLValue(AssocExpr).getAddress(); 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 = 7602 CGF.EmitOMPSharedLValue(I->getAssociatedExpression()).getAddress(); 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(); 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(); 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(), VDLVal.getPointer()); 8176 BasePointers.push_back(ThisLVal.getPointer()); 8177 Pointers.push_back(ThisLValVal.getPointer()); 8178 Sizes.push_back( 8179 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8180 CGF.Int64Ty, /*isSigned=*/true)); 8181 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8182 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8183 } 8184 for (const LambdaCapture &LC : RD->captures()) { 8185 if (!LC.capturesVariable()) 8186 continue; 8187 const VarDecl *VD = LC.getCapturedVar(); 8188 if (LC.getCaptureKind() != LCK_ByRef && !VD->getType()->isPointerType()) 8189 continue; 8190 auto It = Captures.find(VD); 8191 assert(It != Captures.end() && "Found lambda capture without field."); 8192 LValue VarLVal = CGF.EmitLValueForFieldInitialization(VDLVal, It->second); 8193 if (LC.getCaptureKind() == LCK_ByRef) { 8194 LValue VarLValVal = CGF.EmitLValueForField(VDLVal, It->second); 8195 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer()); 8196 BasePointers.push_back(VarLVal.getPointer()); 8197 Pointers.push_back(VarLValVal.getPointer()); 8198 Sizes.push_back(CGF.Builder.CreateIntCast( 8199 CGF.getTypeSize( 8200 VD->getType().getCanonicalType().getNonReferenceType()), 8201 CGF.Int64Ty, /*isSigned=*/true)); 8202 } else { 8203 RValue VarRVal = CGF.EmitLoadOfLValue(VarLVal, RD->getLocation()); 8204 LambdaPointers.try_emplace(VarLVal.getPointer(), VDLVal.getPointer()); 8205 BasePointers.push_back(VarLVal.getPointer()); 8206 Pointers.push_back(VarRVal.getScalarVal()); 8207 Sizes.push_back(llvm::ConstantInt::get(CGF.Int64Ty, 0)); 8208 } 8209 Types.push_back(OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8210 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT); 8211 } 8212 } 8213 8214 /// Set correct indices for lambdas captures. 8215 void adjustMemberOfForLambdaCaptures( 8216 const llvm::DenseMap<llvm::Value *, llvm::Value *> &LambdaPointers, 8217 MapBaseValuesArrayTy &BasePointers, MapValuesArrayTy &Pointers, 8218 MapFlagsArrayTy &Types) const { 8219 for (unsigned I = 0, E = Types.size(); I < E; ++I) { 8220 // Set correct member_of idx for all implicit lambda captures. 8221 if (Types[I] != (OMP_MAP_PTR_AND_OBJ | OMP_MAP_LITERAL | 8222 OMP_MAP_MEMBER_OF | OMP_MAP_IMPLICIT)) 8223 continue; 8224 llvm::Value *BasePtr = LambdaPointers.lookup(*BasePointers[I]); 8225 assert(BasePtr && "Unable to find base lambda address."); 8226 int TgtIdx = -1; 8227 for (unsigned J = I; J > 0; --J) { 8228 unsigned Idx = J - 1; 8229 if (Pointers[Idx] != BasePtr) 8230 continue; 8231 TgtIdx = Idx; 8232 break; 8233 } 8234 assert(TgtIdx != -1 && "Unable to find parent lambda."); 8235 // All other current entries will be MEMBER_OF the combined entry 8236 // (except for PTR_AND_OBJ entries which do not have a placeholder value 8237 // 0xFFFF in the MEMBER_OF field). 8238 OpenMPOffloadMappingFlags MemberOfFlag = getMemberOfFlag(TgtIdx); 8239 setCorrectMemberOfFlag(Types[I], MemberOfFlag); 8240 } 8241 } 8242 8243 /// Generate the base pointers, section pointers, sizes and map types 8244 /// associated to a given capture. 8245 void generateInfoForCapture(const CapturedStmt::Capture *Cap, 8246 llvm::Value *Arg, 8247 MapBaseValuesArrayTy &BasePointers, 8248 MapValuesArrayTy &Pointers, 8249 MapValuesArrayTy &Sizes, MapFlagsArrayTy &Types, 8250 StructRangeInfoTy &PartialStruct) const { 8251 assert(!Cap->capturesVariableArrayType() && 8252 "Not expecting to generate map info for a variable array type!"); 8253 8254 // We need to know when we generating information for the first component 8255 const ValueDecl *VD = Cap->capturesThis() 8256 ? nullptr 8257 : Cap->getCapturedVar()->getCanonicalDecl(); 8258 8259 // If this declaration appears in a is_device_ptr clause we just have to 8260 // pass the pointer by value. If it is a reference to a declaration, we just 8261 // pass its value. 8262 if (DevPointersMap.count(VD)) { 8263 BasePointers.emplace_back(Arg, VD); 8264 Pointers.push_back(Arg); 8265 Sizes.push_back( 8266 CGF.Builder.CreateIntCast(CGF.getTypeSize(CGF.getContext().VoidPtrTy), 8267 CGF.Int64Ty, /*isSigned=*/true)); 8268 Types.push_back(OMP_MAP_LITERAL | OMP_MAP_TARGET_PARAM); 8269 return; 8270 } 8271 8272 using MapData = 8273 std::tuple<OMPClauseMappableExprCommon::MappableExprComponentListRef, 8274 OpenMPMapClauseKind, ArrayRef<OpenMPMapModifierKind>, bool>; 8275 SmallVector<MapData, 4> DeclComponentLists; 8276 assert(CurDir.is<const OMPExecutableDirective *>() && 8277 "Expect a executable directive"); 8278 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8279 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8280 for (const auto &L : C->decl_component_lists(VD)) { 8281 assert(L.first == VD && 8282 "We got information for the wrong declaration??"); 8283 assert(!L.second.empty() && 8284 "Not expecting declaration with no component lists."); 8285 DeclComponentLists.emplace_back(L.second, C->getMapType(), 8286 C->getMapTypeModifiers(), 8287 C->isImplicit()); 8288 } 8289 } 8290 8291 // Find overlapping elements (including the offset from the base element). 8292 llvm::SmallDenseMap< 8293 const MapData *, 8294 llvm::SmallVector< 8295 OMPClauseMappableExprCommon::MappableExprComponentListRef, 4>, 8296 4> 8297 OverlappedData; 8298 size_t Count = 0; 8299 for (const MapData &L : DeclComponentLists) { 8300 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8301 OpenMPMapClauseKind MapType; 8302 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8303 bool IsImplicit; 8304 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8305 ++Count; 8306 for (const MapData &L1 : makeArrayRef(DeclComponentLists).slice(Count)) { 8307 OMPClauseMappableExprCommon::MappableExprComponentListRef Components1; 8308 std::tie(Components1, MapType, MapModifiers, IsImplicit) = L1; 8309 auto CI = Components.rbegin(); 8310 auto CE = Components.rend(); 8311 auto SI = Components1.rbegin(); 8312 auto SE = Components1.rend(); 8313 for (; CI != CE && SI != SE; ++CI, ++SI) { 8314 if (CI->getAssociatedExpression()->getStmtClass() != 8315 SI->getAssociatedExpression()->getStmtClass()) 8316 break; 8317 // Are we dealing with different variables/fields? 8318 if (CI->getAssociatedDeclaration() != SI->getAssociatedDeclaration()) 8319 break; 8320 } 8321 // Found overlapping if, at least for one component, reached the head of 8322 // the components list. 8323 if (CI == CE || SI == SE) { 8324 assert((CI != CE || SI != SE) && 8325 "Unexpected full match of the mapping components."); 8326 const MapData &BaseData = CI == CE ? L : L1; 8327 OMPClauseMappableExprCommon::MappableExprComponentListRef SubData = 8328 SI == SE ? Components : Components1; 8329 auto &OverlappedElements = OverlappedData.FindAndConstruct(&BaseData); 8330 OverlappedElements.getSecond().push_back(SubData); 8331 } 8332 } 8333 } 8334 // Sort the overlapped elements for each item. 8335 llvm::SmallVector<const FieldDecl *, 4> Layout; 8336 if (!OverlappedData.empty()) { 8337 if (const auto *CRD = 8338 VD->getType().getCanonicalType()->getAsCXXRecordDecl()) 8339 getPlainLayout(CRD, Layout, /*AsBase=*/false); 8340 else { 8341 const auto *RD = VD->getType().getCanonicalType()->getAsRecordDecl(); 8342 Layout.append(RD->field_begin(), RD->field_end()); 8343 } 8344 } 8345 for (auto &Pair : OverlappedData) { 8346 llvm::sort( 8347 Pair.getSecond(), 8348 [&Layout]( 8349 OMPClauseMappableExprCommon::MappableExprComponentListRef First, 8350 OMPClauseMappableExprCommon::MappableExprComponentListRef 8351 Second) { 8352 auto CI = First.rbegin(); 8353 auto CE = First.rend(); 8354 auto SI = Second.rbegin(); 8355 auto SE = Second.rend(); 8356 for (; CI != CE && SI != SE; ++CI, ++SI) { 8357 if (CI->getAssociatedExpression()->getStmtClass() != 8358 SI->getAssociatedExpression()->getStmtClass()) 8359 break; 8360 // Are we dealing with different variables/fields? 8361 if (CI->getAssociatedDeclaration() != 8362 SI->getAssociatedDeclaration()) 8363 break; 8364 } 8365 8366 // Lists contain the same elements. 8367 if (CI == CE && SI == SE) 8368 return false; 8369 8370 // List with less elements is less than list with more elements. 8371 if (CI == CE || SI == SE) 8372 return CI == CE; 8373 8374 const auto *FD1 = cast<FieldDecl>(CI->getAssociatedDeclaration()); 8375 const auto *FD2 = cast<FieldDecl>(SI->getAssociatedDeclaration()); 8376 if (FD1->getParent() == FD2->getParent()) 8377 return FD1->getFieldIndex() < FD2->getFieldIndex(); 8378 const auto It = 8379 llvm::find_if(Layout, [FD1, FD2](const FieldDecl *FD) { 8380 return FD == FD1 || FD == FD2; 8381 }); 8382 return *It == FD1; 8383 }); 8384 } 8385 8386 // Associated with a capture, because the mapping flags depend on it. 8387 // Go through all of the elements with the overlapped elements. 8388 for (const auto &Pair : OverlappedData) { 8389 const MapData &L = *Pair.getFirst(); 8390 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8391 OpenMPMapClauseKind MapType; 8392 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8393 bool IsImplicit; 8394 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8395 ArrayRef<OMPClauseMappableExprCommon::MappableExprComponentListRef> 8396 OverlappedComponents = Pair.getSecond(); 8397 bool IsFirstComponentList = true; 8398 generateInfoForComponentList(MapType, MapModifiers, Components, 8399 BasePointers, Pointers, Sizes, Types, 8400 PartialStruct, IsFirstComponentList, 8401 IsImplicit, OverlappedComponents); 8402 } 8403 // Go through other elements without overlapped elements. 8404 bool IsFirstComponentList = OverlappedData.empty(); 8405 for (const MapData &L : DeclComponentLists) { 8406 OMPClauseMappableExprCommon::MappableExprComponentListRef Components; 8407 OpenMPMapClauseKind MapType; 8408 ArrayRef<OpenMPMapModifierKind> MapModifiers; 8409 bool IsImplicit; 8410 std::tie(Components, MapType, MapModifiers, IsImplicit) = L; 8411 auto It = OverlappedData.find(&L); 8412 if (It == OverlappedData.end()) 8413 generateInfoForComponentList(MapType, MapModifiers, Components, 8414 BasePointers, Pointers, Sizes, Types, 8415 PartialStruct, IsFirstComponentList, 8416 IsImplicit); 8417 IsFirstComponentList = false; 8418 } 8419 } 8420 8421 /// Generate the base pointers, section pointers, sizes and map types 8422 /// associated with the declare target link variables. 8423 void generateInfoForDeclareTargetLink(MapBaseValuesArrayTy &BasePointers, 8424 MapValuesArrayTy &Pointers, 8425 MapValuesArrayTy &Sizes, 8426 MapFlagsArrayTy &Types) const { 8427 assert(CurDir.is<const OMPExecutableDirective *>() && 8428 "Expect a executable directive"); 8429 const auto *CurExecDir = CurDir.get<const OMPExecutableDirective *>(); 8430 // Map other list items in the map clause which are not captured variables 8431 // but "declare target link" global variables. 8432 for (const auto *C : CurExecDir->getClausesOfKind<OMPMapClause>()) { 8433 for (const auto &L : C->component_lists()) { 8434 if (!L.first) 8435 continue; 8436 const auto *VD = dyn_cast<VarDecl>(L.first); 8437 if (!VD) 8438 continue; 8439 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 8440 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 8441 if (CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory() || 8442 !Res || *Res != OMPDeclareTargetDeclAttr::MT_Link) 8443 continue; 8444 StructRangeInfoTy PartialStruct; 8445 generateInfoForComponentList( 8446 C->getMapType(), C->getMapTypeModifiers(), L.second, BasePointers, 8447 Pointers, Sizes, Types, PartialStruct, 8448 /*IsFirstComponentList=*/true, C->isImplicit()); 8449 assert(!PartialStruct.Base.isValid() && 8450 "No partial structs for declare target link expected."); 8451 } 8452 } 8453 } 8454 8455 /// Generate the default map information for a given capture \a CI, 8456 /// record field declaration \a RI and captured value \a CV. 8457 void generateDefaultMapInfo(const CapturedStmt::Capture &CI, 8458 const FieldDecl &RI, llvm::Value *CV, 8459 MapBaseValuesArrayTy &CurBasePointers, 8460 MapValuesArrayTy &CurPointers, 8461 MapValuesArrayTy &CurSizes, 8462 MapFlagsArrayTy &CurMapTypes) const { 8463 bool IsImplicit = true; 8464 // Do the default mapping. 8465 if (CI.capturesThis()) { 8466 CurBasePointers.push_back(CV); 8467 CurPointers.push_back(CV); 8468 const auto *PtrTy = cast<PointerType>(RI.getType().getTypePtr()); 8469 CurSizes.push_back( 8470 CGF.Builder.CreateIntCast(CGF.getTypeSize(PtrTy->getPointeeType()), 8471 CGF.Int64Ty, /*isSigned=*/true)); 8472 // Default map type. 8473 CurMapTypes.push_back(OMP_MAP_TO | OMP_MAP_FROM); 8474 } else if (CI.capturesVariableByCopy()) { 8475 CurBasePointers.push_back(CV); 8476 CurPointers.push_back(CV); 8477 if (!RI.getType()->isAnyPointerType()) { 8478 // We have to signal to the runtime captures passed by value that are 8479 // not pointers. 8480 CurMapTypes.push_back(OMP_MAP_LITERAL); 8481 CurSizes.push_back(CGF.Builder.CreateIntCast( 8482 CGF.getTypeSize(RI.getType()), CGF.Int64Ty, /*isSigned=*/true)); 8483 } else { 8484 // Pointers are implicitly mapped with a zero size and no flags 8485 // (other than first map that is added for all implicit maps). 8486 CurMapTypes.push_back(OMP_MAP_NONE); 8487 CurSizes.push_back(llvm::Constant::getNullValue(CGF.Int64Ty)); 8488 } 8489 const VarDecl *VD = CI.getCapturedVar(); 8490 auto I = FirstPrivateDecls.find(VD); 8491 if (I != FirstPrivateDecls.end()) 8492 IsImplicit = I->getSecond(); 8493 } else { 8494 assert(CI.capturesVariable() && "Expected captured reference."); 8495 const auto *PtrTy = cast<ReferenceType>(RI.getType().getTypePtr()); 8496 QualType ElementType = PtrTy->getPointeeType(); 8497 CurSizes.push_back(CGF.Builder.CreateIntCast( 8498 CGF.getTypeSize(ElementType), CGF.Int64Ty, /*isSigned=*/true)); 8499 // The default map type for a scalar/complex type is 'to' because by 8500 // default the value doesn't have to be retrieved. For an aggregate 8501 // type, the default is 'tofrom'. 8502 CurMapTypes.push_back(getMapModifiersForPrivateClauses(CI)); 8503 const VarDecl *VD = CI.getCapturedVar(); 8504 auto I = FirstPrivateDecls.find(VD); 8505 if (I != FirstPrivateDecls.end() && 8506 VD->getType().isConstant(CGF.getContext())) { 8507 llvm::Constant *Addr = 8508 CGF.CGM.getOpenMPRuntime().registerTargetFirstprivateCopy(CGF, VD); 8509 // Copy the value of the original variable to the new global copy. 8510 CGF.Builder.CreateMemCpy( 8511 CGF.MakeNaturalAlignAddrLValue(Addr, ElementType).getAddress(), 8512 Address(CV, CGF.getContext().getTypeAlignInChars(ElementType)), 8513 CurSizes.back(), /*IsVolatile=*/false); 8514 // Use new global variable as the base pointers. 8515 CurBasePointers.push_back(Addr); 8516 CurPointers.push_back(Addr); 8517 } else { 8518 CurBasePointers.push_back(CV); 8519 if (I != FirstPrivateDecls.end() && ElementType->isAnyPointerType()) { 8520 Address PtrAddr = CGF.EmitLoadOfReference(CGF.MakeAddrLValue( 8521 CV, ElementType, CGF.getContext().getDeclAlign(VD), 8522 AlignmentSource::Decl)); 8523 CurPointers.push_back(PtrAddr.getPointer()); 8524 } else { 8525 CurPointers.push_back(CV); 8526 } 8527 } 8528 if (I != FirstPrivateDecls.end()) 8529 IsImplicit = I->getSecond(); 8530 } 8531 // Every default map produces a single argument which is a target parameter. 8532 CurMapTypes.back() |= OMP_MAP_TARGET_PARAM; 8533 8534 // Add flag stating this is an implicit map. 8535 if (IsImplicit) 8536 CurMapTypes.back() |= OMP_MAP_IMPLICIT; 8537 } 8538 }; 8539 } // anonymous namespace 8540 8541 /// Emit the arrays used to pass the captures and map information to the 8542 /// offloading runtime library. If there is no map or capture information, 8543 /// return nullptr by reference. 8544 static void 8545 emitOffloadingArrays(CodeGenFunction &CGF, 8546 MappableExprsHandler::MapBaseValuesArrayTy &BasePointers, 8547 MappableExprsHandler::MapValuesArrayTy &Pointers, 8548 MappableExprsHandler::MapValuesArrayTy &Sizes, 8549 MappableExprsHandler::MapFlagsArrayTy &MapTypes, 8550 CGOpenMPRuntime::TargetDataInfo &Info) { 8551 CodeGenModule &CGM = CGF.CGM; 8552 ASTContext &Ctx = CGF.getContext(); 8553 8554 // Reset the array information. 8555 Info.clearArrayInfo(); 8556 Info.NumberOfPtrs = BasePointers.size(); 8557 8558 if (Info.NumberOfPtrs) { 8559 // Detect if we have any capture size requiring runtime evaluation of the 8560 // size so that a constant array could be eventually used. 8561 bool hasRuntimeEvaluationCaptureSize = false; 8562 for (llvm::Value *S : Sizes) 8563 if (!isa<llvm::Constant>(S)) { 8564 hasRuntimeEvaluationCaptureSize = true; 8565 break; 8566 } 8567 8568 llvm::APInt PointerNumAP(32, Info.NumberOfPtrs, /*isSigned=*/true); 8569 QualType PointerArrayType = Ctx.getConstantArrayType( 8570 Ctx.VoidPtrTy, PointerNumAP, nullptr, ArrayType::Normal, 8571 /*IndexTypeQuals=*/0); 8572 8573 Info.BasePointersArray = 8574 CGF.CreateMemTemp(PointerArrayType, ".offload_baseptrs").getPointer(); 8575 Info.PointersArray = 8576 CGF.CreateMemTemp(PointerArrayType, ".offload_ptrs").getPointer(); 8577 8578 // If we don't have any VLA types or other types that require runtime 8579 // evaluation, we can use a constant array for the map sizes, otherwise we 8580 // need to fill up the arrays as we do for the pointers. 8581 QualType Int64Ty = 8582 Ctx.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 8583 if (hasRuntimeEvaluationCaptureSize) { 8584 QualType SizeArrayType = Ctx.getConstantArrayType( 8585 Int64Ty, PointerNumAP, nullptr, ArrayType::Normal, 8586 /*IndexTypeQuals=*/0); 8587 Info.SizesArray = 8588 CGF.CreateMemTemp(SizeArrayType, ".offload_sizes").getPointer(); 8589 } else { 8590 // We expect all the sizes to be constant, so we collect them to create 8591 // a constant array. 8592 SmallVector<llvm::Constant *, 16> ConstSizes; 8593 for (llvm::Value *S : Sizes) 8594 ConstSizes.push_back(cast<llvm::Constant>(S)); 8595 8596 auto *SizesArrayInit = llvm::ConstantArray::get( 8597 llvm::ArrayType::get(CGM.Int64Ty, ConstSizes.size()), ConstSizes); 8598 std::string Name = CGM.getOpenMPRuntime().getName({"offload_sizes"}); 8599 auto *SizesArrayGbl = new llvm::GlobalVariable( 8600 CGM.getModule(), SizesArrayInit->getType(), 8601 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8602 SizesArrayInit, Name); 8603 SizesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8604 Info.SizesArray = SizesArrayGbl; 8605 } 8606 8607 // The map types are always constant so we don't need to generate code to 8608 // fill arrays. Instead, we create an array constant. 8609 SmallVector<uint64_t, 4> Mapping(MapTypes.size(), 0); 8610 llvm::copy(MapTypes, Mapping.begin()); 8611 llvm::Constant *MapTypesArrayInit = 8612 llvm::ConstantDataArray::get(CGF.Builder.getContext(), Mapping); 8613 std::string MaptypesName = 8614 CGM.getOpenMPRuntime().getName({"offload_maptypes"}); 8615 auto *MapTypesArrayGbl = new llvm::GlobalVariable( 8616 CGM.getModule(), MapTypesArrayInit->getType(), 8617 /*isConstant=*/true, llvm::GlobalValue::PrivateLinkage, 8618 MapTypesArrayInit, MaptypesName); 8619 MapTypesArrayGbl->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global); 8620 Info.MapTypesArray = MapTypesArrayGbl; 8621 8622 for (unsigned I = 0; I < Info.NumberOfPtrs; ++I) { 8623 llvm::Value *BPVal = *BasePointers[I]; 8624 llvm::Value *BP = CGF.Builder.CreateConstInBoundsGEP2_32( 8625 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8626 Info.BasePointersArray, 0, I); 8627 BP = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8628 BP, BPVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8629 Address BPAddr(BP, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8630 CGF.Builder.CreateStore(BPVal, BPAddr); 8631 8632 if (Info.requiresDevicePointerInfo()) 8633 if (const ValueDecl *DevVD = BasePointers[I].getDevicePtrDecl()) 8634 Info.CaptureDeviceAddrMap.try_emplace(DevVD, BPAddr); 8635 8636 llvm::Value *PVal = Pointers[I]; 8637 llvm::Value *P = CGF.Builder.CreateConstInBoundsGEP2_32( 8638 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8639 Info.PointersArray, 0, I); 8640 P = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 8641 P, PVal->getType()->getPointerTo(/*AddrSpace=*/0)); 8642 Address PAddr(P, Ctx.getTypeAlignInChars(Ctx.VoidPtrTy)); 8643 CGF.Builder.CreateStore(PVal, PAddr); 8644 8645 if (hasRuntimeEvaluationCaptureSize) { 8646 llvm::Value *S = CGF.Builder.CreateConstInBoundsGEP2_32( 8647 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8648 Info.SizesArray, 8649 /*Idx0=*/0, 8650 /*Idx1=*/I); 8651 Address SAddr(S, Ctx.getTypeAlignInChars(Int64Ty)); 8652 CGF.Builder.CreateStore( 8653 CGF.Builder.CreateIntCast(Sizes[I], CGM.Int64Ty, /*isSigned=*/true), 8654 SAddr); 8655 } 8656 } 8657 } 8658 } 8659 8660 /// Emit the arguments to be passed to the runtime library based on the 8661 /// arrays of pointers, sizes and map types. 8662 static void emitOffloadingArraysArgument( 8663 CodeGenFunction &CGF, llvm::Value *&BasePointersArrayArg, 8664 llvm::Value *&PointersArrayArg, llvm::Value *&SizesArrayArg, 8665 llvm::Value *&MapTypesArrayArg, CGOpenMPRuntime::TargetDataInfo &Info) { 8666 CodeGenModule &CGM = CGF.CGM; 8667 if (Info.NumberOfPtrs) { 8668 BasePointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8669 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8670 Info.BasePointersArray, 8671 /*Idx0=*/0, /*Idx1=*/0); 8672 PointersArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8673 llvm::ArrayType::get(CGM.VoidPtrTy, Info.NumberOfPtrs), 8674 Info.PointersArray, 8675 /*Idx0=*/0, 8676 /*Idx1=*/0); 8677 SizesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8678 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), Info.SizesArray, 8679 /*Idx0=*/0, /*Idx1=*/0); 8680 MapTypesArrayArg = CGF.Builder.CreateConstInBoundsGEP2_32( 8681 llvm::ArrayType::get(CGM.Int64Ty, Info.NumberOfPtrs), 8682 Info.MapTypesArray, 8683 /*Idx0=*/0, 8684 /*Idx1=*/0); 8685 } else { 8686 BasePointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8687 PointersArrayArg = llvm::ConstantPointerNull::get(CGM.VoidPtrPtrTy); 8688 SizesArrayArg = llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8689 MapTypesArrayArg = 8690 llvm::ConstantPointerNull::get(CGM.Int64Ty->getPointerTo()); 8691 } 8692 } 8693 8694 /// Check for inner distribute directive. 8695 static const OMPExecutableDirective * 8696 getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) { 8697 const auto *CS = D.getInnermostCapturedStmt(); 8698 const auto *Body = 8699 CS->getCapturedStmt()->IgnoreContainers(/*IgnoreCaptured=*/true); 8700 const Stmt *ChildStmt = 8701 CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8702 8703 if (const auto *NestedDir = 8704 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8705 OpenMPDirectiveKind DKind = NestedDir->getDirectiveKind(); 8706 switch (D.getDirectiveKind()) { 8707 case OMPD_target: 8708 if (isOpenMPDistributeDirective(DKind)) 8709 return NestedDir; 8710 if (DKind == OMPD_teams) { 8711 Body = NestedDir->getInnermostCapturedStmt()->IgnoreContainers( 8712 /*IgnoreCaptured=*/true); 8713 if (!Body) 8714 return nullptr; 8715 ChildStmt = CGOpenMPSIMDRuntime::getSingleCompoundChild(Ctx, Body); 8716 if (const auto *NND = 8717 dyn_cast_or_null<OMPExecutableDirective>(ChildStmt)) { 8718 DKind = NND->getDirectiveKind(); 8719 if (isOpenMPDistributeDirective(DKind)) 8720 return NND; 8721 } 8722 } 8723 return nullptr; 8724 case OMPD_target_teams: 8725 if (isOpenMPDistributeDirective(DKind)) 8726 return NestedDir; 8727 return nullptr; 8728 case OMPD_target_parallel: 8729 case OMPD_target_simd: 8730 case OMPD_target_parallel_for: 8731 case OMPD_target_parallel_for_simd: 8732 return nullptr; 8733 case OMPD_target_teams_distribute: 8734 case OMPD_target_teams_distribute_simd: 8735 case OMPD_target_teams_distribute_parallel_for: 8736 case OMPD_target_teams_distribute_parallel_for_simd: 8737 case OMPD_parallel: 8738 case OMPD_for: 8739 case OMPD_parallel_for: 8740 case OMPD_parallel_sections: 8741 case OMPD_for_simd: 8742 case OMPD_parallel_for_simd: 8743 case OMPD_cancel: 8744 case OMPD_cancellation_point: 8745 case OMPD_ordered: 8746 case OMPD_threadprivate: 8747 case OMPD_allocate: 8748 case OMPD_task: 8749 case OMPD_simd: 8750 case OMPD_sections: 8751 case OMPD_section: 8752 case OMPD_single: 8753 case OMPD_master: 8754 case OMPD_critical: 8755 case OMPD_taskyield: 8756 case OMPD_barrier: 8757 case OMPD_taskwait: 8758 case OMPD_taskgroup: 8759 case OMPD_atomic: 8760 case OMPD_flush: 8761 case OMPD_teams: 8762 case OMPD_target_data: 8763 case OMPD_target_exit_data: 8764 case OMPD_target_enter_data: 8765 case OMPD_distribute: 8766 case OMPD_distribute_simd: 8767 case OMPD_distribute_parallel_for: 8768 case OMPD_distribute_parallel_for_simd: 8769 case OMPD_teams_distribute: 8770 case OMPD_teams_distribute_simd: 8771 case OMPD_teams_distribute_parallel_for: 8772 case OMPD_teams_distribute_parallel_for_simd: 8773 case OMPD_target_update: 8774 case OMPD_declare_simd: 8775 case OMPD_declare_variant: 8776 case OMPD_declare_target: 8777 case OMPD_end_declare_target: 8778 case OMPD_declare_reduction: 8779 case OMPD_declare_mapper: 8780 case OMPD_taskloop: 8781 case OMPD_taskloop_simd: 8782 case OMPD_master_taskloop: 8783 case OMPD_parallel_master_taskloop: 8784 case OMPD_requires: 8785 case OMPD_unknown: 8786 llvm_unreachable("Unexpected directive."); 8787 } 8788 } 8789 8790 return nullptr; 8791 } 8792 8793 /// Emit the user-defined mapper function. The code generation follows the 8794 /// pattern in the example below. 8795 /// \code 8796 /// void .omp_mapper.<type_name>.<mapper_id>.(void *rt_mapper_handle, 8797 /// void *base, void *begin, 8798 /// int64_t size, int64_t type) { 8799 /// // Allocate space for an array section first. 8800 /// if (size > 1 && !maptype.IsDelete) 8801 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8802 /// size*sizeof(Ty), clearToFrom(type)); 8803 /// // Map members. 8804 /// for (unsigned i = 0; i < size; i++) { 8805 /// // For each component specified by this mapper: 8806 /// for (auto c : all_components) { 8807 /// if (c.hasMapper()) 8808 /// (*c.Mapper())(rt_mapper_handle, c.arg_base, c.arg_begin, c.arg_size, 8809 /// c.arg_type); 8810 /// else 8811 /// __tgt_push_mapper_component(rt_mapper_handle, c.arg_base, 8812 /// c.arg_begin, c.arg_size, c.arg_type); 8813 /// } 8814 /// } 8815 /// // Delete the array section. 8816 /// if (size > 1 && maptype.IsDelete) 8817 /// __tgt_push_mapper_component(rt_mapper_handle, base, begin, 8818 /// size*sizeof(Ty), clearToFrom(type)); 8819 /// } 8820 /// \endcode 8821 void CGOpenMPRuntime::emitUserDefinedMapper(const OMPDeclareMapperDecl *D, 8822 CodeGenFunction *CGF) { 8823 if (UDMMap.count(D) > 0) 8824 return; 8825 ASTContext &C = CGM.getContext(); 8826 QualType Ty = D->getType(); 8827 QualType PtrTy = C.getPointerType(Ty).withRestrict(); 8828 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 8829 auto *MapperVarDecl = 8830 cast<VarDecl>(cast<DeclRefExpr>(D->getMapperVarRef())->getDecl()); 8831 SourceLocation Loc = D->getLocation(); 8832 CharUnits ElementSize = C.getTypeSizeInChars(Ty); 8833 8834 // Prepare mapper function arguments and attributes. 8835 ImplicitParamDecl HandleArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8836 C.VoidPtrTy, ImplicitParamDecl::Other); 8837 ImplicitParamDecl BaseArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, C.VoidPtrTy, 8838 ImplicitParamDecl::Other); 8839 ImplicitParamDecl BeginArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, 8840 C.VoidPtrTy, ImplicitParamDecl::Other); 8841 ImplicitParamDecl SizeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8842 ImplicitParamDecl::Other); 8843 ImplicitParamDecl TypeArg(C, /*DC=*/nullptr, Loc, /*Id=*/nullptr, Int64Ty, 8844 ImplicitParamDecl::Other); 8845 FunctionArgList Args; 8846 Args.push_back(&HandleArg); 8847 Args.push_back(&BaseArg); 8848 Args.push_back(&BeginArg); 8849 Args.push_back(&SizeArg); 8850 Args.push_back(&TypeArg); 8851 const CGFunctionInfo &FnInfo = 8852 CGM.getTypes().arrangeBuiltinFunctionDeclaration(C.VoidTy, Args); 8853 llvm::FunctionType *FnTy = CGM.getTypes().GetFunctionType(FnInfo); 8854 SmallString<64> TyStr; 8855 llvm::raw_svector_ostream Out(TyStr); 8856 CGM.getCXXABI().getMangleContext().mangleTypeName(Ty, Out); 8857 std::string Name = getName({"omp_mapper", TyStr, D->getName()}); 8858 auto *Fn = llvm::Function::Create(FnTy, llvm::GlobalValue::InternalLinkage, 8859 Name, &CGM.getModule()); 8860 CGM.SetInternalFunctionAttributes(GlobalDecl(), Fn, FnInfo); 8861 Fn->removeFnAttr(llvm::Attribute::OptimizeNone); 8862 // Start the mapper function code generation. 8863 CodeGenFunction MapperCGF(CGM); 8864 MapperCGF.StartFunction(GlobalDecl(), C.VoidTy, Fn, FnInfo, Args, Loc, Loc); 8865 // Compute the starting and end addreses of array elements. 8866 llvm::Value *Size = MapperCGF.EmitLoadOfScalar( 8867 MapperCGF.GetAddrOfLocalVar(&SizeArg), /*Volatile=*/false, 8868 C.getPointerType(Int64Ty), Loc); 8869 llvm::Value *PtrBegin = MapperCGF.Builder.CreateBitCast( 8870 MapperCGF.GetAddrOfLocalVar(&BeginArg).getPointer(), 8871 CGM.getTypes().ConvertTypeForMem(C.getPointerType(PtrTy))); 8872 llvm::Value *PtrEnd = MapperCGF.Builder.CreateGEP(PtrBegin, Size); 8873 llvm::Value *MapType = MapperCGF.EmitLoadOfScalar( 8874 MapperCGF.GetAddrOfLocalVar(&TypeArg), /*Volatile=*/false, 8875 C.getPointerType(Int64Ty), Loc); 8876 // Prepare common arguments for array initiation and deletion. 8877 llvm::Value *Handle = MapperCGF.EmitLoadOfScalar( 8878 MapperCGF.GetAddrOfLocalVar(&HandleArg), 8879 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8880 llvm::Value *BaseIn = MapperCGF.EmitLoadOfScalar( 8881 MapperCGF.GetAddrOfLocalVar(&BaseArg), 8882 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8883 llvm::Value *BeginIn = MapperCGF.EmitLoadOfScalar( 8884 MapperCGF.GetAddrOfLocalVar(&BeginArg), 8885 /*Volatile=*/false, C.getPointerType(C.VoidPtrTy), Loc); 8886 8887 // Emit array initiation if this is an array section and \p MapType indicates 8888 // that memory allocation is required. 8889 llvm::BasicBlock *HeadBB = MapperCGF.createBasicBlock("omp.arraymap.head"); 8890 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 8891 ElementSize, HeadBB, /*IsInit=*/true); 8892 8893 // Emit a for loop to iterate through SizeArg of elements and map all of them. 8894 8895 // Emit the loop header block. 8896 MapperCGF.EmitBlock(HeadBB); 8897 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.arraymap.body"); 8898 llvm::BasicBlock *DoneBB = MapperCGF.createBasicBlock("omp.done"); 8899 // Evaluate whether the initial condition is satisfied. 8900 llvm::Value *IsEmpty = 8901 MapperCGF.Builder.CreateICmpEQ(PtrBegin, PtrEnd, "omp.arraymap.isempty"); 8902 MapperCGF.Builder.CreateCondBr(IsEmpty, DoneBB, BodyBB); 8903 llvm::BasicBlock *EntryBB = MapperCGF.Builder.GetInsertBlock(); 8904 8905 // Emit the loop body block. 8906 MapperCGF.EmitBlock(BodyBB); 8907 llvm::PHINode *PtrPHI = MapperCGF.Builder.CreatePHI( 8908 PtrBegin->getType(), 2, "omp.arraymap.ptrcurrent"); 8909 PtrPHI->addIncoming(PtrBegin, EntryBB); 8910 Address PtrCurrent = 8911 Address(PtrPHI, MapperCGF.GetAddrOfLocalVar(&BeginArg) 8912 .getAlignment() 8913 .alignmentOfArrayElement(ElementSize)); 8914 // Privatize the declared variable of mapper to be the current array element. 8915 CodeGenFunction::OMPPrivateScope Scope(MapperCGF); 8916 Scope.addPrivate(MapperVarDecl, [&MapperCGF, PtrCurrent, PtrTy]() { 8917 return MapperCGF 8918 .EmitLoadOfPointerLValue(PtrCurrent, PtrTy->castAs<PointerType>()) 8919 .getAddress(); 8920 }); 8921 (void)Scope.Privatize(); 8922 8923 // Get map clause information. Fill up the arrays with all mapped variables. 8924 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 8925 MappableExprsHandler::MapValuesArrayTy Pointers; 8926 MappableExprsHandler::MapValuesArrayTy Sizes; 8927 MappableExprsHandler::MapFlagsArrayTy MapTypes; 8928 MappableExprsHandler MEHandler(*D, MapperCGF); 8929 MEHandler.generateAllInfoForMapper(BasePointers, Pointers, Sizes, MapTypes); 8930 8931 // Call the runtime API __tgt_mapper_num_components to get the number of 8932 // pre-existing components. 8933 llvm::Value *OffloadingArgs[] = {Handle}; 8934 llvm::Value *PreviousSize = MapperCGF.EmitRuntimeCall( 8935 createRuntimeFunction(OMPRTL__tgt_mapper_num_components), OffloadingArgs); 8936 llvm::Value *ShiftedPreviousSize = MapperCGF.Builder.CreateShl( 8937 PreviousSize, 8938 MapperCGF.Builder.getInt64(MappableExprsHandler::getFlagMemberOffset())); 8939 8940 // Fill up the runtime mapper handle for all components. 8941 for (unsigned I = 0; I < BasePointers.size(); ++I) { 8942 llvm::Value *CurBaseArg = MapperCGF.Builder.CreateBitCast( 8943 *BasePointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8944 llvm::Value *CurBeginArg = MapperCGF.Builder.CreateBitCast( 8945 Pointers[I], CGM.getTypes().ConvertTypeForMem(C.VoidPtrTy)); 8946 llvm::Value *CurSizeArg = Sizes[I]; 8947 8948 // Extract the MEMBER_OF field from the map type. 8949 llvm::BasicBlock *MemberBB = MapperCGF.createBasicBlock("omp.member"); 8950 MapperCGF.EmitBlock(MemberBB); 8951 llvm::Value *OriMapType = MapperCGF.Builder.getInt64(MapTypes[I]); 8952 llvm::Value *Member = MapperCGF.Builder.CreateAnd( 8953 OriMapType, 8954 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_MEMBER_OF)); 8955 llvm::BasicBlock *MemberCombineBB = 8956 MapperCGF.createBasicBlock("omp.member.combine"); 8957 llvm::BasicBlock *TypeBB = MapperCGF.createBasicBlock("omp.type"); 8958 llvm::Value *IsMember = MapperCGF.Builder.CreateIsNull(Member); 8959 MapperCGF.Builder.CreateCondBr(IsMember, TypeBB, MemberCombineBB); 8960 // Add the number of pre-existing components to the MEMBER_OF field if it 8961 // is valid. 8962 MapperCGF.EmitBlock(MemberCombineBB); 8963 llvm::Value *CombinedMember = 8964 MapperCGF.Builder.CreateNUWAdd(OriMapType, ShiftedPreviousSize); 8965 // Do nothing if it is not a member of previous components. 8966 MapperCGF.EmitBlock(TypeBB); 8967 llvm::PHINode *MemberMapType = 8968 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.membermaptype"); 8969 MemberMapType->addIncoming(OriMapType, MemberBB); 8970 MemberMapType->addIncoming(CombinedMember, MemberCombineBB); 8971 8972 // Combine the map type inherited from user-defined mapper with that 8973 // specified in the program. According to the OMP_MAP_TO and OMP_MAP_FROM 8974 // bits of the \a MapType, which is the input argument of the mapper 8975 // function, the following code will set the OMP_MAP_TO and OMP_MAP_FROM 8976 // bits of MemberMapType. 8977 // [OpenMP 5.0], 1.2.6. map-type decay. 8978 // | alloc | to | from | tofrom | release | delete 8979 // ---------------------------------------------------------- 8980 // alloc | alloc | alloc | alloc | alloc | release | delete 8981 // to | alloc | to | alloc | to | release | delete 8982 // from | alloc | alloc | from | from | release | delete 8983 // tofrom | alloc | to | from | tofrom | release | delete 8984 llvm::Value *LeftToFrom = MapperCGF.Builder.CreateAnd( 8985 MapType, 8986 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO | 8987 MappableExprsHandler::OMP_MAP_FROM)); 8988 llvm::BasicBlock *AllocBB = MapperCGF.createBasicBlock("omp.type.alloc"); 8989 llvm::BasicBlock *AllocElseBB = 8990 MapperCGF.createBasicBlock("omp.type.alloc.else"); 8991 llvm::BasicBlock *ToBB = MapperCGF.createBasicBlock("omp.type.to"); 8992 llvm::BasicBlock *ToElseBB = MapperCGF.createBasicBlock("omp.type.to.else"); 8993 llvm::BasicBlock *FromBB = MapperCGF.createBasicBlock("omp.type.from"); 8994 llvm::BasicBlock *EndBB = MapperCGF.createBasicBlock("omp.type.end"); 8995 llvm::Value *IsAlloc = MapperCGF.Builder.CreateIsNull(LeftToFrom); 8996 MapperCGF.Builder.CreateCondBr(IsAlloc, AllocBB, AllocElseBB); 8997 // In case of alloc, clear OMP_MAP_TO and OMP_MAP_FROM. 8998 MapperCGF.EmitBlock(AllocBB); 8999 llvm::Value *AllocMapType = MapperCGF.Builder.CreateAnd( 9000 MemberMapType, 9001 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9002 MappableExprsHandler::OMP_MAP_FROM))); 9003 MapperCGF.Builder.CreateBr(EndBB); 9004 MapperCGF.EmitBlock(AllocElseBB); 9005 llvm::Value *IsTo = MapperCGF.Builder.CreateICmpEQ( 9006 LeftToFrom, 9007 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_TO)); 9008 MapperCGF.Builder.CreateCondBr(IsTo, ToBB, ToElseBB); 9009 // In case of to, clear OMP_MAP_FROM. 9010 MapperCGF.EmitBlock(ToBB); 9011 llvm::Value *ToMapType = MapperCGF.Builder.CreateAnd( 9012 MemberMapType, 9013 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_FROM)); 9014 MapperCGF.Builder.CreateBr(EndBB); 9015 MapperCGF.EmitBlock(ToElseBB); 9016 llvm::Value *IsFrom = MapperCGF.Builder.CreateICmpEQ( 9017 LeftToFrom, 9018 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_FROM)); 9019 MapperCGF.Builder.CreateCondBr(IsFrom, FromBB, EndBB); 9020 // In case of from, clear OMP_MAP_TO. 9021 MapperCGF.EmitBlock(FromBB); 9022 llvm::Value *FromMapType = MapperCGF.Builder.CreateAnd( 9023 MemberMapType, 9024 MapperCGF.Builder.getInt64(~MappableExprsHandler::OMP_MAP_TO)); 9025 // In case of tofrom, do nothing. 9026 MapperCGF.EmitBlock(EndBB); 9027 llvm::PHINode *CurMapType = 9028 MapperCGF.Builder.CreatePHI(CGM.Int64Ty, 4, "omp.maptype"); 9029 CurMapType->addIncoming(AllocMapType, AllocBB); 9030 CurMapType->addIncoming(ToMapType, ToBB); 9031 CurMapType->addIncoming(FromMapType, FromBB); 9032 CurMapType->addIncoming(MemberMapType, ToElseBB); 9033 9034 // TODO: call the corresponding mapper function if a user-defined mapper is 9035 // associated with this map clause. 9036 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9037 // data structure. 9038 llvm::Value *OffloadingArgs[] = {Handle, CurBaseArg, CurBeginArg, 9039 CurSizeArg, CurMapType}; 9040 MapperCGF.EmitRuntimeCall( 9041 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), 9042 OffloadingArgs); 9043 } 9044 9045 // Update the pointer to point to the next element that needs to be mapped, 9046 // and check whether we have mapped all elements. 9047 llvm::Value *PtrNext = MapperCGF.Builder.CreateConstGEP1_32( 9048 PtrPHI, /*Idx0=*/1, "omp.arraymap.next"); 9049 PtrPHI->addIncoming(PtrNext, BodyBB); 9050 llvm::Value *IsDone = 9051 MapperCGF.Builder.CreateICmpEQ(PtrNext, PtrEnd, "omp.arraymap.isdone"); 9052 llvm::BasicBlock *ExitBB = MapperCGF.createBasicBlock("omp.arraymap.exit"); 9053 MapperCGF.Builder.CreateCondBr(IsDone, ExitBB, BodyBB); 9054 9055 MapperCGF.EmitBlock(ExitBB); 9056 // Emit array deletion if this is an array section and \p MapType indicates 9057 // that deletion is required. 9058 emitUDMapperArrayInitOrDel(MapperCGF, Handle, BaseIn, BeginIn, Size, MapType, 9059 ElementSize, DoneBB, /*IsInit=*/false); 9060 9061 // Emit the function exit block. 9062 MapperCGF.EmitBlock(DoneBB, /*IsFinished=*/true); 9063 MapperCGF.FinishFunction(); 9064 UDMMap.try_emplace(D, Fn); 9065 if (CGF) { 9066 auto &Decls = FunctionUDMMap.FindAndConstruct(CGF->CurFn); 9067 Decls.second.push_back(D); 9068 } 9069 } 9070 9071 /// Emit the array initialization or deletion portion for user-defined mapper 9072 /// code generation. First, it evaluates whether an array section is mapped and 9073 /// whether the \a MapType instructs to delete this section. If \a IsInit is 9074 /// true, and \a MapType indicates to not delete this array, array 9075 /// initialization code is generated. If \a IsInit is false, and \a MapType 9076 /// indicates to not this array, array deletion code is generated. 9077 void CGOpenMPRuntime::emitUDMapperArrayInitOrDel( 9078 CodeGenFunction &MapperCGF, llvm::Value *Handle, llvm::Value *Base, 9079 llvm::Value *Begin, llvm::Value *Size, llvm::Value *MapType, 9080 CharUnits ElementSize, llvm::BasicBlock *ExitBB, bool IsInit) { 9081 StringRef Prefix = IsInit ? ".init" : ".del"; 9082 9083 // Evaluate if this is an array section. 9084 llvm::BasicBlock *IsDeleteBB = 9085 MapperCGF.createBasicBlock("omp.array" + Prefix + ".evaldelete"); 9086 llvm::BasicBlock *BodyBB = MapperCGF.createBasicBlock("omp.array" + Prefix); 9087 llvm::Value *IsArray = MapperCGF.Builder.CreateICmpSGE( 9088 Size, MapperCGF.Builder.getInt64(1), "omp.arrayinit.isarray"); 9089 MapperCGF.Builder.CreateCondBr(IsArray, IsDeleteBB, ExitBB); 9090 9091 // Evaluate if we are going to delete this section. 9092 MapperCGF.EmitBlock(IsDeleteBB); 9093 llvm::Value *DeleteBit = MapperCGF.Builder.CreateAnd( 9094 MapType, 9095 MapperCGF.Builder.getInt64(MappableExprsHandler::OMP_MAP_DELETE)); 9096 llvm::Value *DeleteCond; 9097 if (IsInit) { 9098 DeleteCond = MapperCGF.Builder.CreateIsNull( 9099 DeleteBit, "omp.array" + Prefix + ".delete"); 9100 } else { 9101 DeleteCond = MapperCGF.Builder.CreateIsNotNull( 9102 DeleteBit, "omp.array" + Prefix + ".delete"); 9103 } 9104 MapperCGF.Builder.CreateCondBr(DeleteCond, BodyBB, ExitBB); 9105 9106 MapperCGF.EmitBlock(BodyBB); 9107 // Get the array size by multiplying element size and element number (i.e., \p 9108 // Size). 9109 llvm::Value *ArraySize = MapperCGF.Builder.CreateNUWMul( 9110 Size, MapperCGF.Builder.getInt64(ElementSize.getQuantity())); 9111 // Remove OMP_MAP_TO and OMP_MAP_FROM from the map type, so that it achieves 9112 // memory allocation/deletion purpose only. 9113 llvm::Value *MapTypeArg = MapperCGF.Builder.CreateAnd( 9114 MapType, 9115 MapperCGF.Builder.getInt64(~(MappableExprsHandler::OMP_MAP_TO | 9116 MappableExprsHandler::OMP_MAP_FROM))); 9117 // Call the runtime API __tgt_push_mapper_component to fill up the runtime 9118 // data structure. 9119 llvm::Value *OffloadingArgs[] = {Handle, Base, Begin, ArraySize, MapTypeArg}; 9120 MapperCGF.EmitRuntimeCall( 9121 createRuntimeFunction(OMPRTL__tgt_push_mapper_component), OffloadingArgs); 9122 } 9123 9124 void CGOpenMPRuntime::emitTargetNumIterationsCall( 9125 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9126 llvm::Value *DeviceID, 9127 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9128 const OMPLoopDirective &D)> 9129 SizeEmitter) { 9130 OpenMPDirectiveKind Kind = D.getDirectiveKind(); 9131 const OMPExecutableDirective *TD = &D; 9132 // Get nested teams distribute kind directive, if any. 9133 if (!isOpenMPDistributeDirective(Kind) || !isOpenMPTeamsDirective(Kind)) 9134 TD = getNestedDistributeDirective(CGM.getContext(), D); 9135 if (!TD) 9136 return; 9137 const auto *LD = cast<OMPLoopDirective>(TD); 9138 auto &&CodeGen = [LD, DeviceID, SizeEmitter, this](CodeGenFunction &CGF, 9139 PrePostActionTy &) { 9140 if (llvm::Value *NumIterations = SizeEmitter(CGF, *LD)) { 9141 llvm::Value *Args[] = {DeviceID, NumIterations}; 9142 CGF.EmitRuntimeCall( 9143 createRuntimeFunction(OMPRTL__kmpc_push_target_tripcount), Args); 9144 } 9145 }; 9146 emitInlinedDirective(CGF, OMPD_unknown, CodeGen); 9147 } 9148 9149 void CGOpenMPRuntime::emitTargetCall( 9150 CodeGenFunction &CGF, const OMPExecutableDirective &D, 9151 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 9152 const Expr *Device, 9153 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 9154 const OMPLoopDirective &D)> 9155 SizeEmitter) { 9156 if (!CGF.HaveInsertPoint()) 9157 return; 9158 9159 assert(OutlinedFn && "Invalid outlined function!"); 9160 9161 const bool RequiresOuterTask = D.hasClausesOfKind<OMPDependClause>(); 9162 llvm::SmallVector<llvm::Value *, 16> CapturedVars; 9163 const CapturedStmt &CS = *D.getCapturedStmt(OMPD_target); 9164 auto &&ArgsCodegen = [&CS, &CapturedVars](CodeGenFunction &CGF, 9165 PrePostActionTy &) { 9166 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9167 }; 9168 emitInlinedDirective(CGF, OMPD_unknown, ArgsCodegen); 9169 9170 CodeGenFunction::OMPTargetDataInfo InputInfo; 9171 llvm::Value *MapTypesArray = nullptr; 9172 // Fill up the pointer arrays and transfer execution to the device. 9173 auto &&ThenGen = [this, Device, OutlinedFn, OutlinedFnID, &D, &InputInfo, 9174 &MapTypesArray, &CS, RequiresOuterTask, &CapturedVars, 9175 SizeEmitter](CodeGenFunction &CGF, PrePostActionTy &) { 9176 // On top of the arrays that were filled up, the target offloading call 9177 // takes as arguments the device id as well as the host pointer. The host 9178 // pointer is used by the runtime library to identify the current target 9179 // region, so it only has to be unique and not necessarily point to 9180 // anything. It could be the pointer to the outlined function that 9181 // implements the target region, but we aren't using that so that the 9182 // compiler doesn't need to keep that, and could therefore inline the host 9183 // function if proven worthwhile during optimization. 9184 9185 // From this point on, we need to have an ID of the target region defined. 9186 assert(OutlinedFnID && "Invalid outlined function ID!"); 9187 9188 // Emit device ID if any. 9189 llvm::Value *DeviceID; 9190 if (Device) { 9191 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9192 CGF.Int64Ty, /*isSigned=*/true); 9193 } else { 9194 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9195 } 9196 9197 // Emit the number of elements in the offloading arrays. 9198 llvm::Value *PointerNum = 9199 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 9200 9201 // Return value of the runtime offloading call. 9202 llvm::Value *Return; 9203 9204 llvm::Value *NumTeams = emitNumTeamsForTargetDirective(CGF, D); 9205 llvm::Value *NumThreads = emitNumThreadsForTargetDirective(CGF, D); 9206 9207 // Emit tripcount for the target loop-based directive. 9208 emitTargetNumIterationsCall(CGF, D, DeviceID, SizeEmitter); 9209 9210 bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 9211 // The target region is an outlined function launched by the runtime 9212 // via calls __tgt_target() or __tgt_target_teams(). 9213 // 9214 // __tgt_target() launches a target region with one team and one thread, 9215 // executing a serial region. This master thread may in turn launch 9216 // more threads within its team upon encountering a parallel region, 9217 // however, no additional teams can be launched on the device. 9218 // 9219 // __tgt_target_teams() launches a target region with one or more teams, 9220 // each with one or more threads. This call is required for target 9221 // constructs such as: 9222 // 'target teams' 9223 // 'target' / 'teams' 9224 // 'target teams distribute parallel for' 9225 // 'target parallel' 9226 // and so on. 9227 // 9228 // Note that on the host and CPU targets, the runtime implementation of 9229 // these calls simply call the outlined function without forking threads. 9230 // The outlined functions themselves have runtime calls to 9231 // __kmpc_fork_teams() and __kmpc_fork() for this purpose, codegen'd by 9232 // the compiler in emitTeamsCall() and emitParallelCall(). 9233 // 9234 // In contrast, on the NVPTX target, the implementation of 9235 // __tgt_target_teams() launches a GPU kernel with the requested number 9236 // of teams and threads so no additional calls to the runtime are required. 9237 if (NumTeams) { 9238 // If we have NumTeams defined this means that we have an enclosed teams 9239 // region. Therefore we also expect to have NumThreads defined. These two 9240 // values should be defined in the presence of a teams directive, 9241 // regardless of having any clauses associated. If the user is using teams 9242 // but no clauses, these two values will be the default that should be 9243 // passed to the runtime library - a 32-bit integer with the value zero. 9244 assert(NumThreads && "Thread limit expression should be available along " 9245 "with number of teams."); 9246 llvm::Value *OffloadingArgs[] = {DeviceID, 9247 OutlinedFnID, 9248 PointerNum, 9249 InputInfo.BasePointersArray.getPointer(), 9250 InputInfo.PointersArray.getPointer(), 9251 InputInfo.SizesArray.getPointer(), 9252 MapTypesArray, 9253 NumTeams, 9254 NumThreads}; 9255 Return = CGF.EmitRuntimeCall( 9256 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_teams_nowait 9257 : OMPRTL__tgt_target_teams), 9258 OffloadingArgs); 9259 } else { 9260 llvm::Value *OffloadingArgs[] = {DeviceID, 9261 OutlinedFnID, 9262 PointerNum, 9263 InputInfo.BasePointersArray.getPointer(), 9264 InputInfo.PointersArray.getPointer(), 9265 InputInfo.SizesArray.getPointer(), 9266 MapTypesArray}; 9267 Return = CGF.EmitRuntimeCall( 9268 createRuntimeFunction(HasNowait ? OMPRTL__tgt_target_nowait 9269 : OMPRTL__tgt_target), 9270 OffloadingArgs); 9271 } 9272 9273 // Check the error code and execute the host version if required. 9274 llvm::BasicBlock *OffloadFailedBlock = 9275 CGF.createBasicBlock("omp_offload.failed"); 9276 llvm::BasicBlock *OffloadContBlock = 9277 CGF.createBasicBlock("omp_offload.cont"); 9278 llvm::Value *Failed = CGF.Builder.CreateIsNotNull(Return); 9279 CGF.Builder.CreateCondBr(Failed, OffloadFailedBlock, OffloadContBlock); 9280 9281 CGF.EmitBlock(OffloadFailedBlock); 9282 if (RequiresOuterTask) { 9283 CapturedVars.clear(); 9284 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9285 } 9286 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9287 CGF.EmitBranch(OffloadContBlock); 9288 9289 CGF.EmitBlock(OffloadContBlock, /*IsFinished=*/true); 9290 }; 9291 9292 // Notify that the host version must be executed. 9293 auto &&ElseGen = [this, &D, OutlinedFn, &CS, &CapturedVars, 9294 RequiresOuterTask](CodeGenFunction &CGF, 9295 PrePostActionTy &) { 9296 if (RequiresOuterTask) { 9297 CapturedVars.clear(); 9298 CGF.GenerateOpenMPCapturedVars(CS, CapturedVars); 9299 } 9300 emitOutlinedFunctionCall(CGF, D.getBeginLoc(), OutlinedFn, CapturedVars); 9301 }; 9302 9303 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray, 9304 &CapturedVars, RequiresOuterTask, 9305 &CS](CodeGenFunction &CGF, PrePostActionTy &) { 9306 // Fill up the arrays with all the captured variables. 9307 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9308 MappableExprsHandler::MapValuesArrayTy Pointers; 9309 MappableExprsHandler::MapValuesArrayTy Sizes; 9310 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9311 9312 // Get mappable expression information. 9313 MappableExprsHandler MEHandler(D, CGF); 9314 llvm::DenseMap<llvm::Value *, llvm::Value *> LambdaPointers; 9315 9316 auto RI = CS.getCapturedRecordDecl()->field_begin(); 9317 auto CV = CapturedVars.begin(); 9318 for (CapturedStmt::const_capture_iterator CI = CS.capture_begin(), 9319 CE = CS.capture_end(); 9320 CI != CE; ++CI, ++RI, ++CV) { 9321 MappableExprsHandler::MapBaseValuesArrayTy CurBasePointers; 9322 MappableExprsHandler::MapValuesArrayTy CurPointers; 9323 MappableExprsHandler::MapValuesArrayTy CurSizes; 9324 MappableExprsHandler::MapFlagsArrayTy CurMapTypes; 9325 MappableExprsHandler::StructRangeInfoTy PartialStruct; 9326 9327 // VLA sizes are passed to the outlined region by copy and do not have map 9328 // information associated. 9329 if (CI->capturesVariableArrayType()) { 9330 CurBasePointers.push_back(*CV); 9331 CurPointers.push_back(*CV); 9332 CurSizes.push_back(CGF.Builder.CreateIntCast( 9333 CGF.getTypeSize(RI->getType()), CGF.Int64Ty, /*isSigned=*/true)); 9334 // Copy to the device as an argument. No need to retrieve it. 9335 CurMapTypes.push_back(MappableExprsHandler::OMP_MAP_LITERAL | 9336 MappableExprsHandler::OMP_MAP_TARGET_PARAM | 9337 MappableExprsHandler::OMP_MAP_IMPLICIT); 9338 } else { 9339 // If we have any information in the map clause, we use it, otherwise we 9340 // just do a default mapping. 9341 MEHandler.generateInfoForCapture(CI, *CV, CurBasePointers, CurPointers, 9342 CurSizes, CurMapTypes, PartialStruct); 9343 if (CurBasePointers.empty()) 9344 MEHandler.generateDefaultMapInfo(*CI, **RI, *CV, CurBasePointers, 9345 CurPointers, CurSizes, CurMapTypes); 9346 // Generate correct mapping for variables captured by reference in 9347 // lambdas. 9348 if (CI->capturesVariable()) 9349 MEHandler.generateInfoForLambdaCaptures( 9350 CI->getCapturedVar(), *CV, CurBasePointers, CurPointers, CurSizes, 9351 CurMapTypes, LambdaPointers); 9352 } 9353 // We expect to have at least an element of information for this capture. 9354 assert(!CurBasePointers.empty() && 9355 "Non-existing map pointer for capture!"); 9356 assert(CurBasePointers.size() == CurPointers.size() && 9357 CurBasePointers.size() == CurSizes.size() && 9358 CurBasePointers.size() == CurMapTypes.size() && 9359 "Inconsistent map information sizes!"); 9360 9361 // If there is an entry in PartialStruct it means we have a struct with 9362 // individual members mapped. Emit an extra combined entry. 9363 if (PartialStruct.Base.isValid()) 9364 MEHandler.emitCombinedEntry(BasePointers, Pointers, Sizes, MapTypes, 9365 CurMapTypes, PartialStruct); 9366 9367 // We need to append the results of this capture to what we already have. 9368 BasePointers.append(CurBasePointers.begin(), CurBasePointers.end()); 9369 Pointers.append(CurPointers.begin(), CurPointers.end()); 9370 Sizes.append(CurSizes.begin(), CurSizes.end()); 9371 MapTypes.append(CurMapTypes.begin(), CurMapTypes.end()); 9372 } 9373 // Adjust MEMBER_OF flags for the lambdas captures. 9374 MEHandler.adjustMemberOfForLambdaCaptures(LambdaPointers, BasePointers, 9375 Pointers, MapTypes); 9376 // Map other list items in the map clause which are not captured variables 9377 // but "declare target link" global variables. 9378 MEHandler.generateInfoForDeclareTargetLink(BasePointers, Pointers, Sizes, 9379 MapTypes); 9380 9381 TargetDataInfo Info; 9382 // Fill up the arrays and create the arguments. 9383 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9384 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 9385 Info.PointersArray, Info.SizesArray, 9386 Info.MapTypesArray, Info); 9387 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 9388 InputInfo.BasePointersArray = 9389 Address(Info.BasePointersArray, CGM.getPointerAlign()); 9390 InputInfo.PointersArray = 9391 Address(Info.PointersArray, CGM.getPointerAlign()); 9392 InputInfo.SizesArray = Address(Info.SizesArray, CGM.getPointerAlign()); 9393 MapTypesArray = Info.MapTypesArray; 9394 if (RequiresOuterTask) 9395 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 9396 else 9397 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 9398 }; 9399 9400 auto &&TargetElseGen = [this, &ElseGen, &D, RequiresOuterTask]( 9401 CodeGenFunction &CGF, PrePostActionTy &) { 9402 if (RequiresOuterTask) { 9403 CodeGenFunction::OMPTargetDataInfo InputInfo; 9404 CGF.EmitOMPTargetTaskBasedDirective(D, ElseGen, InputInfo); 9405 } else { 9406 emitInlinedDirective(CGF, D.getDirectiveKind(), ElseGen); 9407 } 9408 }; 9409 9410 // If we have a target function ID it means that we need to support 9411 // offloading, otherwise, just execute on the host. We need to execute on host 9412 // regardless of the conditional in the if clause if, e.g., the user do not 9413 // specify target triples. 9414 if (OutlinedFnID) { 9415 if (IfCond) { 9416 emitOMPIfClause(CGF, IfCond, TargetThenGen, TargetElseGen); 9417 } else { 9418 RegionCodeGenTy ThenRCG(TargetThenGen); 9419 ThenRCG(CGF); 9420 } 9421 } else { 9422 RegionCodeGenTy ElseRCG(TargetElseGen); 9423 ElseRCG(CGF); 9424 } 9425 } 9426 9427 void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S, 9428 StringRef ParentName) { 9429 if (!S) 9430 return; 9431 9432 // Codegen OMP target directives that offload compute to the device. 9433 bool RequiresDeviceCodegen = 9434 isa<OMPExecutableDirective>(S) && 9435 isOpenMPTargetExecutionDirective( 9436 cast<OMPExecutableDirective>(S)->getDirectiveKind()); 9437 9438 if (RequiresDeviceCodegen) { 9439 const auto &E = *cast<OMPExecutableDirective>(S); 9440 unsigned DeviceID; 9441 unsigned FileID; 9442 unsigned Line; 9443 getTargetEntryUniqueInfo(CGM.getContext(), E.getBeginLoc(), DeviceID, 9444 FileID, Line); 9445 9446 // Is this a target region that should not be emitted as an entry point? If 9447 // so just signal we are done with this target region. 9448 if (!OffloadEntriesInfoManager.hasTargetRegionEntryInfo(DeviceID, FileID, 9449 ParentName, Line)) 9450 return; 9451 9452 switch (E.getDirectiveKind()) { 9453 case OMPD_target: 9454 CodeGenFunction::EmitOMPTargetDeviceFunction(CGM, ParentName, 9455 cast<OMPTargetDirective>(E)); 9456 break; 9457 case OMPD_target_parallel: 9458 CodeGenFunction::EmitOMPTargetParallelDeviceFunction( 9459 CGM, ParentName, cast<OMPTargetParallelDirective>(E)); 9460 break; 9461 case OMPD_target_teams: 9462 CodeGenFunction::EmitOMPTargetTeamsDeviceFunction( 9463 CGM, ParentName, cast<OMPTargetTeamsDirective>(E)); 9464 break; 9465 case OMPD_target_teams_distribute: 9466 CodeGenFunction::EmitOMPTargetTeamsDistributeDeviceFunction( 9467 CGM, ParentName, cast<OMPTargetTeamsDistributeDirective>(E)); 9468 break; 9469 case OMPD_target_teams_distribute_simd: 9470 CodeGenFunction::EmitOMPTargetTeamsDistributeSimdDeviceFunction( 9471 CGM, ParentName, cast<OMPTargetTeamsDistributeSimdDirective>(E)); 9472 break; 9473 case OMPD_target_parallel_for: 9474 CodeGenFunction::EmitOMPTargetParallelForDeviceFunction( 9475 CGM, ParentName, cast<OMPTargetParallelForDirective>(E)); 9476 break; 9477 case OMPD_target_parallel_for_simd: 9478 CodeGenFunction::EmitOMPTargetParallelForSimdDeviceFunction( 9479 CGM, ParentName, cast<OMPTargetParallelForSimdDirective>(E)); 9480 break; 9481 case OMPD_target_simd: 9482 CodeGenFunction::EmitOMPTargetSimdDeviceFunction( 9483 CGM, ParentName, cast<OMPTargetSimdDirective>(E)); 9484 break; 9485 case OMPD_target_teams_distribute_parallel_for: 9486 CodeGenFunction::EmitOMPTargetTeamsDistributeParallelForDeviceFunction( 9487 CGM, ParentName, 9488 cast<OMPTargetTeamsDistributeParallelForDirective>(E)); 9489 break; 9490 case OMPD_target_teams_distribute_parallel_for_simd: 9491 CodeGenFunction:: 9492 EmitOMPTargetTeamsDistributeParallelForSimdDeviceFunction( 9493 CGM, ParentName, 9494 cast<OMPTargetTeamsDistributeParallelForSimdDirective>(E)); 9495 break; 9496 case OMPD_parallel: 9497 case OMPD_for: 9498 case OMPD_parallel_for: 9499 case OMPD_parallel_sections: 9500 case OMPD_for_simd: 9501 case OMPD_parallel_for_simd: 9502 case OMPD_cancel: 9503 case OMPD_cancellation_point: 9504 case OMPD_ordered: 9505 case OMPD_threadprivate: 9506 case OMPD_allocate: 9507 case OMPD_task: 9508 case OMPD_simd: 9509 case OMPD_sections: 9510 case OMPD_section: 9511 case OMPD_single: 9512 case OMPD_master: 9513 case OMPD_critical: 9514 case OMPD_taskyield: 9515 case OMPD_barrier: 9516 case OMPD_taskwait: 9517 case OMPD_taskgroup: 9518 case OMPD_atomic: 9519 case OMPD_flush: 9520 case OMPD_teams: 9521 case OMPD_target_data: 9522 case OMPD_target_exit_data: 9523 case OMPD_target_enter_data: 9524 case OMPD_distribute: 9525 case OMPD_distribute_simd: 9526 case OMPD_distribute_parallel_for: 9527 case OMPD_distribute_parallel_for_simd: 9528 case OMPD_teams_distribute: 9529 case OMPD_teams_distribute_simd: 9530 case OMPD_teams_distribute_parallel_for: 9531 case OMPD_teams_distribute_parallel_for_simd: 9532 case OMPD_target_update: 9533 case OMPD_declare_simd: 9534 case OMPD_declare_variant: 9535 case OMPD_declare_target: 9536 case OMPD_end_declare_target: 9537 case OMPD_declare_reduction: 9538 case OMPD_declare_mapper: 9539 case OMPD_taskloop: 9540 case OMPD_taskloop_simd: 9541 case OMPD_master_taskloop: 9542 case OMPD_parallel_master_taskloop: 9543 case OMPD_requires: 9544 case OMPD_unknown: 9545 llvm_unreachable("Unknown target directive for OpenMP device codegen."); 9546 } 9547 return; 9548 } 9549 9550 if (const auto *E = dyn_cast<OMPExecutableDirective>(S)) { 9551 if (!E->hasAssociatedStmt() || !E->getAssociatedStmt()) 9552 return; 9553 9554 scanForTargetRegionsFunctions( 9555 E->getInnermostCapturedStmt()->getCapturedStmt(), ParentName); 9556 return; 9557 } 9558 9559 // If this is a lambda function, look into its body. 9560 if (const auto *L = dyn_cast<LambdaExpr>(S)) 9561 S = L->getBody(); 9562 9563 // Keep looking for target regions recursively. 9564 for (const Stmt *II : S->children()) 9565 scanForTargetRegionsFunctions(II, ParentName); 9566 } 9567 9568 bool CGOpenMPRuntime::emitTargetFunctions(GlobalDecl GD) { 9569 // If emitting code for the host, we do not process FD here. Instead we do 9570 // the normal code generation. 9571 if (!CGM.getLangOpts().OpenMPIsDevice) { 9572 if (const auto *FD = dyn_cast<FunctionDecl>(GD.getDecl())) { 9573 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9574 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9575 // Do not emit device_type(nohost) functions for the host. 9576 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_NoHost) 9577 return true; 9578 } 9579 return false; 9580 } 9581 9582 const ValueDecl *VD = cast<ValueDecl>(GD.getDecl()); 9583 StringRef Name = CGM.getMangledName(GD); 9584 // Try to detect target regions in the function. 9585 if (const auto *FD = dyn_cast<FunctionDecl>(VD)) { 9586 scanForTargetRegionsFunctions(FD->getBody(), Name); 9587 Optional<OMPDeclareTargetDeclAttr::DevTypeTy> DevTy = 9588 OMPDeclareTargetDeclAttr::getDeviceType(FD); 9589 // Do not emit device_type(nohost) functions for the host. 9590 if (DevTy && *DevTy == OMPDeclareTargetDeclAttr::DT_Host) 9591 return true; 9592 } 9593 9594 // Do not to emit function if it is not marked as declare target. 9595 return !OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD) && 9596 AlreadyEmittedTargetFunctions.count(Name) == 0; 9597 } 9598 9599 bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 9600 if (!CGM.getLangOpts().OpenMPIsDevice) 9601 return false; 9602 9603 // Check if there are Ctors/Dtors in this declaration and look for target 9604 // regions in it. We use the complete variant to produce the kernel name 9605 // mangling. 9606 QualType RDTy = cast<VarDecl>(GD.getDecl())->getType(); 9607 if (const auto *RD = RDTy->getBaseElementTypeUnsafe()->getAsCXXRecordDecl()) { 9608 for (const CXXConstructorDecl *Ctor : RD->ctors()) { 9609 StringRef ParentName = 9610 CGM.getMangledName(GlobalDecl(Ctor, Ctor_Complete)); 9611 scanForTargetRegionsFunctions(Ctor->getBody(), ParentName); 9612 } 9613 if (const CXXDestructorDecl *Dtor = RD->getDestructor()) { 9614 StringRef ParentName = 9615 CGM.getMangledName(GlobalDecl(Dtor, Dtor_Complete)); 9616 scanForTargetRegionsFunctions(Dtor->getBody(), ParentName); 9617 } 9618 } 9619 9620 // Do not to emit variable if it is not marked as declare target. 9621 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9622 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( 9623 cast<VarDecl>(GD.getDecl())); 9624 if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || 9625 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9626 HasRequiresUnifiedSharedMemory)) { 9627 DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl())); 9628 return true; 9629 } 9630 return false; 9631 } 9632 9633 llvm::Constant * 9634 CGOpenMPRuntime::registerTargetFirstprivateCopy(CodeGenFunction &CGF, 9635 const VarDecl *VD) { 9636 assert(VD->getType().isConstant(CGM.getContext()) && 9637 "Expected constant variable."); 9638 StringRef VarName; 9639 llvm::Constant *Addr; 9640 llvm::GlobalValue::LinkageTypes Linkage; 9641 QualType Ty = VD->getType(); 9642 SmallString<128> Buffer; 9643 { 9644 unsigned DeviceID; 9645 unsigned FileID; 9646 unsigned Line; 9647 getTargetEntryUniqueInfo(CGM.getContext(), VD->getLocation(), DeviceID, 9648 FileID, Line); 9649 llvm::raw_svector_ostream OS(Buffer); 9650 OS << "__omp_offloading_firstprivate_" << llvm::format("_%x", DeviceID) 9651 << llvm::format("_%x_", FileID) << VD->getName() << "_l" << Line; 9652 VarName = OS.str(); 9653 } 9654 Linkage = llvm::GlobalValue::InternalLinkage; 9655 Addr = 9656 getOrCreateInternalVariable(CGM.getTypes().ConvertTypeForMem(Ty), VarName, 9657 getDefaultFirstprivateAddressSpace()); 9658 cast<llvm::GlobalValue>(Addr)->setLinkage(Linkage); 9659 CharUnits VarSize = CGM.getContext().getTypeSizeInChars(Ty); 9660 CGM.addCompilerUsedGlobal(cast<llvm::GlobalValue>(Addr)); 9661 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9662 VarName, Addr, VarSize, 9663 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo, Linkage); 9664 return Addr; 9665 } 9666 9667 void CGOpenMPRuntime::registerTargetGlobalVariable(const VarDecl *VD, 9668 llvm::Constant *Addr) { 9669 if (CGM.getLangOpts().OMPTargetTriples.empty() && 9670 !CGM.getLangOpts().OpenMPIsDevice) 9671 return; 9672 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9673 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9674 if (!Res) { 9675 if (CGM.getLangOpts().OpenMPIsDevice) { 9676 // Register non-target variables being emitted in device code (debug info 9677 // may cause this). 9678 StringRef VarName = CGM.getMangledName(VD); 9679 EmittedNonTargetVariables.try_emplace(VarName, Addr); 9680 } 9681 return; 9682 } 9683 // Register declare target variables. 9684 OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryKind Flags; 9685 StringRef VarName; 9686 CharUnits VarSize; 9687 llvm::GlobalValue::LinkageTypes Linkage; 9688 9689 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9690 !HasRequiresUnifiedSharedMemory) { 9691 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9692 VarName = CGM.getMangledName(VD); 9693 if (VD->hasDefinition(CGM.getContext()) != VarDecl::DeclarationOnly) { 9694 VarSize = CGM.getContext().getTypeSizeInChars(VD->getType()); 9695 assert(!VarSize.isZero() && "Expected non-zero size of the variable"); 9696 } else { 9697 VarSize = CharUnits::Zero(); 9698 } 9699 Linkage = CGM.getLLVMLinkageVarDefinition(VD, /*IsConstant=*/false); 9700 // Temp solution to prevent optimizations of the internal variables. 9701 if (CGM.getLangOpts().OpenMPIsDevice && !VD->isExternallyVisible()) { 9702 std::string RefName = getName({VarName, "ref"}); 9703 if (!CGM.GetGlobalValue(RefName)) { 9704 llvm::Constant *AddrRef = 9705 getOrCreateInternalVariable(Addr->getType(), RefName); 9706 auto *GVAddrRef = cast<llvm::GlobalVariable>(AddrRef); 9707 GVAddrRef->setConstant(/*Val=*/true); 9708 GVAddrRef->setLinkage(llvm::GlobalValue::InternalLinkage); 9709 GVAddrRef->setInitializer(Addr); 9710 CGM.addCompilerUsedGlobal(GVAddrRef); 9711 } 9712 } 9713 } else { 9714 assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || 9715 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9716 HasRequiresUnifiedSharedMemory)) && 9717 "Declare target attribute must link or to with unified memory."); 9718 if (*Res == OMPDeclareTargetDeclAttr::MT_Link) 9719 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryLink; 9720 else 9721 Flags = OffloadEntriesInfoManagerTy::OMPTargetGlobalVarEntryTo; 9722 9723 if (CGM.getLangOpts().OpenMPIsDevice) { 9724 VarName = Addr->getName(); 9725 Addr = nullptr; 9726 } else { 9727 VarName = getAddrOfDeclareTargetVar(VD).getName(); 9728 Addr = cast<llvm::Constant>(getAddrOfDeclareTargetVar(VD).getPointer()); 9729 } 9730 VarSize = CGM.getPointerSize(); 9731 Linkage = llvm::GlobalValue::WeakAnyLinkage; 9732 } 9733 9734 OffloadEntriesInfoManager.registerDeviceGlobalVarEntryInfo( 9735 VarName, Addr, VarSize, Flags, Linkage); 9736 } 9737 9738 bool CGOpenMPRuntime::emitTargetGlobal(GlobalDecl GD) { 9739 if (isa<FunctionDecl>(GD.getDecl()) || 9740 isa<OMPDeclareReductionDecl>(GD.getDecl())) 9741 return emitTargetFunctions(GD); 9742 9743 return emitTargetGlobalVariable(GD); 9744 } 9745 9746 void CGOpenMPRuntime::emitDeferredTargetDecls() const { 9747 for (const VarDecl *VD : DeferredGlobalVariables) { 9748 llvm::Optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res = 9749 OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); 9750 if (!Res) 9751 continue; 9752 if (*Res == OMPDeclareTargetDeclAttr::MT_To && 9753 !HasRequiresUnifiedSharedMemory) { 9754 CGM.EmitGlobal(VD); 9755 } else { 9756 assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || 9757 (*Res == OMPDeclareTargetDeclAttr::MT_To && 9758 HasRequiresUnifiedSharedMemory)) && 9759 "Expected link clause or to clause with unified memory."); 9760 (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); 9761 } 9762 } 9763 } 9764 9765 void CGOpenMPRuntime::adjustTargetSpecificDataForLambdas( 9766 CodeGenFunction &CGF, const OMPExecutableDirective &D) const { 9767 assert(isOpenMPTargetExecutionDirective(D.getDirectiveKind()) && 9768 " Expected target-based directive."); 9769 } 9770 9771 void CGOpenMPRuntime::checkArchForUnifiedAddressing( 9772 const OMPRequiresDecl *D) { 9773 for (const OMPClause *Clause : D->clauselists()) { 9774 if (Clause->getClauseKind() == OMPC_unified_shared_memory) { 9775 HasRequiresUnifiedSharedMemory = true; 9776 break; 9777 } 9778 } 9779 } 9780 9781 bool CGOpenMPRuntime::hasAllocateAttributeForGlobalVar(const VarDecl *VD, 9782 LangAS &AS) { 9783 if (!VD || !VD->hasAttr<OMPAllocateDeclAttr>()) 9784 return false; 9785 const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); 9786 switch(A->getAllocatorType()) { 9787 case OMPAllocateDeclAttr::OMPDefaultMemAlloc: 9788 // Not supported, fallback to the default mem space. 9789 case OMPAllocateDeclAttr::OMPLargeCapMemAlloc: 9790 case OMPAllocateDeclAttr::OMPCGroupMemAlloc: 9791 case OMPAllocateDeclAttr::OMPHighBWMemAlloc: 9792 case OMPAllocateDeclAttr::OMPLowLatMemAlloc: 9793 case OMPAllocateDeclAttr::OMPThreadMemAlloc: 9794 case OMPAllocateDeclAttr::OMPConstMemAlloc: 9795 case OMPAllocateDeclAttr::OMPPTeamMemAlloc: 9796 AS = LangAS::Default; 9797 return true; 9798 case OMPAllocateDeclAttr::OMPUserDefinedMemAlloc: 9799 llvm_unreachable("Expected predefined allocator for the variables with the " 9800 "static storage."); 9801 } 9802 return false; 9803 } 9804 9805 bool CGOpenMPRuntime::hasRequiresUnifiedSharedMemory() const { 9806 return HasRequiresUnifiedSharedMemory; 9807 } 9808 9809 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::DisableAutoDeclareTargetRAII( 9810 CodeGenModule &CGM) 9811 : CGM(CGM) { 9812 if (CGM.getLangOpts().OpenMPIsDevice) { 9813 SavedShouldMarkAsGlobal = CGM.getOpenMPRuntime().ShouldMarkAsGlobal; 9814 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = false; 9815 } 9816 } 9817 9818 CGOpenMPRuntime::DisableAutoDeclareTargetRAII::~DisableAutoDeclareTargetRAII() { 9819 if (CGM.getLangOpts().OpenMPIsDevice) 9820 CGM.getOpenMPRuntime().ShouldMarkAsGlobal = SavedShouldMarkAsGlobal; 9821 } 9822 9823 bool CGOpenMPRuntime::markAsGlobalTarget(GlobalDecl GD) { 9824 if (!CGM.getLangOpts().OpenMPIsDevice || !ShouldMarkAsGlobal) 9825 return true; 9826 9827 StringRef Name = CGM.getMangledName(GD); 9828 const auto *D = cast<FunctionDecl>(GD.getDecl()); 9829 // Do not to emit function if it is marked as declare target as it was already 9830 // emitted. 9831 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(D)) { 9832 if (D->hasBody() && AlreadyEmittedTargetFunctions.count(Name) == 0) { 9833 if (auto *F = dyn_cast_or_null<llvm::Function>(CGM.GetGlobalValue(Name))) 9834 return !F->isDeclaration(); 9835 return false; 9836 } 9837 return true; 9838 } 9839 9840 return !AlreadyEmittedTargetFunctions.insert(Name).second; 9841 } 9842 9843 llvm::Function *CGOpenMPRuntime::emitRequiresDirectiveRegFun() { 9844 // If we don't have entries or if we are emitting code for the device, we 9845 // don't need to do anything. 9846 if (CGM.getLangOpts().OMPTargetTriples.empty() || 9847 CGM.getLangOpts().OpenMPSimd || CGM.getLangOpts().OpenMPIsDevice || 9848 (OffloadEntriesInfoManager.empty() && 9849 !HasEmittedDeclareTargetRegion && 9850 !HasEmittedTargetRegion)) 9851 return nullptr; 9852 9853 // Create and register the function that handles the requires directives. 9854 ASTContext &C = CGM.getContext(); 9855 9856 llvm::Function *RequiresRegFn; 9857 { 9858 CodeGenFunction CGF(CGM); 9859 const auto &FI = CGM.getTypes().arrangeNullaryFunction(); 9860 llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType(FI); 9861 std::string ReqName = getName({"omp_offloading", "requires_reg"}); 9862 RequiresRegFn = CGM.CreateGlobalInitOrDestructFunction(FTy, ReqName, FI); 9863 CGF.StartFunction(GlobalDecl(), C.VoidTy, RequiresRegFn, FI, {}); 9864 OpenMPOffloadingRequiresDirFlags Flags = OMP_REQ_NONE; 9865 // TODO: check for other requires clauses. 9866 // The requires directive takes effect only when a target region is 9867 // present in the compilation unit. Otherwise it is ignored and not 9868 // passed to the runtime. This avoids the runtime from throwing an error 9869 // for mismatching requires clauses across compilation units that don't 9870 // contain at least 1 target region. 9871 assert((HasEmittedTargetRegion || 9872 HasEmittedDeclareTargetRegion || 9873 !OffloadEntriesInfoManager.empty()) && 9874 "Target or declare target region expected."); 9875 if (HasRequiresUnifiedSharedMemory) 9876 Flags = OMP_REQ_UNIFIED_SHARED_MEMORY; 9877 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_register_requires), 9878 llvm::ConstantInt::get(CGM.Int64Ty, Flags)); 9879 CGF.FinishFunction(); 9880 } 9881 return RequiresRegFn; 9882 } 9883 9884 void CGOpenMPRuntime::emitTeamsCall(CodeGenFunction &CGF, 9885 const OMPExecutableDirective &D, 9886 SourceLocation Loc, 9887 llvm::Function *OutlinedFn, 9888 ArrayRef<llvm::Value *> CapturedVars) { 9889 if (!CGF.HaveInsertPoint()) 9890 return; 9891 9892 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9893 CodeGenFunction::RunCleanupsScope Scope(CGF); 9894 9895 // Build call __kmpc_fork_teams(loc, n, microtask, var1, .., varn); 9896 llvm::Value *Args[] = { 9897 RTLoc, 9898 CGF.Builder.getInt32(CapturedVars.size()), // Number of captured vars 9899 CGF.Builder.CreateBitCast(OutlinedFn, getKmpc_MicroPointerTy())}; 9900 llvm::SmallVector<llvm::Value *, 16> RealArgs; 9901 RealArgs.append(std::begin(Args), std::end(Args)); 9902 RealArgs.append(CapturedVars.begin(), CapturedVars.end()); 9903 9904 llvm::FunctionCallee RTLFn = createRuntimeFunction(OMPRTL__kmpc_fork_teams); 9905 CGF.EmitRuntimeCall(RTLFn, RealArgs); 9906 } 9907 9908 void CGOpenMPRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 9909 const Expr *NumTeams, 9910 const Expr *ThreadLimit, 9911 SourceLocation Loc) { 9912 if (!CGF.HaveInsertPoint()) 9913 return; 9914 9915 llvm::Value *RTLoc = emitUpdateLocation(CGF, Loc); 9916 9917 llvm::Value *NumTeamsVal = 9918 NumTeams 9919 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(NumTeams), 9920 CGF.CGM.Int32Ty, /* isSigned = */ true) 9921 : CGF.Builder.getInt32(0); 9922 9923 llvm::Value *ThreadLimitVal = 9924 ThreadLimit 9925 ? CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(ThreadLimit), 9926 CGF.CGM.Int32Ty, /* isSigned = */ true) 9927 : CGF.Builder.getInt32(0); 9928 9929 // Build call __kmpc_push_num_teamss(&loc, global_tid, num_teams, thread_limit) 9930 llvm::Value *PushNumTeamsArgs[] = {RTLoc, getThreadID(CGF, Loc), NumTeamsVal, 9931 ThreadLimitVal}; 9932 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_push_num_teams), 9933 PushNumTeamsArgs); 9934 } 9935 9936 void CGOpenMPRuntime::emitTargetDataCalls( 9937 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 9938 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 9939 if (!CGF.HaveInsertPoint()) 9940 return; 9941 9942 // Action used to replace the default codegen action and turn privatization 9943 // off. 9944 PrePostActionTy NoPrivAction; 9945 9946 // Generate the code for the opening of the data environment. Capture all the 9947 // arguments of the runtime call by reference because they are used in the 9948 // closing of the region. 9949 auto &&BeginThenGen = [this, &D, Device, &Info, 9950 &CodeGen](CodeGenFunction &CGF, PrePostActionTy &) { 9951 // Fill up the arrays with all the mapped variables. 9952 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 9953 MappableExprsHandler::MapValuesArrayTy Pointers; 9954 MappableExprsHandler::MapValuesArrayTy Sizes; 9955 MappableExprsHandler::MapFlagsArrayTy MapTypes; 9956 9957 // Get map clause information. 9958 MappableExprsHandler MCHandler(D, CGF); 9959 MCHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 9960 9961 // Fill up the arrays and create the arguments. 9962 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 9963 9964 llvm::Value *BasePointersArrayArg = nullptr; 9965 llvm::Value *PointersArrayArg = nullptr; 9966 llvm::Value *SizesArrayArg = nullptr; 9967 llvm::Value *MapTypesArrayArg = nullptr; 9968 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 9969 SizesArrayArg, MapTypesArrayArg, Info); 9970 9971 // Emit device ID if any. 9972 llvm::Value *DeviceID = nullptr; 9973 if (Device) { 9974 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 9975 CGF.Int64Ty, /*isSigned=*/true); 9976 } else { 9977 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 9978 } 9979 9980 // Emit the number of elements in the offloading arrays. 9981 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 9982 9983 llvm::Value *OffloadingArgs[] = { 9984 DeviceID, PointerNum, BasePointersArrayArg, 9985 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 9986 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_begin), 9987 OffloadingArgs); 9988 9989 // If device pointer privatization is required, emit the body of the region 9990 // here. It will have to be duplicated: with and without privatization. 9991 if (!Info.CaptureDeviceAddrMap.empty()) 9992 CodeGen(CGF); 9993 }; 9994 9995 // Generate code for the closing of the data region. 9996 auto &&EndThenGen = [this, Device, &Info](CodeGenFunction &CGF, 9997 PrePostActionTy &) { 9998 assert(Info.isValid() && "Invalid data environment closing arguments."); 9999 10000 llvm::Value *BasePointersArrayArg = nullptr; 10001 llvm::Value *PointersArrayArg = nullptr; 10002 llvm::Value *SizesArrayArg = nullptr; 10003 llvm::Value *MapTypesArrayArg = nullptr; 10004 emitOffloadingArraysArgument(CGF, BasePointersArrayArg, PointersArrayArg, 10005 SizesArrayArg, MapTypesArrayArg, Info); 10006 10007 // Emit device ID if any. 10008 llvm::Value *DeviceID = nullptr; 10009 if (Device) { 10010 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10011 CGF.Int64Ty, /*isSigned=*/true); 10012 } else { 10013 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10014 } 10015 10016 // Emit the number of elements in the offloading arrays. 10017 llvm::Value *PointerNum = CGF.Builder.getInt32(Info.NumberOfPtrs); 10018 10019 llvm::Value *OffloadingArgs[] = { 10020 DeviceID, PointerNum, BasePointersArrayArg, 10021 PointersArrayArg, SizesArrayArg, MapTypesArrayArg}; 10022 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__tgt_target_data_end), 10023 OffloadingArgs); 10024 }; 10025 10026 // If we need device pointer privatization, we need to emit the body of the 10027 // region with no privatization in the 'else' branch of the conditional. 10028 // Otherwise, we don't have to do anything. 10029 auto &&BeginElseGen = [&Info, &CodeGen, &NoPrivAction](CodeGenFunction &CGF, 10030 PrePostActionTy &) { 10031 if (!Info.CaptureDeviceAddrMap.empty()) { 10032 CodeGen.setAction(NoPrivAction); 10033 CodeGen(CGF); 10034 } 10035 }; 10036 10037 // We don't have to do anything to close the region if the if clause evaluates 10038 // to false. 10039 auto &&EndElseGen = [](CodeGenFunction &CGF, PrePostActionTy &) {}; 10040 10041 if (IfCond) { 10042 emitOMPIfClause(CGF, IfCond, BeginThenGen, BeginElseGen); 10043 } else { 10044 RegionCodeGenTy RCG(BeginThenGen); 10045 RCG(CGF); 10046 } 10047 10048 // If we don't require privatization of device pointers, we emit the body in 10049 // between the runtime calls. This avoids duplicating the body code. 10050 if (Info.CaptureDeviceAddrMap.empty()) { 10051 CodeGen.setAction(NoPrivAction); 10052 CodeGen(CGF); 10053 } 10054 10055 if (IfCond) { 10056 emitOMPIfClause(CGF, IfCond, EndThenGen, EndElseGen); 10057 } else { 10058 RegionCodeGenTy RCG(EndThenGen); 10059 RCG(CGF); 10060 } 10061 } 10062 10063 void CGOpenMPRuntime::emitTargetDataStandAloneCall( 10064 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 10065 const Expr *Device) { 10066 if (!CGF.HaveInsertPoint()) 10067 return; 10068 10069 assert((isa<OMPTargetEnterDataDirective>(D) || 10070 isa<OMPTargetExitDataDirective>(D) || 10071 isa<OMPTargetUpdateDirective>(D)) && 10072 "Expecting either target enter, exit data, or update directives."); 10073 10074 CodeGenFunction::OMPTargetDataInfo InputInfo; 10075 llvm::Value *MapTypesArray = nullptr; 10076 // Generate the code for the opening of the data environment. 10077 auto &&ThenGen = [this, &D, Device, &InputInfo, 10078 &MapTypesArray](CodeGenFunction &CGF, PrePostActionTy &) { 10079 // Emit device ID if any. 10080 llvm::Value *DeviceID = nullptr; 10081 if (Device) { 10082 DeviceID = CGF.Builder.CreateIntCast(CGF.EmitScalarExpr(Device), 10083 CGF.Int64Ty, /*isSigned=*/true); 10084 } else { 10085 DeviceID = CGF.Builder.getInt64(OMP_DEVICEID_UNDEF); 10086 } 10087 10088 // Emit the number of elements in the offloading arrays. 10089 llvm::Constant *PointerNum = 10090 CGF.Builder.getInt32(InputInfo.NumberOfTargetItems); 10091 10092 llvm::Value *OffloadingArgs[] = {DeviceID, 10093 PointerNum, 10094 InputInfo.BasePointersArray.getPointer(), 10095 InputInfo.PointersArray.getPointer(), 10096 InputInfo.SizesArray.getPointer(), 10097 MapTypesArray}; 10098 10099 // Select the right runtime function call for each expected standalone 10100 // directive. 10101 const bool HasNowait = D.hasClausesOfKind<OMPNowaitClause>(); 10102 OpenMPRTLFunction RTLFn; 10103 switch (D.getDirectiveKind()) { 10104 case OMPD_target_enter_data: 10105 RTLFn = HasNowait ? OMPRTL__tgt_target_data_begin_nowait 10106 : OMPRTL__tgt_target_data_begin; 10107 break; 10108 case OMPD_target_exit_data: 10109 RTLFn = HasNowait ? OMPRTL__tgt_target_data_end_nowait 10110 : OMPRTL__tgt_target_data_end; 10111 break; 10112 case OMPD_target_update: 10113 RTLFn = HasNowait ? OMPRTL__tgt_target_data_update_nowait 10114 : OMPRTL__tgt_target_data_update; 10115 break; 10116 case OMPD_parallel: 10117 case OMPD_for: 10118 case OMPD_parallel_for: 10119 case OMPD_parallel_sections: 10120 case OMPD_for_simd: 10121 case OMPD_parallel_for_simd: 10122 case OMPD_cancel: 10123 case OMPD_cancellation_point: 10124 case OMPD_ordered: 10125 case OMPD_threadprivate: 10126 case OMPD_allocate: 10127 case OMPD_task: 10128 case OMPD_simd: 10129 case OMPD_sections: 10130 case OMPD_section: 10131 case OMPD_single: 10132 case OMPD_master: 10133 case OMPD_critical: 10134 case OMPD_taskyield: 10135 case OMPD_barrier: 10136 case OMPD_taskwait: 10137 case OMPD_taskgroup: 10138 case OMPD_atomic: 10139 case OMPD_flush: 10140 case OMPD_teams: 10141 case OMPD_target_data: 10142 case OMPD_distribute: 10143 case OMPD_distribute_simd: 10144 case OMPD_distribute_parallel_for: 10145 case OMPD_distribute_parallel_for_simd: 10146 case OMPD_teams_distribute: 10147 case OMPD_teams_distribute_simd: 10148 case OMPD_teams_distribute_parallel_for: 10149 case OMPD_teams_distribute_parallel_for_simd: 10150 case OMPD_declare_simd: 10151 case OMPD_declare_variant: 10152 case OMPD_declare_target: 10153 case OMPD_end_declare_target: 10154 case OMPD_declare_reduction: 10155 case OMPD_declare_mapper: 10156 case OMPD_taskloop: 10157 case OMPD_taskloop_simd: 10158 case OMPD_master_taskloop: 10159 case OMPD_parallel_master_taskloop: 10160 case OMPD_target: 10161 case OMPD_target_simd: 10162 case OMPD_target_teams_distribute: 10163 case OMPD_target_teams_distribute_simd: 10164 case OMPD_target_teams_distribute_parallel_for: 10165 case OMPD_target_teams_distribute_parallel_for_simd: 10166 case OMPD_target_teams: 10167 case OMPD_target_parallel: 10168 case OMPD_target_parallel_for: 10169 case OMPD_target_parallel_for_simd: 10170 case OMPD_requires: 10171 case OMPD_unknown: 10172 llvm_unreachable("Unexpected standalone target data directive."); 10173 break; 10174 } 10175 CGF.EmitRuntimeCall(createRuntimeFunction(RTLFn), OffloadingArgs); 10176 }; 10177 10178 auto &&TargetThenGen = [this, &ThenGen, &D, &InputInfo, &MapTypesArray]( 10179 CodeGenFunction &CGF, PrePostActionTy &) { 10180 // Fill up the arrays with all the mapped variables. 10181 MappableExprsHandler::MapBaseValuesArrayTy BasePointers; 10182 MappableExprsHandler::MapValuesArrayTy Pointers; 10183 MappableExprsHandler::MapValuesArrayTy Sizes; 10184 MappableExprsHandler::MapFlagsArrayTy MapTypes; 10185 10186 // Get map clause information. 10187 MappableExprsHandler MEHandler(D, CGF); 10188 MEHandler.generateAllInfo(BasePointers, Pointers, Sizes, MapTypes); 10189 10190 TargetDataInfo Info; 10191 // Fill up the arrays and create the arguments. 10192 emitOffloadingArrays(CGF, BasePointers, Pointers, Sizes, MapTypes, Info); 10193 emitOffloadingArraysArgument(CGF, Info.BasePointersArray, 10194 Info.PointersArray, Info.SizesArray, 10195 Info.MapTypesArray, Info); 10196 InputInfo.NumberOfTargetItems = Info.NumberOfPtrs; 10197 InputInfo.BasePointersArray = 10198 Address(Info.BasePointersArray, CGM.getPointerAlign()); 10199 InputInfo.PointersArray = 10200 Address(Info.PointersArray, CGM.getPointerAlign()); 10201 InputInfo.SizesArray = 10202 Address(Info.SizesArray, CGM.getPointerAlign()); 10203 MapTypesArray = Info.MapTypesArray; 10204 if (D.hasClausesOfKind<OMPDependClause>()) 10205 CGF.EmitOMPTargetTaskBasedDirective(D, ThenGen, InputInfo); 10206 else 10207 emitInlinedDirective(CGF, D.getDirectiveKind(), ThenGen); 10208 }; 10209 10210 if (IfCond) { 10211 emitOMPIfClause(CGF, IfCond, TargetThenGen, 10212 [](CodeGenFunction &CGF, PrePostActionTy &) {}); 10213 } else { 10214 RegionCodeGenTy ThenRCG(TargetThenGen); 10215 ThenRCG(CGF); 10216 } 10217 } 10218 10219 namespace { 10220 /// Kind of parameter in a function with 'declare simd' directive. 10221 enum ParamKindTy { LinearWithVarStride, Linear, Uniform, Vector }; 10222 /// Attribute set of the parameter. 10223 struct ParamAttrTy { 10224 ParamKindTy Kind = Vector; 10225 llvm::APSInt StrideOrArg; 10226 llvm::APSInt Alignment; 10227 }; 10228 } // namespace 10229 10230 static unsigned evaluateCDTSize(const FunctionDecl *FD, 10231 ArrayRef<ParamAttrTy> ParamAttrs) { 10232 // Every vector variant of a SIMD-enabled function has a vector length (VLEN). 10233 // If OpenMP clause "simdlen" is used, the VLEN is the value of the argument 10234 // of that clause. The VLEN value must be power of 2. 10235 // In other case the notion of the function`s "characteristic data type" (CDT) 10236 // is used to compute the vector length. 10237 // CDT is defined in the following order: 10238 // a) For non-void function, the CDT is the return type. 10239 // b) If the function has any non-uniform, non-linear parameters, then the 10240 // CDT is the type of the first such parameter. 10241 // c) If the CDT determined by a) or b) above is struct, union, or class 10242 // type which is pass-by-value (except for the type that maps to the 10243 // built-in complex data type), the characteristic data type is int. 10244 // d) If none of the above three cases is applicable, the CDT is int. 10245 // The VLEN is then determined based on the CDT and the size of vector 10246 // register of that ISA for which current vector version is generated. The 10247 // VLEN is computed using the formula below: 10248 // VLEN = sizeof(vector_register) / sizeof(CDT), 10249 // where vector register size specified in section 3.2.1 Registers and the 10250 // Stack Frame of original AMD64 ABI document. 10251 QualType RetType = FD->getReturnType(); 10252 if (RetType.isNull()) 10253 return 0; 10254 ASTContext &C = FD->getASTContext(); 10255 QualType CDT; 10256 if (!RetType.isNull() && !RetType->isVoidType()) { 10257 CDT = RetType; 10258 } else { 10259 unsigned Offset = 0; 10260 if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { 10261 if (ParamAttrs[Offset].Kind == Vector) 10262 CDT = C.getPointerType(C.getRecordType(MD->getParent())); 10263 ++Offset; 10264 } 10265 if (CDT.isNull()) { 10266 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10267 if (ParamAttrs[I + Offset].Kind == Vector) { 10268 CDT = FD->getParamDecl(I)->getType(); 10269 break; 10270 } 10271 } 10272 } 10273 } 10274 if (CDT.isNull()) 10275 CDT = C.IntTy; 10276 CDT = CDT->getCanonicalTypeUnqualified(); 10277 if (CDT->isRecordType() || CDT->isUnionType()) 10278 CDT = C.IntTy; 10279 return C.getTypeSize(CDT); 10280 } 10281 10282 static void 10283 emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn, 10284 const llvm::APSInt &VLENVal, 10285 ArrayRef<ParamAttrTy> ParamAttrs, 10286 OMPDeclareSimdDeclAttr::BranchStateTy State) { 10287 struct ISADataTy { 10288 char ISA; 10289 unsigned VecRegSize; 10290 }; 10291 ISADataTy ISAData[] = { 10292 { 10293 'b', 128 10294 }, // SSE 10295 { 10296 'c', 256 10297 }, // AVX 10298 { 10299 'd', 256 10300 }, // AVX2 10301 { 10302 'e', 512 10303 }, // AVX512 10304 }; 10305 llvm::SmallVector<char, 2> Masked; 10306 switch (State) { 10307 case OMPDeclareSimdDeclAttr::BS_Undefined: 10308 Masked.push_back('N'); 10309 Masked.push_back('M'); 10310 break; 10311 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10312 Masked.push_back('N'); 10313 break; 10314 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10315 Masked.push_back('M'); 10316 break; 10317 } 10318 for (char Mask : Masked) { 10319 for (const ISADataTy &Data : ISAData) { 10320 SmallString<256> Buffer; 10321 llvm::raw_svector_ostream Out(Buffer); 10322 Out << "_ZGV" << Data.ISA << Mask; 10323 if (!VLENVal) { 10324 unsigned NumElts = evaluateCDTSize(FD, ParamAttrs); 10325 assert(NumElts && "Non-zero simdlen/cdtsize expected"); 10326 Out << llvm::APSInt::getUnsigned(Data.VecRegSize / NumElts); 10327 } else { 10328 Out << VLENVal; 10329 } 10330 for (const ParamAttrTy &ParamAttr : ParamAttrs) { 10331 switch (ParamAttr.Kind){ 10332 case LinearWithVarStride: 10333 Out << 's' << ParamAttr.StrideOrArg; 10334 break; 10335 case Linear: 10336 Out << 'l'; 10337 if (!!ParamAttr.StrideOrArg) 10338 Out << ParamAttr.StrideOrArg; 10339 break; 10340 case Uniform: 10341 Out << 'u'; 10342 break; 10343 case Vector: 10344 Out << 'v'; 10345 break; 10346 } 10347 if (!!ParamAttr.Alignment) 10348 Out << 'a' << ParamAttr.Alignment; 10349 } 10350 Out << '_' << Fn->getName(); 10351 Fn->addFnAttr(Out.str()); 10352 } 10353 } 10354 } 10355 10356 // This are the Functions that are needed to mangle the name of the 10357 // vector functions generated by the compiler, according to the rules 10358 // defined in the "Vector Function ABI specifications for AArch64", 10359 // available at 10360 // https://developer.arm.com/products/software-development-tools/hpc/arm-compiler-for-hpc/vector-function-abi. 10361 10362 /// Maps To Vector (MTV), as defined in 3.1.1 of the AAVFABI. 10363 /// 10364 /// TODO: Need to implement the behavior for reference marked with a 10365 /// var or no linear modifiers (1.b in the section). For this, we 10366 /// need to extend ParamKindTy to support the linear modifiers. 10367 static bool getAArch64MTV(QualType QT, ParamKindTy Kind) { 10368 QT = QT.getCanonicalType(); 10369 10370 if (QT->isVoidType()) 10371 return false; 10372 10373 if (Kind == ParamKindTy::Uniform) 10374 return false; 10375 10376 if (Kind == ParamKindTy::Linear) 10377 return false; 10378 10379 // TODO: Handle linear references with modifiers 10380 10381 if (Kind == ParamKindTy::LinearWithVarStride) 10382 return false; 10383 10384 return true; 10385 } 10386 10387 /// Pass By Value (PBV), as defined in 3.1.2 of the AAVFABI. 10388 static bool getAArch64PBV(QualType QT, ASTContext &C) { 10389 QT = QT.getCanonicalType(); 10390 unsigned Size = C.getTypeSize(QT); 10391 10392 // Only scalars and complex within 16 bytes wide set PVB to true. 10393 if (Size != 8 && Size != 16 && Size != 32 && Size != 64 && Size != 128) 10394 return false; 10395 10396 if (QT->isFloatingType()) 10397 return true; 10398 10399 if (QT->isIntegerType()) 10400 return true; 10401 10402 if (QT->isPointerType()) 10403 return true; 10404 10405 // TODO: Add support for complex types (section 3.1.2, item 2). 10406 10407 return false; 10408 } 10409 10410 /// Computes the lane size (LS) of a return type or of an input parameter, 10411 /// as defined by `LS(P)` in 3.2.1 of the AAVFABI. 10412 /// TODO: Add support for references, section 3.2.1, item 1. 10413 static unsigned getAArch64LS(QualType QT, ParamKindTy Kind, ASTContext &C) { 10414 if (getAArch64MTV(QT, Kind) && QT.getCanonicalType()->isPointerType()) { 10415 QualType PTy = QT.getCanonicalType()->getPointeeType(); 10416 if (getAArch64PBV(PTy, C)) 10417 return C.getTypeSize(PTy); 10418 } 10419 if (getAArch64PBV(QT, C)) 10420 return C.getTypeSize(QT); 10421 10422 return C.getTypeSize(C.getUIntPtrType()); 10423 } 10424 10425 // Get Narrowest Data Size (NDS) and Widest Data Size (WDS) from the 10426 // signature of the scalar function, as defined in 3.2.2 of the 10427 // AAVFABI. 10428 static std::tuple<unsigned, unsigned, bool> 10429 getNDSWDS(const FunctionDecl *FD, ArrayRef<ParamAttrTy> ParamAttrs) { 10430 QualType RetType = FD->getReturnType().getCanonicalType(); 10431 10432 ASTContext &C = FD->getASTContext(); 10433 10434 bool OutputBecomesInput = false; 10435 10436 llvm::SmallVector<unsigned, 8> Sizes; 10437 if (!RetType->isVoidType()) { 10438 Sizes.push_back(getAArch64LS(RetType, ParamKindTy::Vector, C)); 10439 if (!getAArch64PBV(RetType, C) && getAArch64MTV(RetType, {})) 10440 OutputBecomesInput = true; 10441 } 10442 for (unsigned I = 0, E = FD->getNumParams(); I < E; ++I) { 10443 QualType QT = FD->getParamDecl(I)->getType().getCanonicalType(); 10444 Sizes.push_back(getAArch64LS(QT, ParamAttrs[I].Kind, C)); 10445 } 10446 10447 assert(!Sizes.empty() && "Unable to determine NDS and WDS."); 10448 // The LS of a function parameter / return value can only be a power 10449 // of 2, starting from 8 bits, up to 128. 10450 assert(std::all_of(Sizes.begin(), Sizes.end(), 10451 [](unsigned Size) { 10452 return Size == 8 || Size == 16 || Size == 32 || 10453 Size == 64 || Size == 128; 10454 }) && 10455 "Invalid size"); 10456 10457 return std::make_tuple(*std::min_element(std::begin(Sizes), std::end(Sizes)), 10458 *std::max_element(std::begin(Sizes), std::end(Sizes)), 10459 OutputBecomesInput); 10460 } 10461 10462 /// Mangle the parameter part of the vector function name according to 10463 /// their OpenMP classification. The mangling function is defined in 10464 /// section 3.5 of the AAVFABI. 10465 static std::string mangleVectorParameters(ArrayRef<ParamAttrTy> ParamAttrs) { 10466 SmallString<256> Buffer; 10467 llvm::raw_svector_ostream Out(Buffer); 10468 for (const auto &ParamAttr : ParamAttrs) { 10469 switch (ParamAttr.Kind) { 10470 case LinearWithVarStride: 10471 Out << "ls" << ParamAttr.StrideOrArg; 10472 break; 10473 case Linear: 10474 Out << 'l'; 10475 // Don't print the step value if it is not present or if it is 10476 // equal to 1. 10477 if (!!ParamAttr.StrideOrArg && ParamAttr.StrideOrArg != 1) 10478 Out << ParamAttr.StrideOrArg; 10479 break; 10480 case Uniform: 10481 Out << 'u'; 10482 break; 10483 case Vector: 10484 Out << 'v'; 10485 break; 10486 } 10487 10488 if (!!ParamAttr.Alignment) 10489 Out << 'a' << ParamAttr.Alignment; 10490 } 10491 10492 return Out.str(); 10493 } 10494 10495 // Function used to add the attribute. The parameter `VLEN` is 10496 // templated to allow the use of "x" when targeting scalable functions 10497 // for SVE. 10498 template <typename T> 10499 static void addAArch64VectorName(T VLEN, StringRef LMask, StringRef Prefix, 10500 char ISA, StringRef ParSeq, 10501 StringRef MangledName, bool OutputBecomesInput, 10502 llvm::Function *Fn) { 10503 SmallString<256> Buffer; 10504 llvm::raw_svector_ostream Out(Buffer); 10505 Out << Prefix << ISA << LMask << VLEN; 10506 if (OutputBecomesInput) 10507 Out << "v"; 10508 Out << ParSeq << "_" << MangledName; 10509 Fn->addFnAttr(Out.str()); 10510 } 10511 10512 // Helper function to generate the Advanced SIMD names depending on 10513 // the value of the NDS when simdlen is not present. 10514 static void addAArch64AdvSIMDNDSNames(unsigned NDS, StringRef Mask, 10515 StringRef Prefix, char ISA, 10516 StringRef ParSeq, StringRef MangledName, 10517 bool OutputBecomesInput, 10518 llvm::Function *Fn) { 10519 switch (NDS) { 10520 case 8: 10521 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10522 OutputBecomesInput, Fn); 10523 addAArch64VectorName(16, Mask, Prefix, ISA, ParSeq, MangledName, 10524 OutputBecomesInput, Fn); 10525 break; 10526 case 16: 10527 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10528 OutputBecomesInput, Fn); 10529 addAArch64VectorName(8, Mask, Prefix, ISA, ParSeq, MangledName, 10530 OutputBecomesInput, Fn); 10531 break; 10532 case 32: 10533 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10534 OutputBecomesInput, Fn); 10535 addAArch64VectorName(4, Mask, Prefix, ISA, ParSeq, MangledName, 10536 OutputBecomesInput, Fn); 10537 break; 10538 case 64: 10539 case 128: 10540 addAArch64VectorName(2, Mask, Prefix, ISA, ParSeq, MangledName, 10541 OutputBecomesInput, Fn); 10542 break; 10543 default: 10544 llvm_unreachable("Scalar type is too wide."); 10545 } 10546 } 10547 10548 /// Emit vector function attributes for AArch64, as defined in the AAVFABI. 10549 static void emitAArch64DeclareSimdFunction( 10550 CodeGenModule &CGM, const FunctionDecl *FD, unsigned UserVLEN, 10551 ArrayRef<ParamAttrTy> ParamAttrs, 10552 OMPDeclareSimdDeclAttr::BranchStateTy State, StringRef MangledName, 10553 char ISA, unsigned VecRegSize, llvm::Function *Fn, SourceLocation SLoc) { 10554 10555 // Get basic data for building the vector signature. 10556 const auto Data = getNDSWDS(FD, ParamAttrs); 10557 const unsigned NDS = std::get<0>(Data); 10558 const unsigned WDS = std::get<1>(Data); 10559 const bool OutputBecomesInput = std::get<2>(Data); 10560 10561 // Check the values provided via `simdlen` by the user. 10562 // 1. A `simdlen(1)` doesn't produce vector signatures, 10563 if (UserVLEN == 1) { 10564 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10565 DiagnosticsEngine::Warning, 10566 "The clause simdlen(1) has no effect when targeting aarch64."); 10567 CGM.getDiags().Report(SLoc, DiagID); 10568 return; 10569 } 10570 10571 // 2. Section 3.3.1, item 1: user input must be a power of 2 for 10572 // Advanced SIMD output. 10573 if (ISA == 'n' && UserVLEN && !llvm::isPowerOf2_32(UserVLEN)) { 10574 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10575 DiagnosticsEngine::Warning, "The value specified in simdlen must be a " 10576 "power of 2 when targeting Advanced SIMD."); 10577 CGM.getDiags().Report(SLoc, DiagID); 10578 return; 10579 } 10580 10581 // 3. Section 3.4.1. SVE fixed lengh must obey the architectural 10582 // limits. 10583 if (ISA == 's' && UserVLEN != 0) { 10584 if ((UserVLEN * WDS > 2048) || (UserVLEN * WDS % 128 != 0)) { 10585 unsigned DiagID = CGM.getDiags().getCustomDiagID( 10586 DiagnosticsEngine::Warning, "The clause simdlen must fit the %0-bit " 10587 "lanes in the architectural constraints " 10588 "for SVE (min is 128-bit, max is " 10589 "2048-bit, by steps of 128-bit)"); 10590 CGM.getDiags().Report(SLoc, DiagID) << WDS; 10591 return; 10592 } 10593 } 10594 10595 // Sort out parameter sequence. 10596 const std::string ParSeq = mangleVectorParameters(ParamAttrs); 10597 StringRef Prefix = "_ZGV"; 10598 // Generate simdlen from user input (if any). 10599 if (UserVLEN) { 10600 if (ISA == 's') { 10601 // SVE generates only a masked function. 10602 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10603 OutputBecomesInput, Fn); 10604 } else { 10605 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10606 // Advanced SIMD generates one or two functions, depending on 10607 // the `[not]inbranch` clause. 10608 switch (State) { 10609 case OMPDeclareSimdDeclAttr::BS_Undefined: 10610 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10611 OutputBecomesInput, Fn); 10612 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10613 OutputBecomesInput, Fn); 10614 break; 10615 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10616 addAArch64VectorName(UserVLEN, "N", Prefix, ISA, ParSeq, MangledName, 10617 OutputBecomesInput, Fn); 10618 break; 10619 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10620 addAArch64VectorName(UserVLEN, "M", Prefix, ISA, ParSeq, MangledName, 10621 OutputBecomesInput, Fn); 10622 break; 10623 } 10624 } 10625 } else { 10626 // If no user simdlen is provided, follow the AAVFABI rules for 10627 // generating the vector length. 10628 if (ISA == 's') { 10629 // SVE, section 3.4.1, item 1. 10630 addAArch64VectorName("x", "M", Prefix, ISA, ParSeq, MangledName, 10631 OutputBecomesInput, Fn); 10632 } else { 10633 assert(ISA == 'n' && "Expected ISA either 's' or 'n'."); 10634 // Advanced SIMD, Section 3.3.1 of the AAVFABI, generates one or 10635 // two vector names depending on the use of the clause 10636 // `[not]inbranch`. 10637 switch (State) { 10638 case OMPDeclareSimdDeclAttr::BS_Undefined: 10639 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10640 OutputBecomesInput, Fn); 10641 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10642 OutputBecomesInput, Fn); 10643 break; 10644 case OMPDeclareSimdDeclAttr::BS_Notinbranch: 10645 addAArch64AdvSIMDNDSNames(NDS, "N", Prefix, ISA, ParSeq, MangledName, 10646 OutputBecomesInput, Fn); 10647 break; 10648 case OMPDeclareSimdDeclAttr::BS_Inbranch: 10649 addAArch64AdvSIMDNDSNames(NDS, "M", Prefix, ISA, ParSeq, MangledName, 10650 OutputBecomesInput, Fn); 10651 break; 10652 } 10653 } 10654 } 10655 } 10656 10657 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD, 10658 llvm::Function *Fn) { 10659 ASTContext &C = CGM.getContext(); 10660 FD = FD->getMostRecentDecl(); 10661 // Map params to their positions in function decl. 10662 llvm::DenseMap<const Decl *, unsigned> ParamPositions; 10663 if (isa<CXXMethodDecl>(FD)) 10664 ParamPositions.try_emplace(FD, 0); 10665 unsigned ParamPos = ParamPositions.size(); 10666 for (const ParmVarDecl *P : FD->parameters()) { 10667 ParamPositions.try_emplace(P->getCanonicalDecl(), ParamPos); 10668 ++ParamPos; 10669 } 10670 while (FD) { 10671 for (const auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) { 10672 llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size()); 10673 // Mark uniform parameters. 10674 for (const Expr *E : Attr->uniforms()) { 10675 E = E->IgnoreParenImpCasts(); 10676 unsigned Pos; 10677 if (isa<CXXThisExpr>(E)) { 10678 Pos = ParamPositions[FD]; 10679 } else { 10680 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10681 ->getCanonicalDecl(); 10682 Pos = ParamPositions[PVD]; 10683 } 10684 ParamAttrs[Pos].Kind = Uniform; 10685 } 10686 // Get alignment info. 10687 auto NI = Attr->alignments_begin(); 10688 for (const Expr *E : Attr->aligneds()) { 10689 E = E->IgnoreParenImpCasts(); 10690 unsigned Pos; 10691 QualType ParmTy; 10692 if (isa<CXXThisExpr>(E)) { 10693 Pos = ParamPositions[FD]; 10694 ParmTy = E->getType(); 10695 } else { 10696 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10697 ->getCanonicalDecl(); 10698 Pos = ParamPositions[PVD]; 10699 ParmTy = PVD->getType(); 10700 } 10701 ParamAttrs[Pos].Alignment = 10702 (*NI) 10703 ? (*NI)->EvaluateKnownConstInt(C) 10704 : llvm::APSInt::getUnsigned( 10705 C.toCharUnitsFromBits(C.getOpenMPDefaultSimdAlign(ParmTy)) 10706 .getQuantity()); 10707 ++NI; 10708 } 10709 // Mark linear parameters. 10710 auto SI = Attr->steps_begin(); 10711 auto MI = Attr->modifiers_begin(); 10712 for (const Expr *E : Attr->linears()) { 10713 E = E->IgnoreParenImpCasts(); 10714 unsigned Pos; 10715 if (isa<CXXThisExpr>(E)) { 10716 Pos = ParamPositions[FD]; 10717 } else { 10718 const auto *PVD = cast<ParmVarDecl>(cast<DeclRefExpr>(E)->getDecl()) 10719 ->getCanonicalDecl(); 10720 Pos = ParamPositions[PVD]; 10721 } 10722 ParamAttrTy &ParamAttr = ParamAttrs[Pos]; 10723 ParamAttr.Kind = Linear; 10724 if (*SI) { 10725 Expr::EvalResult Result; 10726 if (!(*SI)->EvaluateAsInt(Result, C, Expr::SE_AllowSideEffects)) { 10727 if (const auto *DRE = 10728 cast<DeclRefExpr>((*SI)->IgnoreParenImpCasts())) { 10729 if (const auto *StridePVD = cast<ParmVarDecl>(DRE->getDecl())) { 10730 ParamAttr.Kind = LinearWithVarStride; 10731 ParamAttr.StrideOrArg = llvm::APSInt::getUnsigned( 10732 ParamPositions[StridePVD->getCanonicalDecl()]); 10733 } 10734 } 10735 } else { 10736 ParamAttr.StrideOrArg = Result.Val.getInt(); 10737 } 10738 } 10739 ++SI; 10740 ++MI; 10741 } 10742 llvm::APSInt VLENVal; 10743 SourceLocation ExprLoc; 10744 const Expr *VLENExpr = Attr->getSimdlen(); 10745 if (VLENExpr) { 10746 VLENVal = VLENExpr->EvaluateKnownConstInt(C); 10747 ExprLoc = VLENExpr->getExprLoc(); 10748 } 10749 OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState(); 10750 if (CGM.getTriple().getArch() == llvm::Triple::x86 || 10751 CGM.getTriple().getArch() == llvm::Triple::x86_64) { 10752 emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State); 10753 } else if (CGM.getTriple().getArch() == llvm::Triple::aarch64) { 10754 unsigned VLEN = VLENVal.getExtValue(); 10755 StringRef MangledName = Fn->getName(); 10756 if (CGM.getTarget().hasFeature("sve")) 10757 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10758 MangledName, 's', 128, Fn, ExprLoc); 10759 if (CGM.getTarget().hasFeature("neon")) 10760 emitAArch64DeclareSimdFunction(CGM, FD, VLEN, ParamAttrs, State, 10761 MangledName, 'n', 128, Fn, ExprLoc); 10762 } 10763 } 10764 FD = FD->getPreviousDecl(); 10765 } 10766 } 10767 10768 namespace { 10769 /// Cleanup action for doacross support. 10770 class DoacrossCleanupTy final : public EHScopeStack::Cleanup { 10771 public: 10772 static const int DoacrossFinArgs = 2; 10773 10774 private: 10775 llvm::FunctionCallee RTLFn; 10776 llvm::Value *Args[DoacrossFinArgs]; 10777 10778 public: 10779 DoacrossCleanupTy(llvm::FunctionCallee RTLFn, 10780 ArrayRef<llvm::Value *> CallArgs) 10781 : RTLFn(RTLFn) { 10782 assert(CallArgs.size() == DoacrossFinArgs); 10783 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10784 } 10785 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10786 if (!CGF.HaveInsertPoint()) 10787 return; 10788 CGF.EmitRuntimeCall(RTLFn, Args); 10789 } 10790 }; 10791 } // namespace 10792 10793 void CGOpenMPRuntime::emitDoacrossInit(CodeGenFunction &CGF, 10794 const OMPLoopDirective &D, 10795 ArrayRef<Expr *> NumIterations) { 10796 if (!CGF.HaveInsertPoint()) 10797 return; 10798 10799 ASTContext &C = CGM.getContext(); 10800 QualType Int64Ty = C.getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/true); 10801 RecordDecl *RD; 10802 if (KmpDimTy.isNull()) { 10803 // Build struct kmp_dim { // loop bounds info casted to kmp_int64 10804 // kmp_int64 lo; // lower 10805 // kmp_int64 up; // upper 10806 // kmp_int64 st; // stride 10807 // }; 10808 RD = C.buildImplicitRecord("kmp_dim"); 10809 RD->startDefinition(); 10810 addFieldToRecordDecl(C, RD, Int64Ty); 10811 addFieldToRecordDecl(C, RD, Int64Ty); 10812 addFieldToRecordDecl(C, RD, Int64Ty); 10813 RD->completeDefinition(); 10814 KmpDimTy = C.getRecordType(RD); 10815 } else { 10816 RD = cast<RecordDecl>(KmpDimTy->getAsTagDecl()); 10817 } 10818 llvm::APInt Size(/*numBits=*/32, NumIterations.size()); 10819 QualType ArrayTy = 10820 C.getConstantArrayType(KmpDimTy, Size, nullptr, ArrayType::Normal, 0); 10821 10822 Address DimsAddr = CGF.CreateMemTemp(ArrayTy, "dims"); 10823 CGF.EmitNullInitialization(DimsAddr, ArrayTy); 10824 enum { LowerFD = 0, UpperFD, StrideFD }; 10825 // Fill dims with data. 10826 for (unsigned I = 0, E = NumIterations.size(); I < E; ++I) { 10827 LValue DimsLVal = CGF.MakeAddrLValue( 10828 CGF.Builder.CreateConstArrayGEP(DimsAddr, I), KmpDimTy); 10829 // dims.upper = num_iterations; 10830 LValue UpperLVal = CGF.EmitLValueForField( 10831 DimsLVal, *std::next(RD->field_begin(), UpperFD)); 10832 llvm::Value *NumIterVal = 10833 CGF.EmitScalarConversion(CGF.EmitScalarExpr(NumIterations[I]), 10834 D.getNumIterations()->getType(), Int64Ty, 10835 D.getNumIterations()->getExprLoc()); 10836 CGF.EmitStoreOfScalar(NumIterVal, UpperLVal); 10837 // dims.stride = 1; 10838 LValue StrideLVal = CGF.EmitLValueForField( 10839 DimsLVal, *std::next(RD->field_begin(), StrideFD)); 10840 CGF.EmitStoreOfScalar(llvm::ConstantInt::getSigned(CGM.Int64Ty, /*V=*/1), 10841 StrideLVal); 10842 } 10843 10844 // Build call void __kmpc_doacross_init(ident_t *loc, kmp_int32 gtid, 10845 // kmp_int32 num_dims, struct kmp_dim * dims); 10846 llvm::Value *Args[] = { 10847 emitUpdateLocation(CGF, D.getBeginLoc()), 10848 getThreadID(CGF, D.getBeginLoc()), 10849 llvm::ConstantInt::getSigned(CGM.Int32Ty, NumIterations.size()), 10850 CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 10851 CGF.Builder.CreateConstArrayGEP(DimsAddr, 0).getPointer(), 10852 CGM.VoidPtrTy)}; 10853 10854 llvm::FunctionCallee RTLFn = 10855 createRuntimeFunction(OMPRTL__kmpc_doacross_init); 10856 CGF.EmitRuntimeCall(RTLFn, Args); 10857 llvm::Value *FiniArgs[DoacrossCleanupTy::DoacrossFinArgs] = { 10858 emitUpdateLocation(CGF, D.getEndLoc()), getThreadID(CGF, D.getEndLoc())}; 10859 llvm::FunctionCallee FiniRTLFn = 10860 createRuntimeFunction(OMPRTL__kmpc_doacross_fini); 10861 CGF.EHStack.pushCleanup<DoacrossCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 10862 llvm::makeArrayRef(FiniArgs)); 10863 } 10864 10865 void CGOpenMPRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 10866 const OMPDependClause *C) { 10867 QualType Int64Ty = 10868 CGM.getContext().getIntTypeForBitwidth(/*DestWidth=*/64, /*Signed=*/1); 10869 llvm::APInt Size(/*numBits=*/32, C->getNumLoops()); 10870 QualType ArrayTy = CGM.getContext().getConstantArrayType( 10871 Int64Ty, Size, nullptr, ArrayType::Normal, 0); 10872 Address CntAddr = CGF.CreateMemTemp(ArrayTy, ".cnt.addr"); 10873 for (unsigned I = 0, E = C->getNumLoops(); I < E; ++I) { 10874 const Expr *CounterVal = C->getLoopData(I); 10875 assert(CounterVal); 10876 llvm::Value *CntVal = CGF.EmitScalarConversion( 10877 CGF.EmitScalarExpr(CounterVal), CounterVal->getType(), Int64Ty, 10878 CounterVal->getExprLoc()); 10879 CGF.EmitStoreOfScalar(CntVal, CGF.Builder.CreateConstArrayGEP(CntAddr, I), 10880 /*Volatile=*/false, Int64Ty); 10881 } 10882 llvm::Value *Args[] = { 10883 emitUpdateLocation(CGF, C->getBeginLoc()), 10884 getThreadID(CGF, C->getBeginLoc()), 10885 CGF.Builder.CreateConstArrayGEP(CntAddr, 0).getPointer()}; 10886 llvm::FunctionCallee RTLFn; 10887 if (C->getDependencyKind() == OMPC_DEPEND_source) { 10888 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_post); 10889 } else { 10890 assert(C->getDependencyKind() == OMPC_DEPEND_sink); 10891 RTLFn = createRuntimeFunction(OMPRTL__kmpc_doacross_wait); 10892 } 10893 CGF.EmitRuntimeCall(RTLFn, Args); 10894 } 10895 10896 void CGOpenMPRuntime::emitCall(CodeGenFunction &CGF, SourceLocation Loc, 10897 llvm::FunctionCallee Callee, 10898 ArrayRef<llvm::Value *> Args) const { 10899 assert(Loc.isValid() && "Outlined function call location must be valid."); 10900 auto DL = ApplyDebugLocation::CreateDefaultArtificial(CGF, Loc); 10901 10902 if (auto *Fn = dyn_cast<llvm::Function>(Callee.getCallee())) { 10903 if (Fn->doesNotThrow()) { 10904 CGF.EmitNounwindRuntimeCall(Fn, Args); 10905 return; 10906 } 10907 } 10908 CGF.EmitRuntimeCall(Callee, Args); 10909 } 10910 10911 void CGOpenMPRuntime::emitOutlinedFunctionCall( 10912 CodeGenFunction &CGF, SourceLocation Loc, llvm::FunctionCallee OutlinedFn, 10913 ArrayRef<llvm::Value *> Args) const { 10914 emitCall(CGF, Loc, OutlinedFn, Args); 10915 } 10916 10917 void CGOpenMPRuntime::emitFunctionProlog(CodeGenFunction &CGF, const Decl *D) { 10918 if (const auto *FD = dyn_cast<FunctionDecl>(D)) 10919 if (OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD)) 10920 HasEmittedDeclareTargetRegion = true; 10921 } 10922 10923 Address CGOpenMPRuntime::getParameterAddress(CodeGenFunction &CGF, 10924 const VarDecl *NativeParam, 10925 const VarDecl *TargetParam) const { 10926 return CGF.GetAddrOfLocalVar(NativeParam); 10927 } 10928 10929 namespace { 10930 /// Cleanup action for allocate support. 10931 class OMPAllocateCleanupTy final : public EHScopeStack::Cleanup { 10932 public: 10933 static const int CleanupArgs = 3; 10934 10935 private: 10936 llvm::FunctionCallee RTLFn; 10937 llvm::Value *Args[CleanupArgs]; 10938 10939 public: 10940 OMPAllocateCleanupTy(llvm::FunctionCallee RTLFn, 10941 ArrayRef<llvm::Value *> CallArgs) 10942 : RTLFn(RTLFn) { 10943 assert(CallArgs.size() == CleanupArgs && 10944 "Size of arguments does not match."); 10945 std::copy(CallArgs.begin(), CallArgs.end(), std::begin(Args)); 10946 } 10947 void Emit(CodeGenFunction &CGF, Flags /*flags*/) override { 10948 if (!CGF.HaveInsertPoint()) 10949 return; 10950 CGF.EmitRuntimeCall(RTLFn, Args); 10951 } 10952 }; 10953 } // namespace 10954 10955 Address CGOpenMPRuntime::getAddressOfLocalVariable(CodeGenFunction &CGF, 10956 const VarDecl *VD) { 10957 if (!VD) 10958 return Address::invalid(); 10959 const VarDecl *CVD = VD->getCanonicalDecl(); 10960 if (!CVD->hasAttr<OMPAllocateDeclAttr>()) 10961 return Address::invalid(); 10962 const auto *AA = CVD->getAttr<OMPAllocateDeclAttr>(); 10963 // Use the default allocation. 10964 if (AA->getAllocatorType() == OMPAllocateDeclAttr::OMPDefaultMemAlloc && 10965 !AA->getAllocator()) 10966 return Address::invalid(); 10967 llvm::Value *Size; 10968 CharUnits Align = CGM.getContext().getDeclAlign(CVD); 10969 if (CVD->getType()->isVariablyModifiedType()) { 10970 Size = CGF.getTypeSize(CVD->getType()); 10971 // Align the size: ((size + align - 1) / align) * align 10972 Size = CGF.Builder.CreateNUWAdd( 10973 Size, CGM.getSize(Align - CharUnits::fromQuantity(1))); 10974 Size = CGF.Builder.CreateUDiv(Size, CGM.getSize(Align)); 10975 Size = CGF.Builder.CreateNUWMul(Size, CGM.getSize(Align)); 10976 } else { 10977 CharUnits Sz = CGM.getContext().getTypeSizeInChars(CVD->getType()); 10978 Size = CGM.getSize(Sz.alignTo(Align)); 10979 } 10980 llvm::Value *ThreadID = getThreadID(CGF, CVD->getBeginLoc()); 10981 assert(AA->getAllocator() && 10982 "Expected allocator expression for non-default allocator."); 10983 llvm::Value *Allocator = CGF.EmitScalarExpr(AA->getAllocator()); 10984 // According to the standard, the original allocator type is a enum (integer). 10985 // Convert to pointer type, if required. 10986 if (Allocator->getType()->isIntegerTy()) 10987 Allocator = CGF.Builder.CreateIntToPtr(Allocator, CGM.VoidPtrTy); 10988 else if (Allocator->getType()->isPointerTy()) 10989 Allocator = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast(Allocator, 10990 CGM.VoidPtrTy); 10991 llvm::Value *Args[] = {ThreadID, Size, Allocator}; 10992 10993 llvm::Value *Addr = 10994 CGF.EmitRuntimeCall(createRuntimeFunction(OMPRTL__kmpc_alloc), Args, 10995 CVD->getName() + ".void.addr"); 10996 llvm::Value *FiniArgs[OMPAllocateCleanupTy::CleanupArgs] = {ThreadID, Addr, 10997 Allocator}; 10998 llvm::FunctionCallee FiniRTLFn = createRuntimeFunction(OMPRTL__kmpc_free); 10999 11000 CGF.EHStack.pushCleanup<OMPAllocateCleanupTy>(NormalAndEHCleanup, FiniRTLFn, 11001 llvm::makeArrayRef(FiniArgs)); 11002 Addr = CGF.Builder.CreatePointerBitCastOrAddrSpaceCast( 11003 Addr, 11004 CGF.ConvertTypeForMem(CGM.getContext().getPointerType(CVD->getType())), 11005 CVD->getName() + ".addr"); 11006 return Address(Addr, Align); 11007 } 11008 11009 /// Checks current context and returns true if it matches the context selector. 11010 template <OMPDeclareVariantAttr::CtxSelectorSetType CtxSet, 11011 OMPDeclareVariantAttr::CtxSelectorType Ctx> 11012 static bool checkContext(const OMPDeclareVariantAttr *A) { 11013 assert(CtxSet != OMPDeclareVariantAttr::CtxSetUnknown && 11014 Ctx != OMPDeclareVariantAttr::CtxUnknown && 11015 "Unknown context selector or context selector set."); 11016 return false; 11017 } 11018 11019 /// Checks for implementation={vendor(<vendor>)} context selector. 11020 /// \returns true iff <vendor>="llvm", false otherwise. 11021 template <> 11022 bool checkContext<OMPDeclareVariantAttr::CtxSetImplementation, 11023 OMPDeclareVariantAttr::CtxVendor>( 11024 const OMPDeclareVariantAttr *A) { 11025 return llvm::all_of(A->implVendors(), 11026 [](StringRef S) { return !S.compare_lower("llvm"); }); 11027 } 11028 11029 static bool greaterCtxScore(ASTContext &Ctx, const Expr *LHS, const Expr *RHS) { 11030 // If both scores are unknown, choose the very first one. 11031 if (!LHS && !RHS) 11032 return true; 11033 // If only one is known, return this one. 11034 if (LHS && !RHS) 11035 return true; 11036 if (!LHS && RHS) 11037 return false; 11038 llvm::APSInt LHSVal = LHS->EvaluateKnownConstInt(Ctx); 11039 llvm::APSInt RHSVal = RHS->EvaluateKnownConstInt(Ctx); 11040 return llvm::APSInt::compareValues(LHSVal, RHSVal) >= 0; 11041 } 11042 11043 namespace { 11044 /// Comparator for the priority queue for context selector. 11045 class OMPDeclareVariantAttrComparer 11046 : public std::greater<const OMPDeclareVariantAttr *> { 11047 private: 11048 ASTContext &Ctx; 11049 11050 public: 11051 OMPDeclareVariantAttrComparer(ASTContext &Ctx) : Ctx(Ctx) {} 11052 bool operator()(const OMPDeclareVariantAttr *LHS, 11053 const OMPDeclareVariantAttr *RHS) const { 11054 const Expr *LHSExpr = nullptr; 11055 const Expr *RHSExpr = nullptr; 11056 if (LHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified) 11057 LHSExpr = LHS->getScore(); 11058 if (RHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified) 11059 RHSExpr = RHS->getScore(); 11060 return greaterCtxScore(Ctx, LHSExpr, RHSExpr); 11061 } 11062 }; 11063 } // anonymous namespace 11064 11065 /// Finds the variant function that matches current context with its context 11066 /// selector. 11067 static const FunctionDecl *getDeclareVariantFunction(ASTContext &Ctx, 11068 const FunctionDecl *FD) { 11069 if (!FD->hasAttrs() || !FD->hasAttr<OMPDeclareVariantAttr>()) 11070 return FD; 11071 // Iterate through all DeclareVariant attributes and check context selectors. 11072 auto &&Comparer = [&Ctx](const OMPDeclareVariantAttr *LHS, 11073 const OMPDeclareVariantAttr *RHS) { 11074 const Expr *LHSExpr = nullptr; 11075 const Expr *RHSExpr = nullptr; 11076 if (LHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified) 11077 LHSExpr = LHS->getScore(); 11078 if (RHS->getCtxScore() == OMPDeclareVariantAttr::ScoreSpecified) 11079 RHSExpr = RHS->getScore(); 11080 return greaterCtxScore(Ctx, LHSExpr, RHSExpr); 11081 }; 11082 const OMPDeclareVariantAttr *TopMostAttr = nullptr; 11083 for (const auto *A : FD->specific_attrs<OMPDeclareVariantAttr>()) { 11084 const OMPDeclareVariantAttr *SelectedAttr = nullptr; 11085 switch (A->getCtxSelectorSet()) { 11086 case OMPDeclareVariantAttr::CtxSetImplementation: 11087 switch (A->getCtxSelector()) { 11088 case OMPDeclareVariantAttr::CtxVendor: 11089 if (checkContext<OMPDeclareVariantAttr::CtxSetImplementation, 11090 OMPDeclareVariantAttr::CtxVendor>(A)) 11091 SelectedAttr = A; 11092 break; 11093 case OMPDeclareVariantAttr::CtxUnknown: 11094 llvm_unreachable( 11095 "Unknown context selector in implementation selector set."); 11096 } 11097 break; 11098 case OMPDeclareVariantAttr::CtxSetUnknown: 11099 llvm_unreachable("Unknown context selector set."); 11100 } 11101 // If the attribute matches the context, find the attribute with the highest 11102 // score. 11103 if (SelectedAttr && (!TopMostAttr || !Comparer(TopMostAttr, SelectedAttr))) 11104 TopMostAttr = SelectedAttr; 11105 } 11106 if (!TopMostAttr) 11107 return FD; 11108 return cast<FunctionDecl>( 11109 cast<DeclRefExpr>(TopMostAttr->getVariantFuncRef()->IgnoreParenImpCasts()) 11110 ->getDecl()); 11111 } 11112 11113 bool CGOpenMPRuntime::emitDeclareVariant(GlobalDecl GD, bool IsForDefinition) { 11114 const auto *D = cast<FunctionDecl>(GD.getDecl()); 11115 // If the original function is defined already, use its definition. 11116 StringRef MangledName = CGM.getMangledName(GD); 11117 llvm::GlobalValue *Orig = CGM.GetGlobalValue(MangledName); 11118 if (Orig && !Orig->isDeclaration()) 11119 return false; 11120 const FunctionDecl *NewFD = getDeclareVariantFunction(CGM.getContext(), D); 11121 // Emit original function if it does not have declare variant attribute or the 11122 // context does not match. 11123 if (NewFD == D) 11124 return false; 11125 GlobalDecl NewGD = GD.getWithDecl(NewFD); 11126 if (tryEmitDeclareVariant(NewGD, GD, Orig, IsForDefinition)) { 11127 DeferredVariantFunction.erase(D); 11128 return true; 11129 } 11130 DeferredVariantFunction.insert(std::make_pair(D, std::make_pair(NewGD, GD))); 11131 return true; 11132 } 11133 11134 llvm::Function *CGOpenMPSIMDRuntime::emitParallelOutlinedFunction( 11135 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11136 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11137 llvm_unreachable("Not supported in SIMD-only mode"); 11138 } 11139 11140 llvm::Function *CGOpenMPSIMDRuntime::emitTeamsOutlinedFunction( 11141 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11142 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen) { 11143 llvm_unreachable("Not supported in SIMD-only mode"); 11144 } 11145 11146 llvm::Function *CGOpenMPSIMDRuntime::emitTaskOutlinedFunction( 11147 const OMPExecutableDirective &D, const VarDecl *ThreadIDVar, 11148 const VarDecl *PartIDVar, const VarDecl *TaskTVar, 11149 OpenMPDirectiveKind InnermostKind, const RegionCodeGenTy &CodeGen, 11150 bool Tied, unsigned &NumberOfParts) { 11151 llvm_unreachable("Not supported in SIMD-only mode"); 11152 } 11153 11154 void CGOpenMPSIMDRuntime::emitParallelCall(CodeGenFunction &CGF, 11155 SourceLocation Loc, 11156 llvm::Function *OutlinedFn, 11157 ArrayRef<llvm::Value *> CapturedVars, 11158 const Expr *IfCond) { 11159 llvm_unreachable("Not supported in SIMD-only mode"); 11160 } 11161 11162 void CGOpenMPSIMDRuntime::emitCriticalRegion( 11163 CodeGenFunction &CGF, StringRef CriticalName, 11164 const RegionCodeGenTy &CriticalOpGen, SourceLocation Loc, 11165 const Expr *Hint) { 11166 llvm_unreachable("Not supported in SIMD-only mode"); 11167 } 11168 11169 void CGOpenMPSIMDRuntime::emitMasterRegion(CodeGenFunction &CGF, 11170 const RegionCodeGenTy &MasterOpGen, 11171 SourceLocation Loc) { 11172 llvm_unreachable("Not supported in SIMD-only mode"); 11173 } 11174 11175 void CGOpenMPSIMDRuntime::emitTaskyieldCall(CodeGenFunction &CGF, 11176 SourceLocation Loc) { 11177 llvm_unreachable("Not supported in SIMD-only mode"); 11178 } 11179 11180 void CGOpenMPSIMDRuntime::emitTaskgroupRegion( 11181 CodeGenFunction &CGF, const RegionCodeGenTy &TaskgroupOpGen, 11182 SourceLocation Loc) { 11183 llvm_unreachable("Not supported in SIMD-only mode"); 11184 } 11185 11186 void CGOpenMPSIMDRuntime::emitSingleRegion( 11187 CodeGenFunction &CGF, const RegionCodeGenTy &SingleOpGen, 11188 SourceLocation Loc, ArrayRef<const Expr *> CopyprivateVars, 11189 ArrayRef<const Expr *> DestExprs, ArrayRef<const Expr *> SrcExprs, 11190 ArrayRef<const Expr *> AssignmentOps) { 11191 llvm_unreachable("Not supported in SIMD-only mode"); 11192 } 11193 11194 void CGOpenMPSIMDRuntime::emitOrderedRegion(CodeGenFunction &CGF, 11195 const RegionCodeGenTy &OrderedOpGen, 11196 SourceLocation Loc, 11197 bool IsThreads) { 11198 llvm_unreachable("Not supported in SIMD-only mode"); 11199 } 11200 11201 void CGOpenMPSIMDRuntime::emitBarrierCall(CodeGenFunction &CGF, 11202 SourceLocation Loc, 11203 OpenMPDirectiveKind Kind, 11204 bool EmitChecks, 11205 bool ForceSimpleCall) { 11206 llvm_unreachable("Not supported in SIMD-only mode"); 11207 } 11208 11209 void CGOpenMPSIMDRuntime::emitForDispatchInit( 11210 CodeGenFunction &CGF, SourceLocation Loc, 11211 const OpenMPScheduleTy &ScheduleKind, unsigned IVSize, bool IVSigned, 11212 bool Ordered, const DispatchRTInput &DispatchValues) { 11213 llvm_unreachable("Not supported in SIMD-only mode"); 11214 } 11215 11216 void CGOpenMPSIMDRuntime::emitForStaticInit( 11217 CodeGenFunction &CGF, SourceLocation Loc, OpenMPDirectiveKind DKind, 11218 const OpenMPScheduleTy &ScheduleKind, const StaticRTInput &Values) { 11219 llvm_unreachable("Not supported in SIMD-only mode"); 11220 } 11221 11222 void CGOpenMPSIMDRuntime::emitDistributeStaticInit( 11223 CodeGenFunction &CGF, SourceLocation Loc, 11224 OpenMPDistScheduleClauseKind SchedKind, const StaticRTInput &Values) { 11225 llvm_unreachable("Not supported in SIMD-only mode"); 11226 } 11227 11228 void CGOpenMPSIMDRuntime::emitForOrderedIterationEnd(CodeGenFunction &CGF, 11229 SourceLocation Loc, 11230 unsigned IVSize, 11231 bool IVSigned) { 11232 llvm_unreachable("Not supported in SIMD-only mode"); 11233 } 11234 11235 void CGOpenMPSIMDRuntime::emitForStaticFinish(CodeGenFunction &CGF, 11236 SourceLocation Loc, 11237 OpenMPDirectiveKind DKind) { 11238 llvm_unreachable("Not supported in SIMD-only mode"); 11239 } 11240 11241 llvm::Value *CGOpenMPSIMDRuntime::emitForNext(CodeGenFunction &CGF, 11242 SourceLocation Loc, 11243 unsigned IVSize, bool IVSigned, 11244 Address IL, Address LB, 11245 Address UB, Address ST) { 11246 llvm_unreachable("Not supported in SIMD-only mode"); 11247 } 11248 11249 void CGOpenMPSIMDRuntime::emitNumThreadsClause(CodeGenFunction &CGF, 11250 llvm::Value *NumThreads, 11251 SourceLocation Loc) { 11252 llvm_unreachable("Not supported in SIMD-only mode"); 11253 } 11254 11255 void CGOpenMPSIMDRuntime::emitProcBindClause(CodeGenFunction &CGF, 11256 OpenMPProcBindClauseKind ProcBind, 11257 SourceLocation Loc) { 11258 llvm_unreachable("Not supported in SIMD-only mode"); 11259 } 11260 11261 Address CGOpenMPSIMDRuntime::getAddrOfThreadPrivate(CodeGenFunction &CGF, 11262 const VarDecl *VD, 11263 Address VDAddr, 11264 SourceLocation Loc) { 11265 llvm_unreachable("Not supported in SIMD-only mode"); 11266 } 11267 11268 llvm::Function *CGOpenMPSIMDRuntime::emitThreadPrivateVarDefinition( 11269 const VarDecl *VD, Address VDAddr, SourceLocation Loc, bool PerformInit, 11270 CodeGenFunction *CGF) { 11271 llvm_unreachable("Not supported in SIMD-only mode"); 11272 } 11273 11274 Address CGOpenMPSIMDRuntime::getAddrOfArtificialThreadPrivate( 11275 CodeGenFunction &CGF, QualType VarType, StringRef Name) { 11276 llvm_unreachable("Not supported in SIMD-only mode"); 11277 } 11278 11279 void CGOpenMPSIMDRuntime::emitFlush(CodeGenFunction &CGF, 11280 ArrayRef<const Expr *> Vars, 11281 SourceLocation Loc) { 11282 llvm_unreachable("Not supported in SIMD-only mode"); 11283 } 11284 11285 void CGOpenMPSIMDRuntime::emitTaskCall(CodeGenFunction &CGF, SourceLocation Loc, 11286 const OMPExecutableDirective &D, 11287 llvm::Function *TaskFunction, 11288 QualType SharedsTy, Address Shareds, 11289 const Expr *IfCond, 11290 const OMPTaskDataTy &Data) { 11291 llvm_unreachable("Not supported in SIMD-only mode"); 11292 } 11293 11294 void CGOpenMPSIMDRuntime::emitTaskLoopCall( 11295 CodeGenFunction &CGF, SourceLocation Loc, const OMPLoopDirective &D, 11296 llvm::Function *TaskFunction, QualType SharedsTy, Address Shareds, 11297 const Expr *IfCond, const OMPTaskDataTy &Data) { 11298 llvm_unreachable("Not supported in SIMD-only mode"); 11299 } 11300 11301 void CGOpenMPSIMDRuntime::emitReduction( 11302 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, 11303 ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, 11304 ArrayRef<const Expr *> ReductionOps, ReductionOptionsTy Options) { 11305 assert(Options.SimpleReduction && "Only simple reduction is expected."); 11306 CGOpenMPRuntime::emitReduction(CGF, Loc, Privates, LHSExprs, RHSExprs, 11307 ReductionOps, Options); 11308 } 11309 11310 llvm::Value *CGOpenMPSIMDRuntime::emitTaskReductionInit( 11311 CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> LHSExprs, 11312 ArrayRef<const Expr *> RHSExprs, const OMPTaskDataTy &Data) { 11313 llvm_unreachable("Not supported in SIMD-only mode"); 11314 } 11315 11316 void CGOpenMPSIMDRuntime::emitTaskReductionFixups(CodeGenFunction &CGF, 11317 SourceLocation Loc, 11318 ReductionCodeGen &RCG, 11319 unsigned N) { 11320 llvm_unreachable("Not supported in SIMD-only mode"); 11321 } 11322 11323 Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF, 11324 SourceLocation Loc, 11325 llvm::Value *ReductionsPtr, 11326 LValue SharedLVal) { 11327 llvm_unreachable("Not supported in SIMD-only mode"); 11328 } 11329 11330 void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF, 11331 SourceLocation Loc) { 11332 llvm_unreachable("Not supported in SIMD-only mode"); 11333 } 11334 11335 void CGOpenMPSIMDRuntime::emitCancellationPointCall( 11336 CodeGenFunction &CGF, SourceLocation Loc, 11337 OpenMPDirectiveKind CancelRegion) { 11338 llvm_unreachable("Not supported in SIMD-only mode"); 11339 } 11340 11341 void CGOpenMPSIMDRuntime::emitCancelCall(CodeGenFunction &CGF, 11342 SourceLocation Loc, const Expr *IfCond, 11343 OpenMPDirectiveKind CancelRegion) { 11344 llvm_unreachable("Not supported in SIMD-only mode"); 11345 } 11346 11347 void CGOpenMPSIMDRuntime::emitTargetOutlinedFunction( 11348 const OMPExecutableDirective &D, StringRef ParentName, 11349 llvm::Function *&OutlinedFn, llvm::Constant *&OutlinedFnID, 11350 bool IsOffloadEntry, const RegionCodeGenTy &CodeGen) { 11351 llvm_unreachable("Not supported in SIMD-only mode"); 11352 } 11353 11354 void CGOpenMPSIMDRuntime::emitTargetCall( 11355 CodeGenFunction &CGF, const OMPExecutableDirective &D, 11356 llvm::Function *OutlinedFn, llvm::Value *OutlinedFnID, const Expr *IfCond, 11357 const Expr *Device, 11358 llvm::function_ref<llvm::Value *(CodeGenFunction &CGF, 11359 const OMPLoopDirective &D)> 11360 SizeEmitter) { 11361 llvm_unreachable("Not supported in SIMD-only mode"); 11362 } 11363 11364 bool CGOpenMPSIMDRuntime::emitTargetFunctions(GlobalDecl GD) { 11365 llvm_unreachable("Not supported in SIMD-only mode"); 11366 } 11367 11368 bool CGOpenMPSIMDRuntime::emitTargetGlobalVariable(GlobalDecl GD) { 11369 llvm_unreachable("Not supported in SIMD-only mode"); 11370 } 11371 11372 bool CGOpenMPSIMDRuntime::emitTargetGlobal(GlobalDecl GD) { 11373 return false; 11374 } 11375 11376 void CGOpenMPSIMDRuntime::emitTeamsCall(CodeGenFunction &CGF, 11377 const OMPExecutableDirective &D, 11378 SourceLocation Loc, 11379 llvm::Function *OutlinedFn, 11380 ArrayRef<llvm::Value *> CapturedVars) { 11381 llvm_unreachable("Not supported in SIMD-only mode"); 11382 } 11383 11384 void CGOpenMPSIMDRuntime::emitNumTeamsClause(CodeGenFunction &CGF, 11385 const Expr *NumTeams, 11386 const Expr *ThreadLimit, 11387 SourceLocation Loc) { 11388 llvm_unreachable("Not supported in SIMD-only mode"); 11389 } 11390 11391 void CGOpenMPSIMDRuntime::emitTargetDataCalls( 11392 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11393 const Expr *Device, const RegionCodeGenTy &CodeGen, TargetDataInfo &Info) { 11394 llvm_unreachable("Not supported in SIMD-only mode"); 11395 } 11396 11397 void CGOpenMPSIMDRuntime::emitTargetDataStandAloneCall( 11398 CodeGenFunction &CGF, const OMPExecutableDirective &D, const Expr *IfCond, 11399 const Expr *Device) { 11400 llvm_unreachable("Not supported in SIMD-only mode"); 11401 } 11402 11403 void CGOpenMPSIMDRuntime::emitDoacrossInit(CodeGenFunction &CGF, 11404 const OMPLoopDirective &D, 11405 ArrayRef<Expr *> NumIterations) { 11406 llvm_unreachable("Not supported in SIMD-only mode"); 11407 } 11408 11409 void CGOpenMPSIMDRuntime::emitDoacrossOrdered(CodeGenFunction &CGF, 11410 const OMPDependClause *C) { 11411 llvm_unreachable("Not supported in SIMD-only mode"); 11412 } 11413 11414 const VarDecl * 11415 CGOpenMPSIMDRuntime::translateParameter(const FieldDecl *FD, 11416 const VarDecl *NativeParam) const { 11417 llvm_unreachable("Not supported in SIMD-only mode"); 11418 } 11419 11420 Address 11421 CGOpenMPSIMDRuntime::getParameterAddress(CodeGenFunction &CGF, 11422 const VarDecl *NativeParam, 11423 const VarDecl *TargetParam) const { 11424 llvm_unreachable("Not supported in SIMD-only mode"); 11425 } 11426